From f0a8a370772d4a08ff48a0baa13292b09e6f96d5 Mon Sep 17 00:00:00 2001 From: Hojun-Cho Date: Thu, 21 May 2026 21:18:25 +0900 Subject: [PATCH] selfhost/cmd/wcc: stamp e.type_ for N_YIELD (A.6.2.0f) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Documented richer-than-cstage divergence: cstage cmd/wcc/check.c :1708 walks N_YIELD's lhs but does NOT stamp `n->type` — yield is statement-shaped there. Wwstage's A.6.2 invariant requires every post-dispatch kind have `type_` set, so this commit draws in the leaner side. Yield's value type is the operand's type per Hare's unified stmt/expr AST (ref/hare/hare/ast/expr.ha:449-461 — `yield_expr` is on L459 inside the `expr` sum). Bare `yield;` (no operand) stamps void. Same nil-tolerant pass-through template as A.6.2.0e N_SPREAD, plus the bare-yield void variant. A.6.2 step 6 of 8 (γ order). N_MATCH-as-expression next, then the assertion closer. `make test-unit` green; full `make test` batched per option B. --- selfhost/cmd/w6c/main.combined.ww | 17 +++++++++++++++++ selfhost/cmd/wcc/check.ww | 17 +++++++++++++++++ selfhost/cmd/wwdump/main.combined.ww | 17 +++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/selfhost/cmd/w6c/main.combined.ww b/selfhost/cmd/w6c/main.combined.ww index b9295e3a..e80cb000 100644 --- a/selfhost/cmd/w6c/main.combined.ww +++ b/selfhost/cmd/w6c/main.combined.ww @@ -8897,6 +8897,23 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = { if (t != nil) { e.type_ = tinfofornode(c, t): *void; }; return t; }; + if (k == nkind.N_YIELD) { + // A.6.2.0f — pass-through stamp; cstage check.c:1708 does NOT + // stamp N_YIELD (statement-shaped). Wwstage's A.6.2 invariant + // requires every post-dispatch kind have type_ set. Yield's + // value type is the operand's type per Hare's unified stmt/expr + // AST (ref/hare/hare/ast/expr.ha:449-461 — yield_expr is an + // expression with a type). Bare `yield;` (no operand) stamps + // void. + if (e.lhs == nil) { + let v: *node = mktname(c, "void"); + e.type_ = tinfofornode(c, v): *void; + return v; + }; + let t: *node = exprtype(c, e.lhs, nil); + if (t != nil) { e.type_ = tinfofornode(c, t): *void; }; + return t; + }; 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 96a332c2..0b226e51 100644 --- a/selfhost/cmd/wcc/check.ww +++ b/selfhost/cmd/wcc/check.ww @@ -1933,6 +1933,23 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = { if (t != nil) { e.type_ = tinfofornode(c, t): *void; }; return t; }; + if (k == nkind.N_YIELD) { + // A.6.2.0f — pass-through stamp; cstage check.c:1708 does NOT + // stamp N_YIELD (statement-shaped). Wwstage's A.6.2 invariant + // requires every post-dispatch kind have type_ set. Yield's + // value type is the operand's type per Hare's unified stmt/expr + // AST (ref/hare/hare/ast/expr.ha:449-461 — yield_expr is an + // expression with a type). Bare `yield;` (no operand) stamps + // void. + if (e.lhs == nil) { + let v: *node = mktname(c, "void"); + e.type_ = tinfofornode(c, v): *void; + return v; + }; + let t: *node = exprtype(c, e.lhs, nil); + if (t != nil) { e.type_ = tinfofornode(c, t): *void; }; + return t; + }; 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 7554014f..b12d889b 100644 --- a/selfhost/cmd/wwdump/main.combined.ww +++ b/selfhost/cmd/wwdump/main.combined.ww @@ -8897,6 +8897,23 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = { if (t != nil) { e.type_ = tinfofornode(c, t): *void; }; return t; }; + if (k == nkind.N_YIELD) { + // A.6.2.0f — pass-through stamp; cstage check.c:1708 does NOT + // stamp N_YIELD (statement-shaped). Wwstage's A.6.2 invariant + // requires every post-dispatch kind have type_ set. Yield's + // value type is the operand's type per Hare's unified stmt/expr + // AST (ref/hare/hare/ast/expr.ha:449-461 — yield_expr is an + // expression with a type). Bare `yield;` (no operand) stamps + // void. + if (e.lhs == nil) { + let v: *node = mktname(c, "void"); + e.type_ = tinfofornode(c, v): *void; + return v; + }; + let t: *node = exprtype(c, e.lhs, nil); + if (t != nil) { e.type_ = tinfofornode(c, t): *void; }; + return t; + }; if (k == nkind.N_TRYPROP) { // success unwrap: the success-variant type of operand's // tagged union.