fold-1 narrows a float literal at materialisation only when its node already carries an f32 type — the `f32` suffix. The common un-suffixed case `let x: f32 = 1.0` stays ty_untyped_float through the checker, so the node is never f32-typed: the literal materialises as a 64-bit double and the f32 consumer reads the low 4 bytes (0.0f for clean values). Stamp such a literal f32 when an f32 target type is in context, the way harec's lower_implicit_cast does (ref/harec/src/check.c:148): a float literal's bit pattern is target-dependent, unlike a width-agnostic int immediate, so the value-producing node must carry the type. Scoped to untyped_float -> f32 only (f64 already works via cgen's double default). coerce_floatlit (cstage clet + cstmt N_RETURN) / coercefloatlit (wwstage resolvewalk's post-order N_LET / N_RETURN handler) are logically identical. The wwstage stamp is placed AFTER the child re-walk: the post-order exprtype dispatch re-stamps a bare N_FLOATLIT back to untyped_float, so coercing earlier (checkletassign) would be undone. Scope is let-init and return ONLY, aligned down to the leaner wwstage (rule 10). The wwstage cgen's exprfloatkind hardcodes a float literal to f64 and cgbin / the unary negate pick f32 off the operands, not the node stamp — so a stamped literal in an arith-binop / behind a unary minus narrows in cstage (ADDSS) but not wwstage (ADDSD), a byte-id break. The wwstage checker also has no assign / param-typed call-arg / per-field struct-lit site. binop, unary-minus, assign, call-arg, struct-field wait on #120 (wwstage cgen + checker build-out). 965_f32stamp_run: cstage run + cs==ww byte-id over un-suffixed let-init and return literals, the hole 964 left open. Regen w6c/wwdump combined.ww embeds.
6.8 KiB
6.8 KiB