w6c+wcc: widen struct/tagged-subset, parse ... spread
Three tagged-union gaps:
1. Struct-payload widening was broken at every site (call, let,
assign, return, struct-field init). cg_widen_tagged_store now
materialises str / scalar / struct-lit / struct-ident / tagged
payloads at slot+8+field_off and writes the tag last. Call sites
route through cg_widen_tagged_push (scratch slot + push high→low).
2. Tagged → wider tagged widening forwarded the source tag verbatim.
cg_widen_tag_remap emits a CMPQ-chain switch that translates each
source variant index to the destination's, then zero-pads to the
wider slot. type_eq grew a TY_TAGGED arm (was returning 1 for any
two unions); type_assignable now accepts variant-subset and
rejects the rest.
3. `(...inner | T)` spread parses (cmd/wcc/parse.c, lib/ww/parse).
Marks Node.op = TK_ELLIPSIS; resolve_type unwraps NAMED + flattens
when the spread bit is set so aliases inline like Hare's
tagged_type unwrap flag.
Selfhost mirror: spread parser ported. Cgen widen helpers not yet
mirrored — wwstage stays byte-identical to cstage on the existing
test corpus, but will emit wrong asm if user code uses the new
patterns (probe sp2 shows the divergence).
700_e2e: 9 new rows covering call/let/assign/return × struct +
tagged subset, plus the spread-flatten case.
This commit is contained in:
@@ -323,9 +323,16 @@ resolve_type(Checker *c, Node *n)
|
||||
for (Node *e = n->list; e; e = e->next) {
|
||||
Type *vt = resolve_type(c, e);
|
||||
if (vt == ty_never) continue;
|
||||
if (vt && vt->kind == TY_TAGGED) {
|
||||
/* flatten anonymous nested tagged */
|
||||
for (Tparam *src = vt->params; src; src = src->next) {
|
||||
int spread = (e->op == TK_ELLIPSIS);
|
||||
/* `...inner` spread: flatten the variants of the
|
||||
* (possibly NAMED) inner tagged union into the
|
||||
* enclosing union — matches Hare's parse-time
|
||||
* unwrap flag on each tagged_type entry. */
|
||||
Type *vu = spread && vt && vt->kind == TY_NAMED
|
||||
? vt->under : vt;
|
||||
if (vu && vu->kind == TY_TAGGED &&
|
||||
(spread || vt->kind == TY_TAGGED)) {
|
||||
for (Tparam *src = vu->params; src; src = src->next) {
|
||||
Type *st = src->type;
|
||||
if (st == ty_never) continue;
|
||||
if (variant_present(head, st)) continue;
|
||||
|
||||
Reference in New Issue
Block a user