Types phase 5: polish — huge (idle), sized ints, angle / percent / handle / duration / rune / name #55

Closed
opened 2026-08-31 17:30:51 +02:00 by orkun · 1 comment
Owner

Follow-up to #1 (proposal), phase 5 of the phasing.

  • huge (a.k.a. bignum) — mantissa+exponent scientific number reaching ~1e9e15 (break_infinity.js), for idle/incremental display magnitudes. Display-scale, NOT lockstep-deterministic — must be its own type so it never sneaks into the sim.
  • sized / unsigned ints — u8/i16/u16/u32/i64/u64 for packing, tile ids, RGBA channels, hashes and @Sync/serialize payloads.
  • angle — an auto-wrapping fixed angle with sin/cos/rotate (avoids manual % TAU).
  • percent / normalized — a clamped [0,1] fixed for health %, volume, lerp t.
  • handle — a typed id generalising entity, so asset/entity handles can't be mixed up with a bare int.
  • duration / tick — frame/time values that don't get confused with plain ints.
  • rune / char — a Unicode code point for text handling (Go rune).
  • name — an interned string for fast id comparison by handle, not bytes (Godot StringName).

Phase 1 (IVec2 + Rect) shipped in the #1 thread.

Follow-up to #1 (proposal), phase 5 of the phasing. - **huge** (a.k.a. bignum) — mantissa+exponent scientific number reaching ~1e9e15 (break_infinity.js), for idle/incremental display magnitudes. Display-scale, NOT lockstep-deterministic — must be its own type so it never sneaks into the sim. - **sized / unsigned ints** — u8/i16/u16/u32/i64/u64 for packing, tile ids, RGBA channels, hashes and @Sync/serialize payloads. - **angle** — an auto-wrapping fixed angle with sin/cos/rotate (avoids manual % TAU). - **percent / normalized** — a clamped [0,1] fixed for health %, volume, lerp t. - **handle** — a typed id generalising `entity`, so asset/entity handles can't be mixed up with a bare int. - **duration / tick** — frame/time values that don't get confused with plain ints. - **rune / char** — a Unicode code point for text handling (Go `rune`). - **name** — an interned string for fast id comparison by handle, not bytes (Godot StringName). Phase 1 (IVec2 + Rect) shipped in the #1 thread.
orkun added the
proposal
priority:low
area:types
labels 2026-08-31 17:30:51 +02:00
Author
Owner

Shipped — Huge + Angle + Percent (5dc8394)

Types phase 5, the "polish" grab-bag. A splice-on-demand numeric runtime (runtime/native/numeric.ludic, built on the inline deterministic Math.* trig) exposes three namespaces:

  • Huge.* — idle/incremental big numbers, a normalized mantissa × 10^exponent that reaches far past the integer range. from / add / sub / mul / neg / cmp / sign / mantissa / exp / str (scientific, e.g. 1.00e12). As the proposal specifies, this is display-scale, not lockstep-exact (~4 significant digits) — kept out of the deterministic sim; BigInt/Decimal cover exactness.
  • Angle.* — an auto-wrapping radian angle, so no manual % TAU. from_degrees / to_degrees / wrap / sin / cos / add / diff (shortest signed rotation) / lerp (shortest arc).
  • Percent.* — a value clamped to [0, 1] for health fractions, volumes and interpolation t. clamp / of / lerp / apply.

The rest of phase 5

The remaining items on the list are already covered or need a language feature I have deliberately not rushed:

  • duration / tick — already shipped as the Duration.* namespace (time units).
  • rune / char — already covered by Unicode.* (code-point handling).
  • i64 — already exists as the long type; the other sized ints (u8/i16/u16/u32/u64) are packing/serialization widths.
  • handle (typed id) and a typed name/interned string — these are about nominal type safety (a handle that cannot be mixed up with a bare int). Ludic has no validation pass yet (unknown types lower to ptr, arity/type mismatches are not checked), so a safety wrapper cannot actually enforce anything today. These, and the remaining sized-int types, are the natural payoff of a type-checking pass and are best done together with it rather than as inert aliases.

Note — a compiler bug found and worked around

