wcc_ww/cgen: #92 rhsstructpayload N_STRUCTLIT arm through structlookupchain
The N_STRUCTLIT arm still did bare structlookup on the literal's type
name — an alias-named struct LITERAL widened into a union (`type ali =
base; let v: (void|ali) = ali{...}`) missed the registered structinfo
and fell to the scalar widen arm: word0-only/dropped payload, cs 0 /
ww EXIT 1, byte-id NO (reviewer-B2 find, pre-existing at 486f7f8's
parent). Exactly the class batch-2 c2 closed for the N_IDENT-local arm
of the SAME function; same funnel fix — route through structlookupchain
(cgenutil.ww:1758) and return si.sname so every consumer's re-lookup
hits the REGISTERED name.
One pre-authorized rider: structlookupchain's entry gate accepted only
N_TNAME, but a struct literal's type ref parses as N_IDENT (expression
position, lib/ww/parse/expr.ww builds s.lhs as N_IDENT — OBSERVED).
Widened to `N_TNAME || N_IDENT`; the entry-kind predicate is spelled
twice (the early-return and the chain loop's first iteration — the
loop reassigns cur to aliaslookup results, which are always N_TNAME,
so later iterations are untouched). Consumer census, all 10 call
sites: cgenutil:3187(+this arm; post-commit position), cgenexpr:2927/3006/8775/9011,
cgenstmt:3033 guard on N_TNAME explicitly before calling;
cgenexpr:5756 (etnode = type-spec .lhs), cgenstmt:1978 (arrtn.lhs or
the synthesized #79 N_TNAME), cgenstmt:2695 (cglet n.lhs declared
type spec) pass parsetype products only — parsetype builds zero
N_IDENT nodes (lib/ww/parse/parse.ww). No existing caller can pass
N_IDENT: the widening is strictly accepting-more; existing callers
unmoved. NO second inline chase in the arm (close-by-construction).
Base spellings byte-id: structlookup hits at the chain entry and
si.sname == the literal's own name — same string out, same asm.
Pin: 944_alias_accept_run union_slit_{base_ctl,alias,alias2,order} —
base control holds 0/0; 1/2-level alias + permuted decl order graduate
cs0/ww1-byte-id-NO -> 0/0 byte-id. #63 PROBED post-c3 per the
enrollment rule: does NOT green at this site (8B alias struct-lit
let-init still ww silent-zero-fill exit 1; 16B still loud "aggregate
init from unhandled rhs shape") — its miss is the cgenstmt let-init
dispatch, not rhsstructpayload; documented on task #63, left red, no
row enrolled.
Light gates: test-unit 290 green; sizelint 0; 989 ratchet zero flips;
five-mains NEUTRAL vs master-74195ac scratch on identical inputs +
cs==ww on all five. combined.ww regens ride along (#110).
This commit is contained in:
@@ -17829,11 +17829,19 @@ fn structabisize(si: *structinfo) i32 = {
|
||||
// fieldinfo list regardless of chain depth.
|
||||
export fn structlookupchain(c: *cgen, tn: *node) *structinfo = {
|
||||
if (tn == nil) { return nil; };
|
||||
if (tn.kind != nkind.N_TNAME) { return nil; };
|
||||
// #92: a struct LITERAL's type ref parses as N_IDENT (expression
|
||||
// position, lib/ww/parse/expr.ww) where type specs parse N_TNAME
|
||||
// — both carry the name in .str. Accept both at the ENTRY only:
|
||||
// iterations past the first walk aliaslookup results, which are
|
||||
// N_TNAME by the loop's own reassignment gate. Consumer census
|
||||
// (commit body): no existing caller can pass N_IDENT.
|
||||
if (tn.kind != nkind.N_TNAME && tn.kind != nkind.N_IDENT) { return nil; };
|
||||
let si: *structinfo = structlookup(c, tn.str);
|
||||
if (si != nil) { return si; };
|
||||
let cur: *node = tn;
|
||||
for (cur != nil && cur.kind == nkind.N_TNAME && si == nil) {
|
||||
for (cur != nil
|
||||
&& (cur.kind == nkind.N_TNAME || cur.kind == nkind.N_IDENT)
|
||||
&& si == nil) {
|
||||
let aliased: *node = aliaslookup(c, cur.str);
|
||||
if (aliased == nil) { cur = nil; }
|
||||
else {
|
||||
@@ -19217,13 +19225,16 @@ fn rhsstructpayload(c: *cgen, src: *node) str = {
|
||||
if (src.kind == nkind.N_STRUCTLIT) {
|
||||
let trefn: *node = src.lhs;
|
||||
if (trefn != nil) {
|
||||
let nm: str;
|
||||
nm.ptr = nil; nm.len = 0;
|
||||
if (trefn.kind == nkind.N_IDENT) { nm = trefn.str; };
|
||||
if (trefn.kind == nkind.N_TNAME) { nm = trefn.str; };
|
||||
if (nm.len > 0) {
|
||||
if (structlookup(c, nm) != nil) { return nm; };
|
||||
};
|
||||
// #92: bare structlookup missed an alias-named literal
|
||||
// — `ali{...}` into a union fell to the scalar widen
|
||||
// arm, word0-only payload (the class #62 L2 closed for
|
||||
// the N_IDENT-local arm below). Same funnel: the
|
||||
// REGISTERED name keeps every consumer's re-lookup
|
||||
// hitting. Base spellings: structlookup hits at the
|
||||
// chain entry and si.sname == the literal's own name —
|
||||
// same string out, same asm.
|
||||
let si: *structinfo = structlookupchain(c, trefn);
|
||||
if (si != nil) { return si.sname; };
|
||||
};
|
||||
return empty;
|
||||
};
|
||||
|
||||
@@ -1757,11 +1757,19 @@ fn structabisize(si: *structinfo) i32 = {
|
||||
// fieldinfo list regardless of chain depth.
|
||||
export fn structlookupchain(c: *cgen, tn: *node) *structinfo = {
|
||||
if (tn == nil) { return nil; };
|
||||
if (tn.kind != nkind.N_TNAME) { return nil; };
|
||||
// #92: a struct LITERAL's type ref parses as N_IDENT (expression
|
||||
// position, lib/ww/parse/expr.ww) where type specs parse N_TNAME
|
||||
// — both carry the name in .str. Accept both at the ENTRY only:
|
||||
// iterations past the first walk aliaslookup results, which are
|
||||
// N_TNAME by the loop's own reassignment gate. Consumer census
|
||||
// (commit body): no existing caller can pass N_IDENT.
|
||||
if (tn.kind != nkind.N_TNAME && tn.kind != nkind.N_IDENT) { return nil; };
|
||||
let si: *structinfo = structlookup(c, tn.str);
|
||||
if (si != nil) { return si; };
|
||||
let cur: *node = tn;
|
||||
for (cur != nil && cur.kind == nkind.N_TNAME && si == nil) {
|
||||
for (cur != nil
|
||||
&& (cur.kind == nkind.N_TNAME || cur.kind == nkind.N_IDENT)
|
||||
&& si == nil) {
|
||||
let aliased: *node = aliaslookup(c, cur.str);
|
||||
if (aliased == nil) { cur = nil; }
|
||||
else {
|
||||
@@ -3145,13 +3153,16 @@ fn rhsstructpayload(c: *cgen, src: *node) str = {
|
||||
if (src.kind == nkind.N_STRUCTLIT) {
|
||||
let trefn: *node = src.lhs;
|
||||
if (trefn != nil) {
|
||||
let nm: str;
|
||||
nm.ptr = nil; nm.len = 0;
|
||||
if (trefn.kind == nkind.N_IDENT) { nm = trefn.str; };
|
||||
if (trefn.kind == nkind.N_TNAME) { nm = trefn.str; };
|
||||
if (nm.len > 0) {
|
||||
if (structlookup(c, nm) != nil) { return nm; };
|
||||
};
|
||||
// #92: bare structlookup missed an alias-named literal
|
||||
// — `ali{...}` into a union fell to the scalar widen
|
||||
// arm, word0-only payload (the class #62 L2 closed for
|
||||
// the N_IDENT-local arm below). Same funnel: the
|
||||
// REGISTERED name keeps every consumer's re-lookup
|
||||
// hitting. Base spellings: structlookup hits at the
|
||||
// chain entry and si.sname == the literal's own name —
|
||||
// same string out, same asm.
|
||||
let si: *structinfo = structlookupchain(c, trefn);
|
||||
if (si != nil) { return si.sname; };
|
||||
};
|
||||
return empty;
|
||||
};
|
||||
|
||||
@@ -17829,11 +17829,19 @@ fn structabisize(si: *structinfo) i32 = {
|
||||
// fieldinfo list regardless of chain depth.
|
||||
export fn structlookupchain(c: *cgen, tn: *node) *structinfo = {
|
||||
if (tn == nil) { return nil; };
|
||||
if (tn.kind != nkind.N_TNAME) { return nil; };
|
||||
// #92: a struct LITERAL's type ref parses as N_IDENT (expression
|
||||
// position, lib/ww/parse/expr.ww) where type specs parse N_TNAME
|
||||
// — both carry the name in .str. Accept both at the ENTRY only:
|
||||
// iterations past the first walk aliaslookup results, which are
|
||||
// N_TNAME by the loop's own reassignment gate. Consumer census
|
||||
// (commit body): no existing caller can pass N_IDENT.
|
||||
if (tn.kind != nkind.N_TNAME && tn.kind != nkind.N_IDENT) { return nil; };
|
||||
let si: *structinfo = structlookup(c, tn.str);
|
||||
if (si != nil) { return si; };
|
||||
let cur: *node = tn;
|
||||
for (cur != nil && cur.kind == nkind.N_TNAME && si == nil) {
|
||||
for (cur != nil
|
||||
&& (cur.kind == nkind.N_TNAME || cur.kind == nkind.N_IDENT)
|
||||
&& si == nil) {
|
||||
let aliased: *node = aliaslookup(c, cur.str);
|
||||
if (aliased == nil) { cur = nil; }
|
||||
else {
|
||||
@@ -19217,13 +19225,16 @@ fn rhsstructpayload(c: *cgen, src: *node) str = {
|
||||
if (src.kind == nkind.N_STRUCTLIT) {
|
||||
let trefn: *node = src.lhs;
|
||||
if (trefn != nil) {
|
||||
let nm: str;
|
||||
nm.ptr = nil; nm.len = 0;
|
||||
if (trefn.kind == nkind.N_IDENT) { nm = trefn.str; };
|
||||
if (trefn.kind == nkind.N_TNAME) { nm = trefn.str; };
|
||||
if (nm.len > 0) {
|
||||
if (structlookup(c, nm) != nil) { return nm; };
|
||||
};
|
||||
// #92: bare structlookup missed an alias-named literal
|
||||
// — `ali{...}` into a union fell to the scalar widen
|
||||
// arm, word0-only payload (the class #62 L2 closed for
|
||||
// the N_IDENT-local arm below). Same funnel: the
|
||||
// REGISTERED name keeps every consumer's re-lookup
|
||||
// hitting. Base spellings: structlookup hits at the
|
||||
// chain entry and si.sname == the literal's own name —
|
||||
// same string out, same asm.
|
||||
let si: *structinfo = structlookupchain(c, trefn);
|
||||
if (si != nil) { return si.sname; };
|
||||
};
|
||||
return empty;
|
||||
};
|
||||
|
||||
@@ -48,6 +48,11 @@
|
||||
* | word0-only; cs half c138605, ww half |
|
||||
* | F2a batch-2 c2 — graduated K_RUN; |
|
||||
* | base ctl + #54-bound `as` row loud | 0
|
||||
* union_slit_* | task #92 (F2a batch-3 c3): alias- |
|
||||
* | named struct LITERAL into a union — |
|
||||
* | rhsstructpayload N_STRUCTLIT arm |
|
||||
* | routed through structlookupchain; |
|
||||
* | base ctl + 1/2-level + decl order | 0
|
||||
* nested_alias_field_* | task #71: alias-typed nested-field |
|
||||
* | store/read/addr-of walks fold to |
|
||||
* | direct offsets (byte-id graduation, |
|
||||
@@ -753,6 +758,78 @@ static const struct row rows[] = {
|
||||
" };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, K_RUN, NULL },
|
||||
/* ---- F2a batch-3 c3 (task #92, reviewer-B2 find): the same
|
||||
* rhsstructpayload widen, sourced from a struct LITERAL instead
|
||||
* of a local ident — the N_STRUCTLIT arm still did bare
|
||||
* structlookup, so `ali{...}` into a union fell to the scalar
|
||||
* widen arm (cs 0 / ww EXIT 1, byte-id NO, pre-existing on
|
||||
* master at 486f7f8). Graduated by routing the arm through
|
||||
* structlookupchain (entry gate widened to the literal's N_IDENT
|
||||
* type-ref leaf — consumer census in the commit body). Values
|
||||
* distinct per word, LAST word checked. The alias struct-LIT
|
||||
* LET-INIT zero-fill (task #63) does NOT green at this site —
|
||||
* probed post-c3, documented there, deliberately no row here. */
|
||||
{ "union_slit_base_ctl",
|
||||
"package main;\n"
|
||||
"type base = struct { a: size, b: size };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let v: (void | base) = base{a=4000, b=9000};\n"
|
||||
" match (v) {\n"
|
||||
" case let s: base => {\n"
|
||||
" if (s.a != 4000) { return 1; };\n"
|
||||
" if (s.b != 9000) { return 2; };\n"
|
||||
" };\n"
|
||||
" case void => { return 3; };\n"
|
||||
" };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, K_RUN, NULL },
|
||||
{ "union_slit_alias",
|
||||
"package main;\n"
|
||||
"type base = struct { a: size, b: size };\n"
|
||||
"type ali = base;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let v: (void | ali) = ali{a=4000, b=9000};\n"
|
||||
" match (v) {\n"
|
||||
" case let s: ali => {\n"
|
||||
" if (s.a != 4000) { return 1; };\n"
|
||||
" if (s.b != 9000) { return 2; };\n"
|
||||
" };\n"
|
||||
" case void => { return 3; };\n"
|
||||
" };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, K_RUN, NULL },
|
||||
/* 2-level: the chain walk (structlookupchain's alias loop). */
|
||||
{ "union_slit_alias2",
|
||||
"package main;\n"
|
||||
"type base = struct { a: size, b: size };\n"
|
||||
"type ali = base;\n"
|
||||
"type ali2 = ali;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let v: (void | ali2) = ali2{a=4000, b=9000};\n"
|
||||
" match (v) {\n"
|
||||
" case let s: ali2 => {\n"
|
||||
" if (s.a != 4000) { return 1; };\n"
|
||||
" if (s.b != 9000) { return 2; };\n"
|
||||
" };\n"
|
||||
" case void => { return 3; };\n"
|
||||
" };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, K_RUN, NULL },
|
||||
{ "union_slit_order",
|
||||
"package main;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let v: (void | ali) = ali{a=4000, b=9000};\n"
|
||||
" match (v) {\n"
|
||||
" case let s: ali => {\n"
|
||||
" if (s.a != 4000) { return 1; };\n"
|
||||
" if (s.b != 9000) { return 2; };\n"
|
||||
" };\n"
|
||||
" case void => { return 3; };\n"
|
||||
" };\n"
|
||||
" return 0;\n"
|
||||
"};\n"
|
||||
"type ali = base;\n"
|
||||
"type base = struct { a: size, b: size };\n", 0, K_RUN, NULL },
|
||||
/* ---- F2a batch-2 c3/B1: exprprimresolved's N_DOT base walk was
|
||||
* a hand-rolled 2-peel — a 3-level alias base (or ptr-to-2-level)
|
||||
* left the cast-source width unknowable on wwstage only, so the
|
||||
|
||||
Reference in New Issue
Block a user