selfhost+lib/ww: N_TPARAM wrapper for tuple chains (A.6.2.0b-pre)
A.6.2.0b worker hit a real shared-`.next`-aliasing bug and stopped
per rule 7. Wwstage's N_TTUPLE chained element type ASTs via the
nodes' own `.next` field. `exprtype` routinely returns shared
nodes (sym.decl.lhs, struct field's `.lhs`, another N_TTUPLE's
`.list` element). Naive chain construction in the checker
corrupts source ASTs.
Introduce N_TPARAM = 67 as a chain wrapper for N_TTUPLE.list:
- `.lhs` holds the (possibly-shared) element type AST.
- `.next` chains within the parent N_TTUPLE.
- Other fields unused; never appears outside N_TTUPLE.list.
Mirrors cstage's Tparam at cmd/wcc/check.c:1437-1451. Cstage
keeps it at the Type layer; wwstage has no separate type layer
for tuple chains so the wrapper sits at the AST. Hare's design
intent at ref/hare/hare/ast/type.ha:117 uses `[]*_type` slice-of-
pointer — same principle, slice-flavored.
Migrations:
- lib/ww/ast.ww: kind + nkname + pr() unwrap (transparent for
the 990 -a astprint byte-diff).
- lib/ww/parse/parse.ww: parsetype N_TTUPLE construction wraps
each element in N_TPARAM (sole construction site).
- selfhost/cmd/wcc/check.ww: 4 readers (astalign, astsize,
tinfofornode TY_TUPLE, exprtype N_DOT-tuple-positional). The
last change retires the latent A.6.1.5b shared-`p` return.
- selfhost/cmd/wcc/cgenutil.ww: slotsize TY_TUPLE arm.
- selfhost/cmd/wcc/cgenexpr.ww: cgdot tuple-positional
(size/load op + str-check).
- selfhost/cmd/wcc/cgenstmt.ww: cglet TTUPLE init, cgmlet
call-return walk, cgforrange elem-size + bind-walk.
Out of scope: N_TFN params, N_TTAGGED variants, N_TSTRUCT fields.
N_TFIELD already wraps struct fields; N_TFN/N_TTAGGED aren't
currently chain-mutated by checker synthesis. If they ever are,
the same pattern applies.
Unblocks A.6.2.0b stamp on a clean foundation. Retires task #16.
Verified 132/132 incl. 990 AST byte-diff (astprint unwrap) + 995
self-rebuild byte-identity.
This commit is contained in:
@@ -718,7 +718,7 @@ fn astalign(c: *checker, t: *node) i64 = {
|
||||
let m: i64 = 1i64;
|
||||
let p: *node = t.list;
|
||||
for (p != nil) {
|
||||
let pa: i64 = astalign(c, p);
|
||||
let pa: i64 = astalign(c, p.lhs);
|
||||
if (pa > m) { m = pa; };
|
||||
p = p.next;
|
||||
};
|
||||
@@ -773,7 +773,7 @@ fn astsize(c: *checker, t: *node) i64 = {
|
||||
let total: i64 = 0i64;
|
||||
let p: *node = t.list;
|
||||
for (p != nil) {
|
||||
total += astsize(c, p);
|
||||
total += astsize(c, p.lhs);
|
||||
p = p.next;
|
||||
};
|
||||
return total;
|
||||
@@ -1097,7 +1097,7 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = {
|
||||
let maxal: u64 = 1u64;
|
||||
let p: *node = n.list;
|
||||
for (p != nil) {
|
||||
let pt: *tinfo = tinfofornode(c, p);
|
||||
let pt: *tinfo = tinfofornode(c, p.lhs);
|
||||
if (pt != nil) {
|
||||
if (pt.align > maxal) { maxal = pt.align; };
|
||||
total += pt.size;
|
||||
@@ -1759,8 +1759,9 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = {
|
||||
idx -= 1;
|
||||
};
|
||||
if (p != nil) {
|
||||
e.type_ = tinfofornode(c, p): *void;
|
||||
return p;
|
||||
let pt: *node = p.lhs;
|
||||
e.type_ = tinfofornode(c, pt): *void;
|
||||
return pt;
|
||||
};
|
||||
};
|
||||
}; };
|
||||
|
||||
Reference in New Issue
Block a user