diff --git a/selfhost/cmd/w6c/main.combined.ww b/selfhost/cmd/w6c/main.combined.ww index d8d77fce..9b4b8b04 100644 --- a/selfhost/cmd/w6c/main.combined.ww +++ b/selfhost/cmd/w6c/main.combined.ww @@ -8638,6 +8638,64 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = { m = m.next; }; }; }; + // A.6.1.5b stamp cases — mirror cstage check.c:833-866. Pure + // type-AST stamps; never rewrite e.kind. Lenient on misses + // (cstage errors); falls through to nil under scruttype L656. + // + // Pseudo-fields .len/.cap/.ptr on slice/str/array. Cstage + // L833-842. `str` lives as N_TNAME("str") in wwstage — no + // dedicated N_TSTR kind — so test the trio shape here. + if (bu != nil) { + let isstr: bool = (bu.kind == nkind.N_TNAME) && streq(bu.str, "str"); + if (bu.kind == nkind.N_TSLICE || bu.kind == nkind.N_TARRAY || isstr) { + if (streq(e.str, "len")) { + let tn: *node = mktname(c, "i32"); + e.type_ = tinfofornode(c, tn): *void; + return tn; + }; + if (streq(e.str, "cap")) { + let tn: *node = mktname(c, "i32"); + e.type_ = tinfofornode(c, tn): *void; + return tn; + }; + if (streq(e.str, "ptr")) { + let elem: *node = bu.lhs; + if (isstr) { elem = mktname(c, "u8"); }; + let pp: *node = newnode(nkind.N_TPTR, "", 0, 0); + pp.lhs = elem; + e.type_ = tinfofornode(c, pp): *void; + return pp; + }; + }; + }; + // Struct field walk. Cstage L843-849 errors on missing field. + if (bu != nil) { if (bu.kind == nkind.N_TSTRUCT) { + let f: *node = bu.list; + for (f != nil) { + if (f.kind == nkind.N_TFIELD) { if (streq(f.str, e.str)) { + e.type_ = tinfofornode(c, f.lhs): *void; + return f.lhs; + }; }; + f = f.next; + }; + }; }; + // Tuple positional access `t.0`, `t.1`, …. Cstage L850-866 + // errors on non-numeric / out-of-range; wwstage falls + // through. fldnumidx (cgenutil) returns -1 on non-digit. + if (bu != nil) { if (bu.kind == nkind.N_TTUPLE) { + let idx: i32 = fldnumidx(e.str); + if (idx >= 0) { + let p: *node = bu.list; + for (idx > 0 && p != nil) { + p = p.next; + idx -= 1; + }; + if (p != nil) { + e.type_ = tinfofornode(c, p): *void; + return p; + }; + }; + }; }; }; return nil; }; diff --git a/selfhost/cmd/wcc/check.ww b/selfhost/cmd/wcc/check.ww index 479613ee..85905dc3 100644 --- a/selfhost/cmd/wcc/check.ww +++ b/selfhost/cmd/wcc/check.ww @@ -1706,6 +1706,64 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = { m = m.next; }; }; }; + // A.6.1.5b stamp cases — mirror cstage check.c:833-866. Pure + // type-AST stamps; never rewrite e.kind. Lenient on misses + // (cstage errors); falls through to nil under scruttype L656. + // + // Pseudo-fields .len/.cap/.ptr on slice/str/array. Cstage + // L833-842. `str` lives as N_TNAME("str") in wwstage — no + // dedicated N_TSTR kind — so test the trio shape here. + if (bu != nil) { + let isstr: bool = (bu.kind == nkind.N_TNAME) && streq(bu.str, "str"); + if (bu.kind == nkind.N_TSLICE || bu.kind == nkind.N_TARRAY || isstr) { + if (streq(e.str, "len")) { + let tn: *node = mktname(c, "i32"); + e.type_ = tinfofornode(c, tn): *void; + return tn; + }; + if (streq(e.str, "cap")) { + let tn: *node = mktname(c, "i32"); + e.type_ = tinfofornode(c, tn): *void; + return tn; + }; + if (streq(e.str, "ptr")) { + let elem: *node = bu.lhs; + if (isstr) { elem = mktname(c, "u8"); }; + let pp: *node = newnode(nkind.N_TPTR, "", 0, 0); + pp.lhs = elem; + e.type_ = tinfofornode(c, pp): *void; + return pp; + }; + }; + }; + // Struct field walk. Cstage L843-849 errors on missing field. + if (bu != nil) { if (bu.kind == nkind.N_TSTRUCT) { + let f: *node = bu.list; + for (f != nil) { + if (f.kind == nkind.N_TFIELD) { if (streq(f.str, e.str)) { + e.type_ = tinfofornode(c, f.lhs): *void; + return f.lhs; + }; }; + f = f.next; + }; + }; }; + // Tuple positional access `t.0`, `t.1`, …. Cstage L850-866 + // errors on non-numeric / out-of-range; wwstage falls + // through. fldnumidx (cgenutil) returns -1 on non-digit. + if (bu != nil) { if (bu.kind == nkind.N_TTUPLE) { + let idx: i32 = fldnumidx(e.str); + if (idx >= 0) { + let p: *node = bu.list; + for (idx > 0 && p != nil) { + p = p.next; + idx -= 1; + }; + if (p != nil) { + e.type_ = tinfofornode(c, p): *void; + return p; + }; + }; + }; }; }; return nil; }; diff --git a/selfhost/cmd/wwdump/main.combined.ww b/selfhost/cmd/wwdump/main.combined.ww index bb9cb5db..30d6691d 100644 --- a/selfhost/cmd/wwdump/main.combined.ww +++ b/selfhost/cmd/wwdump/main.combined.ww @@ -8638,6 +8638,64 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = { m = m.next; }; }; }; + // A.6.1.5b stamp cases — mirror cstage check.c:833-866. Pure + // type-AST stamps; never rewrite e.kind. Lenient on misses + // (cstage errors); falls through to nil under scruttype L656. + // + // Pseudo-fields .len/.cap/.ptr on slice/str/array. Cstage + // L833-842. `str` lives as N_TNAME("str") in wwstage — no + // dedicated N_TSTR kind — so test the trio shape here. + if (bu != nil) { + let isstr: bool = (bu.kind == nkind.N_TNAME) && streq(bu.str, "str"); + if (bu.kind == nkind.N_TSLICE || bu.kind == nkind.N_TARRAY || isstr) { + if (streq(e.str, "len")) { + let tn: *node = mktname(c, "i32"); + e.type_ = tinfofornode(c, tn): *void; + return tn; + }; + if (streq(e.str, "cap")) { + let tn: *node = mktname(c, "i32"); + e.type_ = tinfofornode(c, tn): *void; + return tn; + }; + if (streq(e.str, "ptr")) { + let elem: *node = bu.lhs; + if (isstr) { elem = mktname(c, "u8"); }; + let pp: *node = newnode(nkind.N_TPTR, "", 0, 0); + pp.lhs = elem; + e.type_ = tinfofornode(c, pp): *void; + return pp; + }; + }; + }; + // Struct field walk. Cstage L843-849 errors on missing field. + if (bu != nil) { if (bu.kind == nkind.N_TSTRUCT) { + let f: *node = bu.list; + for (f != nil) { + if (f.kind == nkind.N_TFIELD) { if (streq(f.str, e.str)) { + e.type_ = tinfofornode(c, f.lhs): *void; + return f.lhs; + }; }; + f = f.next; + }; + }; }; + // Tuple positional access `t.0`, `t.1`, …. Cstage L850-866 + // errors on non-numeric / out-of-range; wwstage falls + // through. fldnumidx (cgenutil) returns -1 on non-digit. + if (bu != nil) { if (bu.kind == nkind.N_TTUPLE) { + let idx: i32 = fldnumidx(e.str); + if (idx >= 0) { + let p: *node = bu.list; + for (idx > 0 && p != nil) { + p = p.next; + idx -= 1; + }; + if (p != nil) { + e.type_ = tinfofornode(c, p): *void; + return p; + }; + }; + }; }; }; return nil; };