selfhost/cmd/wcc: stamp e.type_ for N_ARRLIT (A.6.1.7)

Port head-only of cstage cmd/wcc/check.c:1198-1211 to exprtype's
new N_ARRLIT arm:

  - Walk e.list, skip the N_FIELD repeat marker (lib/ww/parse/
    expr.ww:100-107).
  - First non-skipped element via recursive exprtype → elt.
  - Count non-skipped elements.
  - Empty list → mktname("i32") per cstage L1209.
  - Synthesize N_TARRAY{lhs=elt, rhs=INTLIT{uval=count}}, stamp
    tinfofornode, return.

One documented divergence from cstage: the inline type_default
lift (cstage L1206 — untyped_int → i32 etc) is skipped. Wwstage
uniformly returns the AST-level untyped name and defers defaulting
to the assignability sink; the N_INTLIT arm (check.ww:1388-1392)
and alloc-value-form (check.ww:1509) follow the same shape, so
defaulting here would be the outlier. No cgen consumer reads
e.type_ on N_ARRLIT today (verified via grep of cgen*.ww); A.6.3
will move the default to the read site or hoist a typedefault
helper — out of α scope.

α scope per Drew (ref/hare/hare/ast/expr.ha:215-218 — Hare's
array_literal is the uniform `{expand, values}` shape, no
named/anonymous split, so head-only is the natural cadence). No
hint plumbing, no unify check on mixed-type elements (cstage uses
first-element-wins).

Phase 1 A.6 step 7 of ~8 — closes the A.6.1 per-kind stamp series.
A.6.2 next: post-checker assertion that every expression node has
type_ set + fail-suite gap sweep.

Verified 132/132 incl. 995_self_rebuild byte-identity.
This commit is contained in:
2026-05-21 19:53:31 +09:00
parent 5f19015e16
commit 0e1ab38586
3 changed files with 123 additions and 0 deletions

View File

