Skip to content

Commit df2703c

Browse files
committed
docs: correct float-wall scope — needs f64 value-type tracking, not just binop dispatch
Investigation correction: the float-wall fix is bigger than "add a gen_binop arm". The f64 instructions exist, but codegen's value model is i32-only — params (codegen.ml ~2995) and results (~2996) are hard-coded I32, and alloc_local (~181) is untyped, so float values cannot flow through params/returns/locals. The load-bearing change is typed locals (item 3); params/returns are small; the binop dispatch is the string-wall ExprFloatBinary pattern. A narrow slice (params+returns+comparisons+stack arith, erroring on float lets) compiles Float->Int classifiers without typed locals but is partial. https://claude.ai/code/session_01WoKhFQePiRsAj7aqnxbG8s
1 parent 2af23f9 commit df2703c

1 file changed

Lines changed: 26 additions & 2 deletions

File tree

proposals/EVIDENCE-float-wall-finding.adoc

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,32 @@ The same type-channel pattern that closed the string wall applies. Either:
5252
Smaller surface but introduces a type channel into codegen that does not yet
5353
exist there.
5454

55-
The f64 instructions already exist in `lib/wasm.ml` (`F64Const` is emitted for
56-
float literals today); only the binop dispatch is missing.
55+
*Scope correction (2026-06-14, after investigation).* This is bigger than "add
56+
a binop arm". The f64 *instructions* all exist in `lib/wasm.ml` (`F64Add`,
57+
`F64Lt`, …; `F64Const` is already emitted for float literals), but the codegen's
58+
*value model is i32-only*, so the fix needs f64 value-type tracking end to end:
59+
60+
. *Params* — `codegen.ml` `TopFn` lowers `ft_params = List.map (fun _ -> I32)
61+
fd.fd_params` (line ~2995). A `Float` param is declared `i32`, so an f64 arg
62+
cannot even arrive. Lower each param from its annotation via the existing
63+
`TyCon "Float" -> F64` mapping (line ~170).
64+
. *Results* — `ft_results = [I32]` (line ~2996). Lower from `fd.fd_ret_ty` so a
65+
`Float`-returning fn declares an `f64` result.
66+
. *Locals* — `alloc_local` (line ~181) tracks only `(name, idx)`; the function's
67+
locals are emitted all-`i32`. Binding a float value (`let y = x + 1.0`) would
68+
`LocalSet` an f64 into an i32 slot → validation failure. Locals must carry a
69+
`val_type`, threaded through `alloc_local` and the locals-emission.
70+
. *Binop dispatch* — the `ExprFloatBinary` elaboration (mirrors slices 8b/9/10):
71+
`synth` records `Float`-typed binop nodes (three sites: the arith branch's
72+
`Float` case, the `comparison` branch's `Float` case, and the `==`/`!=` else
73+
branch when operands are `Float`); elaboration rewrites to `ExprFloatBinary`;
74+
codegen lowers to the f64 family (arith → f64 value; comparison → i32 bool).
75+
76+
Items 1–2 are small; item 3 (typed locals) is the load-bearing change and the
77+
main validation-risk surface; item 4 is the string-wall pattern again. A
78+
*narrow first slice* (params + returns + comparisons + stack-flowing arith,
79+
erroring on float `let`-bindings until typed locals land) makes `Float -> Int`
80+
classifiers like `band_of` compile without item 3, but is partial.
5781

5882
== Harness readiness
5983

0 commit comments

Comments
 (0)