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.