refactor(lang): rename builtins flr->floor and fx->fixed

De-abbreviate the two bare fixed-point conversion builtins:
  flr(f) -> int     ->  floor(f) -> int    (fixed -> int, flooring)
  fx(i)  -> fixed   ->  fixed(i) -> fixed  (int -> fixed; mirrors how the
                                            stringify builtin is `string`)

Updates the compiler dispatch, all call sites, the grammars/LSP/JetBrains
tokens, and the docs (fn-flr -> fn-floor, fn-fx -> fn-fixed). Reseeded;
C-free fixpoint holds; all suites green (45/24/29); site + check.py OK.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-08-30 02:01:56 +03:00
parent effb3f637f
commit 2e0047514b
19 changed files with 80 additions and 80 deletions

View file

@ -1,15 +1,15 @@
---
id: fn-fx
name: fx
id: fn-fixed
name: fixed
category: builtins
kind: builtin
tokens: fx
sig: fx(n) -> fixed
tokens: fixed
sig: fixed(n) -> fixed
tip: Lift an integer into a Q16.16 fixed-point value.
order: 50
---
Converts an integer into a <code>fixed</code> value (Ludic's Q16.16 fixed-point type), so it can take part in fractional arithmetic. Ludic has no floating point; <code>fixed</code> is how you carry sub-pixel precision for smooth movement and physics-like accumulation. Use <code>fx</code> when you need to combine an <code>int</code> with fixed-point values or divide to get a fraction — for example <code>fx(1) / fx(4)</code> is <code>0.25</code>. Convert back to a whole number for drawing with <code>flr</code>.
Converts an integer into a <code>fixed</code> value (Ludic's Q16.16 fixed-point type), so it can take part in fractional arithmetic. Ludic has no floating point; <code>fixed</code> is how you carry sub-pixel precision for smooth movement and physics-like accumulation. Use <code>fixed</code> when you need to combine an <code>int</code> with fixed-point values or divide to get a fraction — for example <code>fixed(1) / fixed(4)</code> is <code>0.25</code>. Convert back to a whole number for drawing with <code>flr</code>.
Parameters:
- `n` — the integer to lift into fixed-point
@ -17,10 +17,10 @@ Parameters:
```ludic
program SmoothAccumulate {
handler ComputeStep phase Start {
let full_speed = fx(3)
let half_speed = full_speed / fx(2)
let full_speed = fixed(3)
let half_speed = full_speed / fixed(2)
let two_steps = half_speed + half_speed
print(flr(two_steps))
print(floor(two_steps))
}
}
```

View file

@ -1,15 +1,15 @@
---
id: fn-flr
name: flr
id: fn-floor
name: floor
category: builtins
kind: builtin
tokens: flr
sig: flr(x) -> int
tokens: floor
sig: floor(x) -> int
tip: Floor a fixed-point value down to the nearest integer.
order: 50
---
Converts a <code>fixed</code> (Q16.16) value back to an <code>int</code> by discarding the fractional part, rounding toward negative infinity. It is the counterpart to <code>fx</code>: you accumulate motion in fixed-point for sub-pixel smoothness, then <code>flr</code> the result to get the whole-pixel column or row to draw at. Because it floors rather than rounds, <code>flr(fx(3) / fx(2))</code> is <code>1</code>, not <code>2</code>. Use it wherever a fixed value must become an integer coordinate, count, or index.
Converts a <code>fixed</code> (Q16.16) value back to an <code>int</code> by discarding the fractional part, rounding toward negative infinity. It is the counterpart to <code>fx</code>: you accumulate motion in fixed-point for sub-pixel smoothness, then <code>floor</code> the result to get the whole-pixel column or row to draw at. Because it floors rather than rounds, <code>floor(fixed(3) / fixed(2))</code> is <code>1</code>, not <code>2</code>. Use it wherever a fixed value must become an integer coordinate, count, or index.
Parameters:
- `x` — the fixed-point value to floor
@ -20,8 +20,8 @@ program FixedToPixels {
handler DrawWorld phase Render {
Screen.clear(Color.MidnightBlue)
let smooth_column = fx(5) + fx(1) / fx(2)
let pixel_x = flr(smooth_column) * TILE_SIZE
let smooth_column = fixed(5) + fixed(1) / fixed(2)
let pixel_x = floor(smooth_column) * TILE_SIZE
Screen.fill_rectangle(x: pixel_x, y: 32, width: TILE_SIZE, height: TILE_SIZE, color: Color.LimeGreen)
Screen.show()
}

View file

@ -11,7 +11,7 @@ ns: Math
member: floor
---
Takes a <code>fixed</code> value and returns the largest <code>int</code> not greater than it — rounding toward negative infinity, so <code>Math.floor(2.7)</code> is <code>2</code> and <code>Math.floor(-0.2)</code> is <code>-1</code>. This is the fixed-to-int conversion you reach for when turning a smooth position into a whole tile or pixel index. It is the same operation as the bare <code>flr(x)</code>.
Takes a <code>fixed</code> value and returns the largest <code>int</code> not greater than it — rounding toward negative infinity, so <code>Math.floor(2.7)</code> is <code>2</code> and <code>Math.floor(-0.2)</code> is <code>-1</code>. This is the fixed-to-int conversion you reach for when turning a smooth position into a whole tile or pixel index. It is the same operation as the bare <code>floor(x)</code>.
Parameters:
- `x` — the `fixed` value to round down

View file

@ -23,8 +23,8 @@ program Physics {
handler MeasureSpeed phase Update {
for (velocity) in query [Velocity, {Projectile}] {
let speed = c_hypot(a: fx(velocity.delta_x), b: fx(velocity.delta_y))
Screen.status(string(flr(speed)))
let speed = c_hypot(a: fixed(velocity.delta_x), b: fixed(velocity.delta_y))
Screen.status(string(floor(speed)))
}
}
}

View file

@ -9,11 +9,11 @@ tip: Q16.16 fixed-point for deterministic fractional math — no floats.
order: 1
---
`fixed` is Q16.16 fixed-point: a fractional number stored in 32 bits, giving you decimals without floating-point. Ludic uses it precisely because it is <b>deterministic</b> — the same computation gives the same bits on every machine, which is what a reproducible simulation and lockstep networking need. A literal with a decimal point (`1.5`) is a `fixed`; arithmetic on two `fixed` values does fixed-point multiply/divide, and mixing an `int` with a `fixed` promotes the `int`. Lift an `int` in with `fx(value)` and take the floor back out with `flr(value)`.
`fixed` is Q16.16 fixed-point: a fractional number stored in 32 bits, giving you decimals without floating-point. Ludic uses it precisely because it is <b>deterministic</b> — the same computation gives the same bits on every machine, which is what a reproducible simulation and lockstep networking need. A literal with a decimal point (`1.5`) is a `fixed`; arithmetic on two `fixed` values does fixed-point multiply/divide, and mixing an `int` with a `fixed` promotes the `int`. Lift an `int` in with `fixed(value)` and take the floor back out with `floor(value)`.
```ludic
const GRAVITY: fixed = 0.5
var velocity_y: fixed = fx(0)
var velocity_y: fixed = fixed(0)
var next_velocity: fixed = velocity_y + GRAVITY
var pixel_row: int = flr(next_velocity)
var pixel_row: int = floor(next_velocity)
```

View file

@ -15,9 +15,9 @@ A <code>fixeds</code> is a raw buffer whose elements are <code>fixed</code> (Q16
program Heights {
handler Setup phase Start {
let heights: fixeds = words(4)
heights[0] = fx(2)
heights[1] = heights[0] + fx(1)
print(flr(heights[1]))
heights[0] = fixed(2)
heights[1] = heights[0] + fixed(1)
print(floor(heights[1]))
}
}
```