wcc: stamp un-suffixed f32-context float literals (#104 fold-2)
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.
This commit is contained in:
@@ -7609,6 +7609,17 @@ fn resolvewalk(c: *checker, n: *node) void = {
|
||||
};
|
||||
};
|
||||
|
||||
// #104 fold-2: narrow a bare f32-context float literal AFTER the
|
||||
// child walk above — the post-order exprtype dispatch (below) re-
|
||||
// stamps a bare N_FLOATLIT back to untyped_float, so coercing earlier
|
||||
// (e.g. in checkletassign) would be undone. Placed here, the f32
|
||||
// stamp on n.rhs / n.lhs sticks; cgen's fold-1 narrow then fires. let
|
||||
// / return only — see coercefloatlit's docstring for the rule-10 scope
|
||||
// (the cstage twin coerces in clet / cstmt N_RETURN). c.fnret is set
|
||||
// by resolvefnbody for the enclosing fn, mirroring checkretassign.
|
||||
if (k == nkind.N_LET) { coercefloatlit(c, n.rhs, n.lhs); };
|
||||
if (k == nkind.N_RETURN) { coercefloatlit(c, n.lhs, c.fnret); };
|
||||
|
||||
// A.6.0: post-order dispatch of exprtype on every expression-yielding
|
||||
// node kind so n.type_ stamps fire universally — not only when reached
|
||||
// through checkletassign / checkretassign / checktryprop / the size-
|
||||
@@ -8877,6 +8888,31 @@ fn unifyarith(c: *checker, ltn: *node, rtn: *node) *node = {
|
||||
return ltn;
|
||||
};
|
||||
|
||||
// coercefloatlit — twin of cstage cmd/wcc/check.c coerce_floatlit (see there
|
||||
// for the full rationale + the rule-10 scope note). Stamp an un-suffixed
|
||||
// float literal (whose type_ is the untyped_float singleton) as f32 when the
|
||||
// target type resolves to f32, so fold-1's cgen narrow (isf32type, cgenexpr.
|
||||
// ww) fires off the now-f32 node.type_. SCOPED to a DIRECT untyped_float
|
||||
// N_FLOATLIT at let-init / return only: the wwstage cgen's exprfloatkind
|
||||
// (cgenutil.ww) hardcodes N_FLOATLIT -> f64 and cgbin / the unary negate pick
|
||||
// f32 off the operands' float-kind, not the node stamp, so a stamped literal
|
||||
// inside an arith-binop / behind a unary minus does NOT narrow there —
|
||||
// binop / unary-minus / assign / call-arg / struct-field wait on #120.
|
||||
fn coercefloatlit(c: *checker, e: *node, target: *node) void = {
|
||||
if (e == nil) { return; };
|
||||
if (target == nil) { return; };
|
||||
let tu: *node = resolvealias(c, unwrapbang(target));
|
||||
if (tu == nil) { return; };
|
||||
if (tu.kind != nkind.N_TNAME) { return; };
|
||||
if (!streq(tu.str, "f32")) { return; };
|
||||
if (e.kind == nkind.N_FLOATLIT) {
|
||||
if ((e.type_: *tinfo) == c.tc.tyuntypedfloat) {
|
||||
let f32t: *node = mktname(c, "f32");
|
||||
e.type_ = tinfofornode(c, f32t): *void;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
// binoptype — derive the result tnode of an N_BIN operator expression.
|
||||
// Mirrors cstage cmd/wcc/check.c:598-640 `cbinop`. Operates on tnodes
|
||||
// returned by exprtype; ptr arithmetic / bitwise / shifts / comparisons /
|
||||
|
||||
@@ -458,6 +458,17 @@ fn resolvewalk(c: *checker, n: *node) void = {
|
||||
};
|
||||
};
|
||||
|
||||
// #104 fold-2: narrow a bare f32-context float literal AFTER the
|
||||
// child walk above — the post-order exprtype dispatch (below) re-
|
||||
// stamps a bare N_FLOATLIT back to untyped_float, so coercing earlier
|
||||
// (e.g. in checkletassign) would be undone. Placed here, the f32
|
||||
// stamp on n.rhs / n.lhs sticks; cgen's fold-1 narrow then fires. let
|
||||
// / return only — see coercefloatlit's docstring for the rule-10 scope
|
||||
// (the cstage twin coerces in clet / cstmt N_RETURN). c.fnret is set
|
||||
// by resolvefnbody for the enclosing fn, mirroring checkretassign.
|
||||
if (k == nkind.N_LET) { coercefloatlit(c, n.rhs, n.lhs); };
|
||||
if (k == nkind.N_RETURN) { coercefloatlit(c, n.lhs, c.fnret); };
|
||||
|
||||
// A.6.0: post-order dispatch of exprtype on every expression-yielding
|
||||
// node kind so n.type_ stamps fire universally — not only when reached
|
||||
// through checkletassign / checkretassign / checktryprop / the size-
|
||||
@@ -1726,6 +1737,31 @@ fn unifyarith(c: *checker, ltn: *node, rtn: *node) *node = {
|
||||
return ltn;
|
||||
};
|
||||
|
||||
// coercefloatlit — twin of cstage cmd/wcc/check.c coerce_floatlit (see there
|
||||
// for the full rationale + the rule-10 scope note). Stamp an un-suffixed
|
||||
// float literal (whose type_ is the untyped_float singleton) as f32 when the
|
||||
// target type resolves to f32, so fold-1's cgen narrow (isf32type, cgenexpr.
|
||||
// ww) fires off the now-f32 node.type_. SCOPED to a DIRECT untyped_float
|
||||
// N_FLOATLIT at let-init / return only: the wwstage cgen's exprfloatkind
|
||||
// (cgenutil.ww) hardcodes N_FLOATLIT -> f64 and cgbin / the unary negate pick
|
||||
// f32 off the operands' float-kind, not the node stamp, so a stamped literal
|
||||
// inside an arith-binop / behind a unary minus does NOT narrow there —
|
||||
// binop / unary-minus / assign / call-arg / struct-field wait on #120.
|
||||
fn coercefloatlit(c: *checker, e: *node, target: *node) void = {
|
||||
if (e == nil) { return; };
|
||||
if (target == nil) { return; };
|
||||
let tu: *node = resolvealias(c, unwrapbang(target));
|
||||
if (tu == nil) { return; };
|
||||
if (tu.kind != nkind.N_TNAME) { return; };
|
||||
if (!streq(tu.str, "f32")) { return; };
|
||||
if (e.kind == nkind.N_FLOATLIT) {
|
||||
if ((e.type_: *tinfo) == c.tc.tyuntypedfloat) {
|
||||
let f32t: *node = mktname(c, "f32");
|
||||
e.type_ = tinfofornode(c, f32t): *void;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
// binoptype — derive the result tnode of an N_BIN operator expression.
|
||||
// Mirrors cstage cmd/wcc/check.c:598-640 `cbinop`. Operates on tnodes
|
||||
// returned by exprtype; ptr arithmetic / bitwise / shifts / comparisons /
|
||||
|
||||
@@ -7609,6 +7609,17 @@ fn resolvewalk(c: *checker, n: *node) void = {
|
||||
};
|
||||
};
|
||||
|
||||
// #104 fold-2: narrow a bare f32-context float literal AFTER the
|
||||
// child walk above — the post-order exprtype dispatch (below) re-
|
||||
// stamps a bare N_FLOATLIT back to untyped_float, so coercing earlier
|
||||
// (e.g. in checkletassign) would be undone. Placed here, the f32
|
||||
// stamp on n.rhs / n.lhs sticks; cgen's fold-1 narrow then fires. let
|
||||
// / return only — see coercefloatlit's docstring for the rule-10 scope
|
||||
// (the cstage twin coerces in clet / cstmt N_RETURN). c.fnret is set
|
||||
// by resolvefnbody for the enclosing fn, mirroring checkretassign.
|
||||
if (k == nkind.N_LET) { coercefloatlit(c, n.rhs, n.lhs); };
|
||||
if (k == nkind.N_RETURN) { coercefloatlit(c, n.lhs, c.fnret); };
|
||||
|
||||
// A.6.0: post-order dispatch of exprtype on every expression-yielding
|
||||
// node kind so n.type_ stamps fire universally — not only when reached
|
||||
// through checkletassign / checkretassign / checktryprop / the size-
|
||||
@@ -8877,6 +8888,31 @@ fn unifyarith(c: *checker, ltn: *node, rtn: *node) *node = {
|
||||
return ltn;
|
||||
};
|
||||
|
||||
// coercefloatlit — twin of cstage cmd/wcc/check.c coerce_floatlit (see there
|
||||
// for the full rationale + the rule-10 scope note). Stamp an un-suffixed
|
||||
// float literal (whose type_ is the untyped_float singleton) as f32 when the
|
||||
// target type resolves to f32, so fold-1's cgen narrow (isf32type, cgenexpr.
|
||||
// ww) fires off the now-f32 node.type_. SCOPED to a DIRECT untyped_float
|
||||
// N_FLOATLIT at let-init / return only: the wwstage cgen's exprfloatkind
|
||||
// (cgenutil.ww) hardcodes N_FLOATLIT -> f64 and cgbin / the unary negate pick
|
||||
// f32 off the operands' float-kind, not the node stamp, so a stamped literal
|
||||
// inside an arith-binop / behind a unary minus does NOT narrow there —
|
||||
// binop / unary-minus / assign / call-arg / struct-field wait on #120.
|
||||
fn coercefloatlit(c: *checker, e: *node, target: *node) void = {
|
||||
if (e == nil) { return; };
|
||||
if (target == nil) { return; };
|
||||
let tu: *node = resolvealias(c, unwrapbang(target));
|
||||
if (tu == nil) { return; };
|
||||
if (tu.kind != nkind.N_TNAME) { return; };
|
||||
if (!streq(tu.str, "f32")) { return; };
|
||||
if (e.kind == nkind.N_FLOATLIT) {
|
||||
if ((e.type_: *tinfo) == c.tc.tyuntypedfloat) {
|
||||
let f32t: *node = mktname(c, "f32");
|
||||
e.type_ = tinfofornode(c, f32t): *void;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
// binoptype — derive the result tnode of an N_BIN operator expression.
|
||||
// Mirrors cstage cmd/wcc/check.c:598-640 `cbinop`. Operates on tnodes
|
||||
// returned by exprtype; ptr arithmetic / bitwise / shifts / comparisons /
|
||||
|
||||
Reference in New Issue
Block a user