plan: Blocker — SX number promotion narrows floats to ints
This commit is contained in:
@@ -279,6 +279,13 @@ Anything that would require a change outside `lib/js/` goes here with a minimal
|
||||
- Variadic lifts: `hypot(…)` (n-args), `max(…)`/`min(…)` (we have 2-arg; JS allows 0 through N)
|
||||
Minimal repro: `Math.sin(0)` currently raises `TypeError: Math.sin is not a function` because `js-global.Math` has no `sin` key. Once the primitives exist in the runtime, `js-global.Math` can be extended in one drop — all 34 Math `not a function` failures flip together.
|
||||
|
||||
- **SX number promotion loses floats on exact-int results.** Minimal repro: `(type-of (* 1.5 2))` is `"number"` (fine) but the value is `3` — an int. In OCaml terms, multiplying a float by something that produces an integral float representable in a `Pervasives.int` triggers a narrowing. Consequence: any iterative float routine like `(let loop ((x 1.5) (n 100)) (if (<= n 0) x (loop (* x 2.0) (- n 1))))` overflows to 0 by n=60 because it's walking ints at that point. In JS terms this blocks:
|
||||
- `Number.MAX_VALUE` — our `js-max-value-approx` loops 1.0 × 2 and overflows to 0; we can't compute a correct 1.7976931348623157e308 from inside the runtime
|
||||
- `Number.MIN_VALUE` — same shape (loop 1.0 / 2 → 0 before reaching denormal 5e-324)
|
||||
- Any literal `1e308` — the SX tokenizer parses `e308` but clips too
|
||||
- `Math.pow(2, 100)` — same loop
|
||||
Proper fix is spec-level: keep `Sx_types.Number` boxed as OCaml `float` until an explicit int cast happens, or introduce a separate `Sx_types.Int` path and a promotion rule. For js-on-sx, `Number.MAX_VALUE` tests are blocked until then. Works around ~6 Number failures and nontrivial surface in Math.
|
||||
|
||||
- **Evaluator CPU bound at ~1 test/s on a 2-core box.** Runner auto-defaults to 1 worker on <=2-cores because two CEK workers starve each other — both are pure-Python/OCaml heavy loops with no IO concurrency to exploit. Each test that parses JS, transpiles to SX, then evaluates the SX under CEK runs in the 0.3–3s range; the long tail is mostly per-test `js-parse` scaling superlinearly with test length plus CEK env lookup walking a list of frames per free variable. Optimization surface someone else could pick up (all shared-file):
|
||||
- **Lexical addresses** in the evaluator: swap env-walk-by-name for `(depth, slot)` tuples resolved at transpile time. Would slash the per-CEK-step cost by an order of magnitude on tight loops.
|
||||
- **Inline caches on `js-get-prop`.** Every `a.b` walks the `__proto__` chain; 99% of call sites hit the same shape. A monomorphic cache keyed on the receiver's structural shape would collapse that to one lookup.
|
||||
|
||||
Reference in New Issue
Block a user