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.
|
// fieldinfo list regardless of chain depth.
|
||||||
export fn structlookupchain(c: *cgen, tn: *node) *structinfo = {
|
export fn structlookupchain(c: *cgen, tn: *node) *structinfo = {
|
||||||
if (tn == nil) { return nil; };
|
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);
|
let si: *structinfo = structlookup(c, tn.str);
|
||||||
if (si != nil) { return si; };
|
if (si != nil) { return si; };
|
||||||
let cur: *node = tn;
|
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);
|
let aliased: *node = aliaslookup(c, cur.str);
|
||||||
if (aliased == nil) { cur = nil; }
|
if (aliased == nil) { cur = nil; }
|
||||||
else {
|
else {
|
||||||
@@ -19217,13 +19225,16 @@ fn rhsstructpayload(c: *cgen, src: *node) str = {
|
|||||||
if (src.kind == nkind.N_STRUCTLIT) {
|
if (src.kind == nkind.N_STRUCTLIT) {
|
||||||
let trefn: *node = src.lhs;
|
let trefn: *node = src.lhs;
|
||||||
if (trefn != nil) {
|
if (trefn != nil) {
|
||||||
let nm: str;
|
// #92: bare structlookup missed an alias-named literal
|
||||||
nm.ptr = nil; nm.len = 0;
|
// — `ali{...}` into a union fell to the scalar widen
|
||||||
if (trefn.kind == nkind.N_IDENT) { nm = trefn.str; };
|
// arm, word0-only payload (the class #62 L2 closed for
|
||||||
if (trefn.kind == nkind.N_TNAME) { nm = trefn.str; };
|
// the N_IDENT-local arm below). Same funnel: the
|
||||||
if (nm.len > 0) {
|
// REGISTERED name keeps every consumer's re-lookup
|
||||||
if (structlookup(c, nm) != nil) { return nm; };
|
// 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;
|
return empty;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1757,11 +1757,19 @@ fn structabisize(si: *structinfo) i32 = {
|
|||||||
// fieldinfo list regardless of chain depth.
|
// fieldinfo list regardless of chain depth.
|
||||||
export fn structlookupchain(c: *cgen, tn: *node) *structinfo = {
|
export fn structlookupchain(c: *cgen, tn: *node) *structinfo = {
|
||||||
if (tn == nil) { return nil; };
|
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);
|
let si: *structinfo = structlookup(c, tn.str);
|
||||||
if (si != nil) { return si; };
|
if (si != nil) { return si; };
|
||||||
let cur: *node = tn;
|
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);
|
let aliased: *node = aliaslookup(c, cur.str);
|
||||||
if (aliased == nil) { cur = nil; }
|
if (aliased == nil) { cur = nil; }
|
||||||
else {
|
else {
|
||||||
@@ -3145,13 +3153,16 @@ fn rhsstructpayload(c: *cgen, src: *node) str = {
|
|||||||
if (src.kind == nkind.N_STRUCTLIT) {
|
if (src.kind == nkind.N_STRUCTLIT) {
|
||||||
let trefn: *node = src.lhs;
|
let trefn: *node = src.lhs;
|
||||||
if (trefn != nil) {
|
if (trefn != nil) {
|
||||||
let nm: str;
|
// #92: bare structlookup missed an alias-named literal
|
||||||
nm.ptr = nil; nm.len = 0;
|
// — `ali{...}` into a union fell to the scalar widen
|
||||||
if (trefn.kind == nkind.N_IDENT) { nm = trefn.str; };
|
// arm, word0-only payload (the class #62 L2 closed for
|
||||||
if (trefn.kind == nkind.N_TNAME) { nm = trefn.str; };
|
// the N_IDENT-local arm below). Same funnel: the
|
||||||
if (nm.len > 0) {
|
// REGISTERED name keeps every consumer's re-lookup
|
||||||
if (structlookup(c, nm) != nil) { return nm; };
|
// 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;
|
return empty;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -17829,11 +17829,19 @@ fn structabisize(si: *structinfo) i32 = {
|
|||||||
// fieldinfo list regardless of chain depth.
|
// fieldinfo list regardless of chain depth.
|
||||||
export fn structlookupchain(c: *cgen, tn: *node) *structinfo = {
|
export fn structlookupchain(c: *cgen, tn: *node) *structinfo = {
|
||||||
if (tn == nil) { return nil; };
|
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);
|
let si: *structinfo = structlookup(c, tn.str);
|
||||||
if (si != nil) { return si; };
|
if (si != nil) { return si; };
|
||||||
let cur: *node = tn;
|
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);
|
let aliased: *node = aliaslookup(c, cur.str);
|
||||||
if (aliased == nil) { cur = nil; }
|
if (aliased == nil) { cur = nil; }
|
||||||
else {
|
else {
|
||||||
@@ -19217,13 +19225,16 @@ fn rhsstructpayload(c: *cgen, src: *node) str = {
|
|||||||
if (src.kind == nkind.N_STRUCTLIT) {
|
if (src.kind == nkind.N_STRUCTLIT) {
|
||||||
let trefn: *node = src.lhs;
|
let trefn: *node = src.lhs;
|
||||||
if (trefn != nil) {
|
if (trefn != nil) {
|
||||||
let nm: str;
|
// #92: bare structlookup missed an alias-named literal
|
||||||
nm.ptr = nil; nm.len = 0;
|
// — `ali{...}` into a union fell to the scalar widen
|
||||||
if (trefn.kind == nkind.N_IDENT) { nm = trefn.str; };
|
// arm, word0-only payload (the class #62 L2 closed for
|
||||||
if (trefn.kind == nkind.N_TNAME) { nm = trefn.str; };
|
// the N_IDENT-local arm below). Same funnel: the
|
||||||
if (nm.len > 0) {
|
// REGISTERED name keeps every consumer's re-lookup
|
||||||
if (structlookup(c, nm) != nil) { return nm; };
|
// 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;
|
return empty;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -48,6 +48,11 @@
|
|||||||
* | word0-only; cs half c138605, ww half |
|
* | word0-only; cs half c138605, ww half |
|
||||||
* | F2a batch-2 c2 — graduated K_RUN; |
|
* | F2a batch-2 c2 — graduated K_RUN; |
|
||||||
* | base ctl + #54-bound `as` row loud | 0
|
* | 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 |
|
* nested_alias_field_* | task #71: alias-typed nested-field |
|
||||||
* | store/read/addr-of walks fold to |
|
* | store/read/addr-of walks fold to |
|
||||||
* | direct offsets (byte-id graduation, |
|
* | direct offsets (byte-id graduation, |
|
||||||
@@ -753,6 +758,78 @@ static const struct row rows[] = {
|
|||||||
" };\n"
|
" };\n"
|
||||||
" return 0;\n"
|
" return 0;\n"
|
||||||
"};\n", 0, K_RUN, NULL },
|
"};\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
|
/* ---- 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)
|
* 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
|
* left the cast-source width unknowable on wwstage only, so the
|
||||||
|
|||||||
Reference in New Issue
Block a user