@@ -8728,6 +8728,47 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = {
e.type_ = tinfofornode(c, e.lhs): *void;
return e.lhs;
};
if (k == nkind.N_ARRLIT) {
// A.6.1.7 — head-only stamp of the array-lit's overall type.
// Mirror cstage cmd/wcc/check.c:1198-1211: walk elements,
// skip the `...` repeat sentinel (parse/expr.ww:101-105),
// first-element-wins for the elem type, count non-skipped
// elements, synthesize an N_TARRAY{elt, INTLIT count}. Empty
// list defaults to `[0]i32` per cstage L1209. Per-element
// stamps still fire via the post-order dispatch at L460-489
// (N_ARRLIT is in the kind list since A.6.0); the re-walk in
// the loop below is tinfocache-idempotent (L467).
//
// Documented cstage divergence: cstage L1206 applies
// type_default to lift untyped_int → i32 etc; wwstage stamps
// the raw exprtype result, matching the alloc-value-form
// precedent at L1509. Consumers default-type via the declared
// `let` slot until A.6.3 lands. Mixed-type elements follow
// cstage first-element-wins; no unify check (future scope).
let elt: *node = nil;
let count: u64 = 0u64;
let it: *node = e.list;
for (it != nil) {
let skip: bool = false;
if (it.kind == nkind.N_FIELD) {
if (streq(it.str, "...")) { skip = true; };
};
if (!skip) {
let t: *node = exprtype(c, it, nil);
if (elt == nil) { elt = t; };
count += 1u64;
};
it = it.next;
};
if (elt == nil) { elt = mktname(c, "i32"); };
let arr: *node = newnode(nkind.N_TARRAY, "", 0, 0);
arr.lhs = elt;
let cn: *node = newnode(nkind.N_INTLIT, "", 0, 0);
cn.uval = count;
arr.rhs = cn;
e.type_ = tinfofornode(c, arr): *void;
return arr;
};
if (k == nkind.N_TRYPROP) {
// success unwrap: the success-variant type of operand's
// tagged union.

View File

@@ -1796,6 +1796,47 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = {
e.type_ = tinfofornode(c, e.lhs): *void;
return e.lhs;
};
if (k == nkind.N_ARRLIT) {
// A.6.1.7 — head-only stamp of the array-lit's overall type.
// Mirror cstage cmd/wcc/check.c:1198-1211: walk elements,
// skip the `...` repeat sentinel (parse/expr.ww:101-105),
// first-element-wins for the elem type, count non-skipped
// elements, synthesize an N_TARRAY{elt, INTLIT count}. Empty
// list defaults to `[0]i32` per cstage L1209. Per-element
// stamps still fire via the post-order dispatch at L460-489
// (N_ARRLIT is in the kind list since A.6.0); the re-walk in
// the loop below is tinfocache-idempotent (L467).
//
// Documented cstage divergence: cstage L1206 applies
// type_default to lift untyped_int → i32 etc; wwstage stamps
// the raw exprtype result, matching the alloc-value-form
// precedent at L1509. Consumers default-type via the declared
// `let` slot until A.6.3 lands. Mixed-type elements follow
// cstage first-element-wins; no unify check (future scope).
let elt: *node = nil;
let count: u64 = 0u64;
let it: *node = e.list;
for (it != nil) {
let skip: bool = false;
if (it.kind == nkind.N_FIELD) {
if (streq(it.str, "...")) { skip = true; };
};
if (!skip) {
let t: *node = exprtype(c, it, nil);
if (elt == nil) { elt = t; };
count += 1u64;
};
it = it.next;
};
if (elt == nil) { elt = mktname(c, "i32"); };
let arr: *node = newnode(nkind.N_TARRAY, "", 0, 0);
arr.lhs = elt;
let cn: *node = newnode(nkind.N_INTLIT, "", 0, 0);
cn.uval = count;
arr.rhs = cn;
e.type_ = tinfofornode(c, arr): *void;
return arr;
};
if (k == nkind.N_TRYPROP) {
// success unwrap: the success-variant type of operand's
// tagged union.

View File

@@ -8728,6 +8728,47 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = {
e.type_ = tinfofornode(c, e.lhs): *void;
return e.lhs;
};
if (k == nkind.N_ARRLIT) {
// A.6.1.7 — head-only stamp of the array-lit's overall type.
// Mirror cstage cmd/wcc/check.c:1198-1211: walk elements,
// skip the `...` repeat sentinel (parse/expr.ww:101-105),
// first-element-wins for the elem type, count non-skipped
// elements, synthesize an N_TARRAY{elt, INTLIT count}. Empty
// list defaults to `[0]i32` per cstage L1209. Per-element
// stamps still fire via the post-order dispatch at L460-489
// (N_ARRLIT is in the kind list since A.6.0); the re-walk in
// the loop below is tinfocache-idempotent (L467).
//
// Documented cstage divergence: cstage L1206 applies
// type_default to lift untyped_int → i32 etc; wwstage stamps
// the raw exprtype result, matching the alloc-value-form
// precedent at L1509. Consumers default-type via the declared
// `let` slot until A.6.3 lands. Mixed-type elements follow
// cstage first-element-wins; no unify check (future scope).
let elt: *node = nil;
let count: u64 = 0u64;
let it: *node = e.list;
for (it != nil) {
let skip: bool = false;
if (it.kind == nkind.N_FIELD) {
if (streq(it.str, "...")) { skip = true; };
};
if (!skip) {
let t: *node = exprtype(c, it, nil);
if (elt == nil) { elt = t; };
count += 1u64;
};
it = it.next;
};
if (elt == nil) { elt = mktname(c, "i32"); };
let arr: *node = newnode(nkind.N_TARRAY, "", 0, 0);
arr.lhs = elt;
let cn: *node = newnode(nkind.N_INTLIT, "", 0, 0);
cn.uval = count;
arr.rhs = cn;
e.type_ = tinfofornode(c, arr): *void;
return arr;
};
if (k == nkind.N_TRYPROP) {
// success unwrap: the success-variant type of operand's
// tagged union.