const X: fixed = 10.0 is broken: a const reference lowers to its raw integer value typed int (emit_call.ludic N_CONST), which silently corrupts fixed-point comparisons (I hit an infinite loop from it). The runtime uses inline fixed literals instead. Worth a separate fix so fixed consts are type-preserving.

Wired end to end: parser splice trigger (g_uses_numeric), emit_call dispatch, reseeded C-free seed, a self-asserting example (examples/library/numeric.ludic, 20 assertions, in the regression suite), per-symbol docs + sections + inventory. All suites green: x test 84/84, x selfhost-test 30/30 (golden renders byte-identical, bootstrap fixpoint holds), x test-tools 30/30, check-impl/check-vocabulary/check-docs.

Closing phase 5. With #52 / #54 / #55 done and phase 1 (#1), the type-system roadmap is now: shipped — 2D types (IVec2/Rect/Vector/Color), economy numbers (BigInt/Decimal), containers (Dict/Set), idle/polish numerics (Huge/Angle/Percent); remaining — the safety/control-flow types in #53 (option/result/tagged enums), which depend on real type-checking.

## Shipped — `Huge` + `Angle` + `Percent` (5dc8394) Types phase 5, the "polish" grab-bag. A splice-on-demand numeric runtime (`runtime/native/numeric.ludic`, built on the inline deterministic `Math.*` trig) exposes three namespaces: - **`Huge.*`** — idle/incremental big numbers, a normalized mantissa × 10^exponent that reaches far past the integer range. `from` / `add` / `sub` / `mul` / `neg` / `cmp` / `sign` / `mantissa` / `exp` / `str` (scientific, e.g. `1.00e12`). As the proposal specifies, this is **display-scale, not lockstep-exact** (~4 significant digits) — kept out of the deterministic sim; `BigInt`/`Decimal` cover exactness. - **`Angle.*`** — an auto-wrapping radian angle, so no manual `% TAU`. `from_degrees` / `to_degrees` / `wrap` / `sin` / `cos` / `add` / `diff` (shortest signed rotation) / `lerp` (shortest arc). - **`Percent.*`** — a value clamped to `[0, 1]` for health fractions, volumes and interpolation `t`. `clamp` / `of` / `lerp` / `apply`. ### The rest of phase 5 The remaining items on the list are already covered or need a language feature I have deliberately not rushed: - **`duration` / `tick`** — already shipped as the `Duration.*` namespace (time units). - **`rune` / `char`** — already covered by `Unicode.*` (code-point handling). - **`i64`** — already exists as the `long` type; the other sized ints (`u8`/`i16`/`u16`/`u32`/`u64`) are packing/serialization widths. - **`handle` (typed id)** and a **typed `name`/interned string** — these are about *nominal type safety* (a handle that cannot be mixed up with a bare int). Ludic has no validation pass yet (unknown types lower to `ptr`, arity/type mismatches are not checked), so a *safety* wrapper cannot actually enforce anything today. These, and the remaining sized-int types, are the natural payoff of a type-checking pass and are best done together with it rather than as inert aliases. ### Note — a compiler bug found and worked around `const X: fixed = 10.0` is broken: a `const` reference lowers to its raw integer value typed `int` (`emit_call.ludic` N_CONST), which silently corrupts fixed-point comparisons (I hit an infinite loop from it). The runtime uses inline fixed literals instead. Worth a separate fix so fixed consts are type-preserving. Wired end to end: parser splice trigger (`g_uses_numeric`), `emit_call` dispatch, reseeded C-free seed, a self-asserting example (`examples/library/numeric.ludic`, 20 assertions, in the regression suite), per-symbol docs + sections + inventory. All suites green: `x test` 84/84, `x selfhost-test` 30/30 (golden renders byte-identical, bootstrap fixpoint holds), `x test-tools` 30/30, `check-impl`/`check-vocabulary`/`check-docs`. Closing phase 5. With #52 / #54 / #55 done and phase 1 (#1), the type-system roadmap is now: shipped — 2D types (IVec2/Rect/Vector/Color), economy numbers (BigInt/Decimal), containers (Dict/Set), idle/polish numerics (Huge/Angle/Percent); remaining — the safety/control-flow types in #53 (option/result/tagged enums), which depend on real type-checking.
orkun closed this issue 2026-08-31 18:05:05 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: workshopsoft/ludic#55
No description provided.