selfhost/cmd/wcc: stamp e.type_ for N_TUPLE (A.6.2.0b)
Port head-only of cstage cmd/wcc/check.c:1437-1451 to exprtype's
new N_TUPLE arm. The arm walks e.list, types each element via
recursive exprtype, and assembles an N_TTUPLE whose .list chains
N_TPARAM wrappers (one per element) so shared element-type ASTs
(sym.decl.lhs, struct field's .lhs, another tuple's element) keep
their own .next untouched.
Foundation: A.6.2.0b-pre (805c841) introduced N_TPARAM as the
chain wrapper for N_TTUPLE.list, mirroring cstage's Tparam at the
AST layer (cstage keeps it at the Type layer; wwstage has no
separate type layer). This commit is the first checker-side
synthesizer to use it.
One documented divergence: empty list returns nil under the
lenient policy (cstage would synthesize empty TY_TUPLE; ww grammar
requires >= 2 elements per parse/expr.ww:117, so empty is
unreachable either way). Same shape as scruttype L656 / A.6.1.5b
N_DOT lenient-on-miss precedent.
α scope per Drew (no hint plumbing, no field-level walks, no
unify check). Hint param stays unused.
A.6.2 step 2 of 8 (γ order). N_ALLOC next (most likely a
parser-vestigial kind — A.6.2.0c worker audits first).
`make test-unit` green; full `make test` deferred to the batched
gate after the A.6.2.1 assertion commit (option B per user).
This commit is contained in:
@@ -8841,6 +8841,39 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = {
|
||||
};
|
||||
return nil;
|
||||
};
|
||||
if (k == nkind.N_TUPLE) {
|
||||
// A.6.2.0b — head-only stamp of the tuple expression's
|
||||
// overall type. Mirrors cstage cmd/wcc/check.c:1437-1451
|
||||
// N_TUPLE: walk e.list, type each element via exprtype, and
|
||||
// assemble an N_TTUPLE whose .list chains N_TPARAM wrappers
|
||||
// (one per element) so shared element-type ASTs (sym.decl.lhs,
|
||||
// another tuple's element, struct field's .lhs) keep their
|
||||
// own .next untouched — see lib/ww/ast.ww:101 and the
|
||||
// A.6.2.0b-pre parser precedent at lib/ww/parse/parse.ww:302.
|
||||
// Per-element exprtype recursion is tinfocache-idempotent
|
||||
// (resolvewalk L460-489 already dispatches into N_TUPLE
|
||||
// children). Lenient on empty list: grammar requires >= 2
|
||||
// elements (lib/ww/parse/expr.ww:117 single-elem returns the
|
||||
// expression), so empty is unreachable and yields nil here
|
||||
// (matches scruttype L656 / A.6.1.5b N_DOT lenient-on-miss).
|
||||
if (e.list == nil) { return nil; };
|
||||
let head: *node = nil;
|
||||
let tail: *node = nil;
|
||||
let it: *node = e.list;
|
||||
for (it != nil) {
|
||||
let elemt: *node = exprtype(c, it, nil);
|
||||
let w: *node = newnode(nkind.N_TPARAM, "", 0, 0);
|
||||
w.lhs = elemt;
|
||||
if (head == nil) { head = w; }
|
||||
else { tail.next = w; };
|
||||
tail = w;
|
||||
it = it.next;
|
||||
};
|
||||
let tt: *node = newnode(nkind.N_TTUPLE, "", 0, 0);
|
||||
tt.list = head;
|
||||
e.type_ = tinfofornode(c, tt): *void;
|
||||
return tt;
|
||||
};
|
||||
if (k == nkind.N_TRYPROP) {
|
||||
// success unwrap: the success-variant type of operand's
|
||||
// tagged union.
|
||||
|
||||
@@ -1877,6 +1877,39 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = {
|
||||
};
|
||||
return nil;
|
||||
};
|
||||
if (k == nkind.N_TUPLE) {
|
||||
// A.6.2.0b — head-only stamp of the tuple expression's
|
||||
// overall type. Mirrors cstage cmd/wcc/check.c:1437-1451
|
||||
// N_TUPLE: walk e.list, type each element via exprtype, and
|
||||
// assemble an N_TTUPLE whose .list chains N_TPARAM wrappers
|
||||
// (one per element) so shared element-type ASTs (sym.decl.lhs,
|
||||
// another tuple's element, struct field's .lhs) keep their
|
||||
// own .next untouched — see lib/ww/ast.ww:101 and the
|
||||
// A.6.2.0b-pre parser precedent at lib/ww/parse/parse.ww:302.
|
||||
// Per-element exprtype recursion is tinfocache-idempotent
|
||||
// (resolvewalk L460-489 already dispatches into N_TUPLE
|
||||
// children). Lenient on empty list: grammar requires >= 2
|
||||
// elements (lib/ww/parse/expr.ww:117 single-elem returns the
|
||||
// expression), so empty is unreachable and yields nil here
|
||||
// (matches scruttype L656 / A.6.1.5b N_DOT lenient-on-miss).
|
||||
if (e.list == nil) { return nil; };
|
||||
let head: *node = nil;
|
||||
let tail: *node = nil;
|
||||
let it: *node = e.list;
|
||||
for (it != nil) {
|
||||
let elemt: *node = exprtype(c, it, nil);
|
||||
let w: *node = newnode(nkind.N_TPARAM, "", 0, 0);
|
||||
w.lhs = elemt;
|
||||
if (head == nil) { head = w; }
|
||||
else { tail.next = w; };
|
||||
tail = w;
|
||||
it = it.next;
|
||||
};
|
||||
let tt: *node = newnode(nkind.N_TTUPLE, "", 0, 0);
|
||||
tt.list = head;
|
||||
e.type_ = tinfofornode(c, tt): *void;
|
||||
return tt;
|
||||
};
|
||||
if (k == nkind.N_TRYPROP) {
|
||||
// success unwrap: the success-variant type of operand's
|
||||
// tagged union.
|
||||
|
||||
@@ -8841,6 +8841,39 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = {
|
||||
};
|
||||
return nil;
|
||||
};
|
||||
if (k == nkind.N_TUPLE) {
|
||||
// A.6.2.0b — head-only stamp of the tuple expression's
|
||||
// overall type. Mirrors cstage cmd/wcc/check.c:1437-1451
|
||||
// N_TUPLE: walk e.list, type each element via exprtype, and
|
||||
// assemble an N_TTUPLE whose .list chains N_TPARAM wrappers
|
||||
// (one per element) so shared element-type ASTs (sym.decl.lhs,
|
||||
// another tuple's element, struct field's .lhs) keep their
|
||||
// own .next untouched — see lib/ww/ast.ww:101 and the
|
||||
// A.6.2.0b-pre parser precedent at lib/ww/parse/parse.ww:302.
|
||||
// Per-element exprtype recursion is tinfocache-idempotent
|
||||
// (resolvewalk L460-489 already dispatches into N_TUPLE
|
||||
// children). Lenient on empty list: grammar requires >= 2
|
||||
// elements (lib/ww/parse/expr.ww:117 single-elem returns the
|
||||
// expression), so empty is unreachable and yields nil here
|
||||
// (matches scruttype L656 / A.6.1.5b N_DOT lenient-on-miss).
|
||||
if (e.list == nil) { return nil; };
|
||||
let head: *node = nil;
|
||||
let tail: *node = nil;
|
||||
let it: *node = e.list;
|
||||
for (it != nil) {
|
||||
let elemt: *node = exprtype(c, it, nil);
|
||||
let w: *node = newnode(nkind.N_TPARAM, "", 0, 0);
|
||||
w.lhs = elemt;
|
||||
if (head == nil) { head = w; }
|
||||
else { tail.next = w; };
|
||||
tail = w;
|
||||
it = it.next;
|
||||
};
|
||||
let tt: *node = newnode(nkind.N_TTUPLE, "", 0, 0);
|
||||
tt.list = head;
|
||||
e.type_ = tinfofornode(c, tt): *void;
|
||||
return tt;
|
||||
};
|
||||
if (k == nkind.N_TRYPROP) {
|
||||
// success unwrap: the success-variant type of operand's
|
||||
// tagged union.
|
||||
|
||||
Reference in New Issue
Block a user