From c564d7d0fd9d5616e295710cd40148cd78ddb07f Mon Sep 17 00:00:00 2001 From: Hojun-Cho Date: Thu, 21 May 2026 20:16:24 +0900 Subject: [PATCH] selfhost/cmd/wcc: stamp e.type_ for N_SLICE (A.6.2.0a) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Port head-only of cstage cmd/wcc/check.c:1214-1228 to exprtype's new N_SLICE arm. Four base shapes: - N_TARRAY → synthesize N_TSLICE{lhs=elem} (cstage L1219). - N_TSLICE → return basetn (pre-peel, matches cstage `base` not `u`; L1221). - N_TNAME("str") → mktname("str") (matches cstage's `ty_str` canonical singleton, L1223). - N_TPTR with non-nil sub → synthesize N_TSLICE{lhs=sub} (L1225, Hare-faithful slice-of-elem from pointer-to-elem). Slice bounds (e.rhs start, e.cond end) are already walked by resolvewalk L406-408 + post-order dispatch L460-489 — typical N_INTLIT/N_IDENT/N_BIN are in the dispatch list; this arm does not double-walk. One documented divergence from cstage: lenient on non-sliceable base (cstage L1227 errs; wwstage returns nil under the established scruttype L656 / A.6.1.5b N_DOT struct-miss precedent). A.6.2 step 1 of 8 (γ scope per Drew, 2026-05-21) — gap-sweep per-kind first, post-checker assertion last. Order by triviality: N_SLICE → N_TUPLE → N_ALLOC → N_RECV → N_SPREAD → N_YIELD → N_MATCH → assertion. Each commit holds invariant; cgen readers migrate in A.6.3. Verified 132/132 incl. 995_self_rebuild byte-identity. --- selfhost/cmd/w6c/main.combined.ww | 39 ++++++++++++++++++++++++++++ selfhost/cmd/wcc/check.ww | 39 ++++++++++++++++++++++++++++ selfhost/cmd/wwdump/main.combined.ww | 39 ++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+) diff --git a/selfhost/cmd/w6c/main.combined.ww b/selfhost/cmd/w6c/main.combined.ww index 8ced2192..c095d49c 100644 --- a/selfhost/cmd/w6c/main.combined.ww +++ b/selfhost/cmd/w6c/main.combined.ww @@ -8769,6 +8769,45 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = { e.type_ = tinfofornode(c, arr): *void; return arr; }; + if (k == nkind.N_SLICE) { + // A.6.2.0a — head-only stamp of the slice expression's overall + // type. Mirrors cstage cmd/wcc/check.c:1214-1228 N_SLICE: peel + // alias on the base; [N]T → []T, []T → []T (return base), str + // → str, *T (non-nil sub) → []T. Slice bounds (e.rhs start, + // e.cond end) are already covered by the post-order dispatch + // at L460-489 (typically N_INTLIT/N_IDENT/N_BIN, all in the + // dispatch list), so we do not double-walk them here. + // Documented cstage divergence: cstage L1227 errors on a + // non-sliceable base; wwstage returns nil (lenient on miss), + // matching scruttype L656 / A.6.1.5b N_DOT precedent. + let basetn: *node = exprtype(c, e.lhs, nil); + let bu: *node = resolvealias(c, unwrapbang(basetn)); + if (bu == nil) { return nil; }; + if (bu.kind == nkind.N_TARRAY) { + let sl: *node = newnode(nkind.N_TSLICE, "", 0, 0); + sl.lhs = bu.lhs; + e.type_ = tinfofornode(c, sl): *void; + return sl; + }; + if (bu.kind == nkind.N_TSLICE) { + e.type_ = tinfofornode(c, basetn): *void; + return basetn; + }; + if (bu.kind == nkind.N_TNAME) { + if (streq(bu.str, "str")) { + let tn: *node = mktname(c, "str"); + e.type_ = tinfofornode(c, tn): *void; + return tn; + }; + }; + if (bu.kind == nkind.N_TPTR && bu.lhs != nil) { + let sl: *node = newnode(nkind.N_TSLICE, "", 0, 0); + sl.lhs = bu.lhs; + e.type_ = tinfofornode(c, sl): *void; + return sl; + }; + return nil; + }; if (k == nkind.N_TRYPROP) { // success unwrap: the success-variant type of operand's // tagged union. diff --git a/selfhost/cmd/wcc/check.ww b/selfhost/cmd/wcc/check.ww index 9194d9d3..fbf2abfd 100644 --- a/selfhost/cmd/wcc/check.ww +++ b/selfhost/cmd/wcc/check.ww @@ -1837,6 +1837,45 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = { e.type_ = tinfofornode(c, arr): *void; return arr; }; + if (k == nkind.N_SLICE) { + // A.6.2.0a — head-only stamp of the slice expression's overall + // type. Mirrors cstage cmd/wcc/check.c:1214-1228 N_SLICE: peel + // alias on the base; [N]T → []T, []T → []T (return base), str + // → str, *T (non-nil sub) → []T. Slice bounds (e.rhs start, + // e.cond end) are already covered by the post-order dispatch + // at L460-489 (typically N_INTLIT/N_IDENT/N_BIN, all in the + // dispatch list), so we do not double-walk them here. + // Documented cstage divergence: cstage L1227 errors on a + // non-sliceable base; wwstage returns nil (lenient on miss), + // matching scruttype L656 / A.6.1.5b N_DOT precedent. + let basetn: *node = exprtype(c, e.lhs, nil); + let bu: *node = resolvealias(c, unwrapbang(basetn)); + if (bu == nil) { return nil; }; + if (bu.kind == nkind.N_TARRAY) { + let sl: *node = newnode(nkind.N_TSLICE, "", 0, 0); + sl.lhs = bu.lhs; + e.type_ = tinfofornode(c, sl): *void; + return sl; + }; + if (bu.kind == nkind.N_TSLICE) { + e.type_ = tinfofornode(c, basetn): *void; + return basetn; + }; + if (bu.kind == nkind.N_TNAME) { + if (streq(bu.str, "str")) { + let tn: *node = mktname(c, "str"); + e.type_ = tinfofornode(c, tn): *void; + return tn; + }; + }; + if (bu.kind == nkind.N_TPTR && bu.lhs != nil) { + let sl: *node = newnode(nkind.N_TSLICE, "", 0, 0); + sl.lhs = bu.lhs; + e.type_ = tinfofornode(c, sl): *void; + return sl; + }; + return nil; + }; if (k == nkind.N_TRYPROP) { // success unwrap: the success-variant type of operand's // tagged union. diff --git a/selfhost/cmd/wwdump/main.combined.ww b/selfhost/cmd/wwdump/main.combined.ww index 2174c258..5f1b0d56 100644 --- a/selfhost/cmd/wwdump/main.combined.ww +++ b/selfhost/cmd/wwdump/main.combined.ww @@ -8769,6 +8769,45 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = { e.type_ = tinfofornode(c, arr): *void; return arr; }; + if (k == nkind.N_SLICE) { + // A.6.2.0a — head-only stamp of the slice expression's overall + // type. Mirrors cstage cmd/wcc/check.c:1214-1228 N_SLICE: peel + // alias on the base; [N]T → []T, []T → []T (return base), str + // → str, *T (non-nil sub) → []T. Slice bounds (e.rhs start, + // e.cond end) are already covered by the post-order dispatch + // at L460-489 (typically N_INTLIT/N_IDENT/N_BIN, all in the + // dispatch list), so we do not double-walk them here. + // Documented cstage divergence: cstage L1227 errors on a + // non-sliceable base; wwstage returns nil (lenient on miss), + // matching scruttype L656 / A.6.1.5b N_DOT precedent. + let basetn: *node = exprtype(c, e.lhs, nil); + let bu: *node = resolvealias(c, unwrapbang(basetn)); + if (bu == nil) { return nil; }; + if (bu.kind == nkind.N_TARRAY) { + let sl: *node = newnode(nkind.N_TSLICE, "", 0, 0); + sl.lhs = bu.lhs; + e.type_ = tinfofornode(c, sl): *void; + return sl; + }; + if (bu.kind == nkind.N_TSLICE) { + e.type_ = tinfofornode(c, basetn): *void; + return basetn; + }; + if (bu.kind == nkind.N_TNAME) { + if (streq(bu.str, "str")) { + let tn: *node = mktname(c, "str"); + e.type_ = tinfofornode(c, tn): *void; + return tn; + }; + }; + if (bu.kind == nkind.N_TPTR && bu.lhs != nil) { + let sl: *node = newnode(nkind.N_TSLICE, "", 0, 0); + sl.lhs = bu.lhs; + e.type_ = tinfofornode(c, sl): *void; + return sl; + }; + return nil; + }; if (k == nkind.N_TRYPROP) { // success unwrap: the success-variant type of operand's // tagged union.