diff --git a/selfhost/cmd/w6c/main.combined.ww b/selfhost/cmd/w6c/main.combined.ww index 310883cb..9214b8ed 100644 --- a/selfhost/cmd/w6c/main.combined.ww +++ b/selfhost/cmd/w6c/main.combined.ww @@ -7366,23 +7366,9 @@ fn resolvewalk(c: *checker, n: *node) void = { }; }; - // #42: trigger the size/align/offset fold here so the mutation - // fires regardless of context (if-conditions, expression statements, - // etc.) — wwstage's exprtype is otherwise called only from - // checkletassign / checkretassign / TRYPROP, and an unwrapped - // `if (size(str) != 16)` would otherwise leave the N_CALL alone - // and cgen would emit a stray `CALL size(SB)`. Mirrors cstage - // cstmt's recursive cexpr discipline. - if (k == nkind.N_CALL) { - if (n.lhs != nil) { - if (n.lhs.kind == nkind.N_IDENT) { - let nm: str = n.lhs.str; - if (streq(nm, "size") || streq(nm, "align") || streq(nm, "offset")) { - let _t: *node = exprtype(c, n, nil); - }; - }; - }; - }; + // #42's size/align/offset fold trigger lived here pre-A.6.0; the + // A.6.0 end-of-fn general dispatch (below) now fires exprtype on + // every N_CALL — same context-free coverage, one dispatch site. // After walking children: a local `let X: T = init;` registers // `X` so subsequent statements can resolve it. Top-level lets @@ -8291,6 +8277,7 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = { sl.next = nome; let tt: *node = newnode(nkind.N_TTAGGED, "", 0, 0); tt.list = sl; + e.type_ = tinfofornode(c, tt): *void; return tt; }; }; @@ -8305,6 +8292,7 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = { ptr.next = nome; let tt: *node = newnode(nkind.N_TTAGGED, "", 0, 0); tt.list = ptr; + e.type_ = tinfofornode(c, tt): *void; return tt; }; }; @@ -8331,14 +8319,24 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = { }; if (!shadowed) { if (e.list != nil) { + // Post-fold the node IS an N_INTLIT-shaped + // untyped_int constant. Mirrors cstage + // cmd/wcc/check.c:926/958 which stamps + // ty_untyped_int after the fold. The return + // tnode mktname("i32") is the assignability + // target for callers, not the constant's + // own type. + let utn: *node = mktname(c, "untyped_int"); if (issize) { let v: i64 = astsize(c, e.list); foldtointlit(c, e, v); + e.type_ = tinfofornode(c, utn): *void; return mktname(c, "i32"); }; if (isalign) { let v: i64 = astalign(c, e.list); foldtointlit(c, e, v); + e.type_ = tinfofornode(c, utn): *void; return mktname(c, "i32"); }; // offset(e.f): the arg is a value expression @@ -8355,6 +8353,7 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = { off = 0i64; }; foldtointlit(c, e, off); + e.type_ = tinfofornode(c, utn): *void; return mktname(c, "i32"); }; }; @@ -8384,7 +8383,11 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = { if (s == nil) { return nil; }; if (s.skind != skind.SK_FN) { return nil; }; if (s.decl == nil) { return nil; }; - return s.decl.lhs; // fn-decl's lhs is the return type + // fn-decl's lhs is the return-type AST node. Mirrors cstage + // cmd/wcc/check.c:984+ regular-CALL `n->type = build_fn_type(c, + // s->decl)->ret` shape. + e.type_ = tinfofornode(c, s.decl.lhs): *void; + return s.decl.lhs; }; if (k == nkind.N_TRYPROP) { // success unwrap: the success-variant type of operand's diff --git a/selfhost/cmd/wcc/check.ww b/selfhost/cmd/wcc/check.ww index 297b7b07..1079e68f 100644 --- a/selfhost/cmd/wcc/check.ww +++ b/selfhost/cmd/wcc/check.ww @@ -434,23 +434,9 @@ fn resolvewalk(c: *checker, n: *node) void = { }; }; - // #42: trigger the size/align/offset fold here so the mutation - // fires regardless of context (if-conditions, expression statements, - // etc.) — wwstage's exprtype is otherwise called only from - // checkletassign / checkretassign / TRYPROP, and an unwrapped - // `if (size(str) != 16)` would otherwise leave the N_CALL alone - // and cgen would emit a stray `CALL size(SB)`. Mirrors cstage - // cstmt's recursive cexpr discipline. - if (k == nkind.N_CALL) { - if (n.lhs != nil) { - if (n.lhs.kind == nkind.N_IDENT) { - let nm: str = n.lhs.str; - if (streq(nm, "size") || streq(nm, "align") || streq(nm, "offset")) { - let _t: *node = exprtype(c, n, nil); - }; - }; - }; - }; + // #42's size/align/offset fold trigger lived here pre-A.6.0; the + // A.6.0 end-of-fn general dispatch (below) now fires exprtype on + // every N_CALL — same context-free coverage, one dispatch site. // After walking children: a local `let X: T = init;` registers // `X` so subsequent statements can resolve it. Top-level lets @@ -1359,6 +1345,7 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = { sl.next = nome; let tt: *node = newnode(nkind.N_TTAGGED, "", 0, 0); tt.list = sl; + e.type_ = tinfofornode(c, tt): *void; return tt; }; }; @@ -1373,6 +1360,7 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = { ptr.next = nome; let tt: *node = newnode(nkind.N_TTAGGED, "", 0, 0); tt.list = ptr; + e.type_ = tinfofornode(c, tt): *void; return tt; }; }; @@ -1399,14 +1387,24 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = { }; if (!shadowed) { if (e.list != nil) { + // Post-fold the node IS an N_INTLIT-shaped + // untyped_int constant. Mirrors cstage + // cmd/wcc/check.c:926/958 which stamps + // ty_untyped_int after the fold. The return + // tnode mktname("i32") is the assignability + // target for callers, not the constant's + // own type. + let utn: *node = mktname(c, "untyped_int"); if (issize) { let v: i64 = astsize(c, e.list); foldtointlit(c, e, v); + e.type_ = tinfofornode(c, utn): *void; return mktname(c, "i32"); }; if (isalign) { let v: i64 = astalign(c, e.list); foldtointlit(c, e, v); + e.type_ = tinfofornode(c, utn): *void; return mktname(c, "i32"); }; // offset(e.f): the arg is a value expression @@ -1423,6 +1421,7 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = { off = 0i64; }; foldtointlit(c, e, off); + e.type_ = tinfofornode(c, utn): *void; return mktname(c, "i32"); }; }; @@ -1452,7 +1451,11 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = { if (s == nil) { return nil; }; if (s.skind != skind.SK_FN) { return nil; }; if (s.decl == nil) { return nil; }; - return s.decl.lhs; // fn-decl's lhs is the return type + // fn-decl's lhs is the return-type AST node. Mirrors cstage + // cmd/wcc/check.c:984+ regular-CALL `n->type = build_fn_type(c, + // s->decl)->ret` shape. + e.type_ = tinfofornode(c, s.decl.lhs): *void; + return s.decl.lhs; }; if (k == nkind.N_TRYPROP) { // success unwrap: the success-variant type of operand's diff --git a/selfhost/cmd/wwdump/main.combined.ww b/selfhost/cmd/wwdump/main.combined.ww index 0e2539a2..fc2036dd 100644 --- a/selfhost/cmd/wwdump/main.combined.ww +++ b/selfhost/cmd/wwdump/main.combined.ww @@ -7366,23 +7366,9 @@ fn resolvewalk(c: *checker, n: *node) void = { }; }; - // #42: trigger the size/align/offset fold here so the mutation - // fires regardless of context (if-conditions, expression statements, - // etc.) — wwstage's exprtype is otherwise called only from - // checkletassign / checkretassign / TRYPROP, and an unwrapped - // `if (size(str) != 16)` would otherwise leave the N_CALL alone - // and cgen would emit a stray `CALL size(SB)`. Mirrors cstage - // cstmt's recursive cexpr discipline. - if (k == nkind.N_CALL) { - if (n.lhs != nil) { - if (n.lhs.kind == nkind.N_IDENT) { - let nm: str = n.lhs.str; - if (streq(nm, "size") || streq(nm, "align") || streq(nm, "offset")) { - let _t: *node = exprtype(c, n, nil); - }; - }; - }; - }; + // #42's size/align/offset fold trigger lived here pre-A.6.0; the + // A.6.0 end-of-fn general dispatch (below) now fires exprtype on + // every N_CALL — same context-free coverage, one dispatch site. // After walking children: a local `let X: T = init;` registers // `X` so subsequent statements can resolve it. Top-level lets @@ -8291,6 +8277,7 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = { sl.next = nome; let tt: *node = newnode(nkind.N_TTAGGED, "", 0, 0); tt.list = sl; + e.type_ = tinfofornode(c, tt): *void; return tt; }; }; @@ -8305,6 +8292,7 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = { ptr.next = nome; let tt: *node = newnode(nkind.N_TTAGGED, "", 0, 0); tt.list = ptr; + e.type_ = tinfofornode(c, tt): *void; return tt; }; }; @@ -8331,14 +8319,24 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = { }; if (!shadowed) { if (e.list != nil) { + // Post-fold the node IS an N_INTLIT-shaped + // untyped_int constant. Mirrors cstage + // cmd/wcc/check.c:926/958 which stamps + // ty_untyped_int after the fold. The return + // tnode mktname("i32") is the assignability + // target for callers, not the constant's + // own type. + let utn: *node = mktname(c, "untyped_int"); if (issize) { let v: i64 = astsize(c, e.list); foldtointlit(c, e, v); + e.type_ = tinfofornode(c, utn): *void; return mktname(c, "i32"); }; if (isalign) { let v: i64 = astalign(c, e.list); foldtointlit(c, e, v); + e.type_ = tinfofornode(c, utn): *void; return mktname(c, "i32"); }; // offset(e.f): the arg is a value expression @@ -8355,6 +8353,7 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = { off = 0i64; }; foldtointlit(c, e, off); + e.type_ = tinfofornode(c, utn): *void; return mktname(c, "i32"); }; }; @@ -8384,7 +8383,11 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = { if (s == nil) { return nil; }; if (s.skind != skind.SK_FN) { return nil; }; if (s.decl == nil) { return nil; }; - return s.decl.lhs; // fn-decl's lhs is the return type + // fn-decl's lhs is the return-type AST node. Mirrors cstage + // cmd/wcc/check.c:984+ regular-CALL `n->type = build_fn_type(c, + // s->decl)->ret` shape. + e.type_ = tinfofornode(c, s.decl.lhs): *void; + return s.decl.lhs; }; if (k == nkind.N_TRYPROP) { // success unwrap: the success-variant type of operand's