feat(types): BigInt + Decimal exact economy numbers (#52)
All checks were successful
bootstrap / cfree-fixpoint (push) Successful in 19s
ci / build-and-test (push) Successful in 1m28s
commit-lint / conventional-commits (push) Successful in 5s
docs / build-and-deploy (push) Successful in 22s

Types phase 2 — the "money problem". A splice-on-demand bignum engine
(runtime/native/bignum.ludic, self-contained, only intrinsics) exposed as
two namespaces:

- BigInt.* — arbitrary-precision integer (sign-magnitude, base-1e9 limbs):
  from/parse, add/sub/mul/pow, div/mod (by int), cmp/eq/is_zero, to_int, str.
  For idle counters and exact huge currencies that overflow a 32/64-bit int.
- Decimal.* — exact base-10 fixed point (BigInt mantissa + decimal scale):
  from/parse, exact add/sub/mul, cmp/eq, scale/rescale (truncate), str.
  So 0.10 + 0.20 is exactly 0.30 — no binary rounding.

Both exact => deterministic; no f32/f64. Wired: parser splice trigger
(g_uses_bignum), emit_call dispatch, reseeded seed, a self-asserting example
(examples/library/bignum.ludic + feat_case), and per-symbol docs + inventory.
All suites green incl. golden renders byte-identical and the bootstrap fixpoint.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-08-31 18:45:14 +03:00
parent 2c9f9ac549
commit bd6b12d2ea
35 changed files with 23274 additions and 20791 deletions

View file

@ -332,6 +332,39 @@ function emit_ns_call(ns: pointer, meth: pointer, e: Node) -> Val {
# tile char, e.g. '#'. line/flood/a_star return []Cell slices. (Pathfinding
# lives under Grid rather than a `Path` namespace — that name is the filesystem
# paths library.)
# BigInt.* / Decimal.* -> the bignum engine (runtime/native/bignum.ludic,
# spliced on demand). These are ordinary Ludic functions, so the generic call
# path resolves them to @fn_bigint_* / @fn_decimal_* and keeps their return
# types (BigNum / Dec / int / bool / string).
if (ns == "BigInt") {
if (meth == "from") { bare = "bigint_from"; push(labels, "value") }
if (meth == "parse") { bare = "bigint_from_str"; push(labels, "text") }
if (meth == "add") { bare = "bigint_add"; push(labels, "a"); push(labels, "b") }
if (meth == "sub") { bare = "bigint_sub"; push(labels, "a"); push(labels, "b") }
if (meth == "mul") { bare = "bigint_mul"; push(labels, "a"); push(labels, "b") }
if (meth == "neg") { bare = "bigint_neg"; push(labels, "a") }
if (meth == "pow") { bare = "bigint_pow"; push(labels, "a"); push(labels, "exp") }
if (meth == "div") { bare = "bigint_div_int"; push(labels, "a"); push(labels, "d") }
if (meth == "mod") { bare = "bigint_mod_int"; push(labels, "a"); push(labels, "d") }
if (meth == "cmp") { bare = "bigint_cmp"; push(labels, "a"); push(labels, "b") }
if (meth == "eq") { bare = "bigint_eq"; push(labels, "a"); push(labels, "b") }
if (meth == "is_zero") { bare = "bigint_is_zero"; push(labels, "a") }
if (meth == "to_int") { bare = "bigint_to_int"; push(labels, "a") }
if (meth == "str") { bare = "bigint_str"; push(labels, "a") }
}
if (ns == "Decimal") {
if (meth == "from") { bare = "decimal_from"; push(labels, "value") }
if (meth == "parse") { bare = "decimal_from_str"; push(labels, "text") }
if (meth == "add") { bare = "decimal_add"; push(labels, "a"); push(labels, "b") }
if (meth == "sub") { bare = "decimal_sub"; push(labels, "a"); push(labels, "b") }
if (meth == "mul") { bare = "decimal_mul"; push(labels, "a"); push(labels, "b") }
if (meth == "neg") { bare = "decimal_neg"; push(labels, "a") }
if (meth == "cmp") { bare = "decimal_cmp"; push(labels, "a"); push(labels, "b") }
if (meth == "eq") { bare = "decimal_eq"; push(labels, "a"); push(labels, "b") }
if (meth == "scale") { bare = "decimal_scale"; push(labels, "d") }
if (meth == "rescale") { bare = "decimal_rescale"; push(labels, "d"); push(labels, "places") }
if (meth == "str") { bare = "decimal_str"; push(labels, "d") }
}
if (ns == "Grid") {
if (meth == "line") { bare = "grid_line"; push(labels, "x0"); push(labels, "y0"); push(labels, "x1"); push(labels, "y1") }
if (meth == "blocked") { bare = "grid_blocked"; push(labels, "x"); push(labels, "y"); push(labels, "wall") }