selfhost: port forrange — N_FORRANGE parser + cgen + tuple destructure

This commit is contained in:
2026-05-12 16:21:13 +09:00
parent ce5d66e18a
commit e087c843e9
8 changed files with 1280 additions and 66 deletions

View File

@@ -92,6 +92,33 @@ fn scanlocals(c: *cgen, n: *node) i32 = {
// ".sw_<labelseq>" at cgen time — unique per switch — so it must
// not dedup. Count it here so the frame SUBQ matches.
if (n.kind == nkind.N_SWITCH) { total += 8; };
// `for (let x .. s)` allocates two 8B scratch slots — `.rgi_<seq>`
// (counter) and `.rgl_<seq>` (length) — plus one slot per binding.
// Per-binding sz defaults to 8 (covers scalar primitives + ptrs).
// `str` tuple-fields would need 16 — selfhost doesn't yet emit
// those, so the simple count tracks C cgen for current fixtures.
if (n.kind == nkind.N_FORRANGE) {
total += 16; // .rgi + .rgl scratch
if (n.list != nil) {
let m: *node = n.list;
for (m != nil) {
let bnm: str = m.str;
if (bnm.len == 0) {
total += 8; // discard binding still gets a slot
} else { if (!scanseenmark(c, bnm)) {
total += 8;
};};
m = m.next;
};
} else {
let bnm: str = n.str;
if (bnm.len == 0) {
total += 8;
} else { if (!scanseenmark(c, bnm)) {
total += 8;
};};
};
};
// Match-arm binding (`case let v: T => ...`) gets a slot too.
// Crucially we do NOT dedup these against c.locals: C cgen
// handles a match as an expression with a by-value locals copy,