wcc: stamp for-range tuple-binds and massign blank via shared helper
For-range tuple-destructure binders (for (let (k,v) .. s)) and the tuple massign discard _ were left nil-typed: the for-range binders are N_IDENT use-sites and the _ slot, though unbound, has a real element type. Add a shared stamptuplebinds helper — one lockstep walk distributing an N_TTUPLE's per-element types onto a binder chain — refactoring the existing N_MLET destructure loop into it (behavior identical) and adding N_FORRANGE and N_MASSIGN call-sites. _ is STAMPED with its slot's element type (unbound is not untyped), not exempted. Mirrors harec create_unpack_bindings (ref/harec/src/check.c:1354-1419), the routine harec shares between let-unpack and the for-each header (:2308-2317). A prerequisite for arming the wwstage asserttyped bail. byte-id holds (cgen derives binder/elem widths structurally, never off type_; 990-997 green). Extends the 901 gap-corpus with 901_forrange_tuple.ww + 901_massign_blank.ww.
This commit is contained in:
@@ -26,6 +26,8 @@
|
||||
* D module-leaf == type/fn name fnmatch 0 (closed)
|
||||
* D module-leaf == type/fn name random 0 (closed)
|
||||
* E computed enum-member value-expr enum_corpus 0 (closed)
|
||||
* F for-range tuple-destructure bind forrange_tuple 0 (closed)
|
||||
* G tuple multi-assign discard `_` massign_blank 0 (closed)
|
||||
*
|
||||
* Exit code of wwdump_ww is intentionally not gated: the diagnostics
|
||||
* land on stderr regardless of the run's success, and arming the bail
|
||||
@@ -119,6 +121,10 @@ main(void)
|
||||
"D module-leaf == type/fn name", 0 },
|
||||
{ "test/wcc/901_enum_corpus.ww",
|
||||
"E computed enum-member value-expr", 0 },
|
||||
{ "test/wcc/901_forrange_tuple.ww",
|
||||
"F for-range tuple-destructure bind", 0 },
|
||||
{ "test/wcc/901_massign_blank.ww",
|
||||
"G tuple multi-assign discard `_`", 0 },
|
||||
{ NULL, NULL, 0 },
|
||||
};
|
||||
|
||||
@@ -154,6 +160,6 @@ main(void)
|
||||
return 1;
|
||||
}
|
||||
printf("asserttyped_gap: ww-stage checker warn set matches manifest "
|
||||
"on %d gap-corpus fixtures (C pinned, A+B+D+E closed)\n", n);
|
||||
"on %d gap-corpus fixtures (C pinned, A+B+D+E+F+G closed)\n", n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
24
test/wcc/901_forrange_tuple.ww
Normal file
24
test/wcc/901_forrange_tuple.ww
Normal file
@@ -0,0 +1,24 @@
|
||||
// 901_forrange_tuple — for-range tuple-destructure binder gap fixture
|
||||
// for the 901 asserttyped net (class F). `for (let (k, v) .. s)` over a
|
||||
// `[](i64, i64)` left both binders — and every body use site of them,
|
||||
// plus the N_BIN wrapping them — type_=nil: the N_FORRANGE handler
|
||||
// installed the binders as SK_VAR but never back-filled their element
|
||||
// type, so the N_IDENT exprtype path read a nil decl type. stamptuplebinds
|
||||
// (the shared binder distributor, harec create_unpack_bindings) now peels
|
||||
// the iterable element tuple and stamps each binder, so this reads 0.
|
||||
package main;
|
||||
|
||||
export fn main() i32 = {
|
||||
let buf: [2]i64;
|
||||
buf[0] = 1i64;
|
||||
buf[1] = 2i64;
|
||||
let s: [](i64, i64);
|
||||
s.ptr = buf.ptr: *(i64, i64);
|
||||
s.len = 1;
|
||||
s.cap = 1;
|
||||
let total: i64 = 0i64;
|
||||
for (let (k, v) .. s) {
|
||||
total += k + v;
|
||||
};
|
||||
return total: i32;
|
||||
};
|
||||
25
test/wcc/901_massign_blank.ww
Normal file
25
test/wcc/901_massign_blank.ww
Normal file
@@ -0,0 +1,25 @@
|
||||
// 901_massign_blank — tuple multi-assign discard `_` gap fixture for the
|
||||
// 901 asserttyped net (class G). In `_, a = f()` the blank `_` parses to
|
||||
// an empty-str N_IDENT with no decl, so the generic N_IDENT exprtype path
|
||||
// left it type_=nil (945's own comment documents the gap). The `_` is a
|
||||
// GAP, not an exemption — the slot has a real element type ([]u8 here), so
|
||||
// stamptuplebinds(define=false) stamps it with that element type (harec
|
||||
// drops `_` but still advances the tuple slot). a is pre-declared and
|
||||
// resolves the normal way; this reads 0.
|
||||
package main;
|
||||
|
||||
fn mk() ([]u8, i64) = {
|
||||
let b: str = "hi";
|
||||
let p: []u8;
|
||||
p.ptr = b.ptr;
|
||||
p.len = 2;
|
||||
p.cap = 5;
|
||||
return (p, 7i64);
|
||||
};
|
||||
|
||||
export fn main() i32 = {
|
||||
let a: i64 = 0i64;
|
||||
_, a = mk();
|
||||
if (a != 7) { return 1; };
|
||||
return 0;
|
||||
};
|
||||
Reference in New Issue
Block a user