selfhost/cmd/wcc: stamp e.type_ for N_CALL + drop fold hook (A.6.1.2)
Six N_CALL stamp sites in exprtype:
- alloc slice form: tt = ([]u8 | nomem)
- alloc value form: tt = (*T | nomem)
- size/align/offset fold sites: untyped_int (mirrors cstage
cmd/wcc/check.c:926/958 which sets n->type = ty_untyped_int
after the fold; the returned mktname("i32") is the assignability
target for callers, not the constant's own type)
- regular call: s.decl.lhs (mirrors cstage's build_fn_type ret)
Five error-path nil returns deliberately don't stamp.
Drop the size/align/offset trigger hook in resolvewalk: the A.6.0
end-of-fn general N_CALL dispatch already fires exprtype on every
N_CALL, making the targeted hook redundant. Pre-edit relied on
double-dispatch (hook → fold → re-dispatch → N_INTLIT stamp);
post-edit folds and stamps in one pass. Final n.type_ identical.
Hook removal + stamps bundled per CLAUDE.md rule 11: same-concern
(N_CALL handling) and the removal is what justifies the inline
fold-site stamps replacing the double-dispatch path.
Verified 132/132 incl. 995_self_rebuild byte-identity.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user