// letshadow_test — #152 regression pin, migrated from test/wcc/989_letshadow_run.c. // // A `let` binding must NOT be visible during its OWN initializer: // `let x = f(x)` evaluates f(x) in the OUTER scope (Hare: harec check.c clet // runs cexpr before scope_define). Both stages once linked the binding into // the cgen localfind chain BEFORE emitting the init, so the init read the // fresh UNINIT shadow slot — a silent miscompile IDENTICAL on both stages // (byte-id was GREEN over it), now fixed. PRIMITIVE-only (i32) asserts. package letshadow_test; fn id(s: str) str = { return s; }; // Row 1 — PARAM self-shadow (ken's headline, the c3-posix shape): // `let p = id(p)` must read the PARAM p, not the uninit shadow. // "hello" → len(5)*100 + 'h'(104) = 604 (pre-fix: 0, the zero slot). fn paramshadow(p: str) i32 = { let p = id(p); return (p.len: i32) * 100 + (p[0]: i32); }; // Row 2 — LET shadows an OUTER-scope LET in its OWN init. ww rejects // same-block redeclaration, so the inner let lives in a nested block; // its init must read the OUTER x (=5) since the inner x isn't linked // yet → 6 (pre-fix: garbage from the fresh uninit shadow slot). fn letinletinit() i32 = { let x: i32 = 5; let r: i32 = 0; { let x: i32 = x + 1; r = x; }; return r; }; // Row 3 — CONTROL (rename, no shadow). Already correct both pre/post; // pins no-regression. "hi" → 2. fn renamecontrol(p: str) i32 = { let p2 = id(p); return p2.len: i32; }; // Row 4 — UNIFORM-arm proof: arrlit self-ref. The inner `let a = [a, a]` // (nested block; ww rejects same-block redeclaration) shadows the outer // a; both elements must read the OUTER a (=3) → 6. Proves the N_ARRLIT // arm defers the link too, not just the value-init arm. fn arrlitselfref() i32 = { let a: i32 = 3; let r: i32 = 0; { let a: [2]i32 = [a, a]; r = a[0] + a[1]; }; return r; }; @test fn param_self_shadow() void = { assert(paramshadow("hello") == 604i32); }; @test fn let_in_let_init() void = { assert(letinletinit() == 6i32); }; @test fn rename_control() void = { assert(renamecontrol("hi") == 2i32); }; @test fn arrlit_self_ref() void = { assert(arrlitselfref() == 6i32); };