Files
ww/test/wcc/944_alias_accept_run.c
Hojun-Cho ce3a25a0b4 test: contain sepwork scratch per-driver tmpdir, fix /tmp+in-repo leak (#8)
The wcc test drivers ran `ww build <bare-/tmp src>` with no -o, so the
compiler's <stem>.sepwork scratch landed beside the source and was never
cleaned: unbounded /tmp growth (2195 stale dirs observed) that fills tmpfs
and fabricates phantom test failures + silent harness aborts, and for
in-repo fixture builds leaked .sepwork into the tracked tree.

Each leaking build now writes its source + output inside a per-invocation
tmpdir, passes -o <tmpdir>/<stem> so the .sepwork lands inside it, and
rm -rf's the tmpdir on every exit path -- including fopen-fail and the
expected-fail reject builds (scratch is mkdir'd before the build can fail).
`ww run` and explicit-`-o`/byte-id helpers are left as-is; the 990/993
byte-id comparison logic is byte-for-byte unchanged.

Two items filed separately (this commit holds the no-Makefile / no-main.c
rail):
- #13: a stale <src>.s byte-id readback (749) silently no-ops since
  separate-compile emits .s to <ostem>.sepwork/__root.s; documented inline.
- #14: build-system Makefile recipes build selfhost/cmd/*/main.ww with no
  -o and leak main.sepwork in-tree (bounded, gitignored; own commit).

One concern -- sepwork leak hygiene -- across 228 drivers; uniform
transform applied per-file and two-round reviewed. make test: all 402
passed, zero net-new /tmp scratch, zero test-driven in-repo .sepwork.
2026-06-22 23:29:39 +09:00

1355 lines
46 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* 944_alias_accept_run — #5 alias arc F1: cstage acceptance ALIGN-UP
* through the transitive TY_NAMED chase (type_chase_named, promoted to
* cmd/wcc/type.c). harec dealiases at every promotion/cond/assign
* consumer (ref/harec/src/types.c:53 type_dealias; :989-996
* type_is_assignable; src/check.c:1083-1105 type_promote; :2141 if,
* :2515 for, :3229 &&/||, :3572 !) — wwstage already accepted these
* shapes AND ran them Hare-right (F0 census /tmp/f0/livelist.md), so
* the cstage single-peel rejects were the lean side aligned UP.
*
* row | shape | want
* ---------------------+--------------------------------------+-----
* binop_alias_base | myint + int (F0 m1_binop) | 0
* binop_2level | myint2 % int, myu / u32 (m1_binop2) | 0
* ret_through_2level | fn(x: myint2) int = x * 2 | 0
* assign_alias_alias | k1 → k2 (same base; harec dealias- |
* | both admits) | 0
* binop_alias_vs_alias | k1 + k2 — cstage stays LOUD per |
* | harec type_promote ALIAS+ALIAS→NULL | err(cs)
* cond_if/for/bang/ | alias-of-bool at every cond consumer |
* andor/fnparam | (F0 m2_* family) | 0
* assert_stays_loud | alias-bool assert — BOTH stages loud |
* | (F0 2a DISSOLVED-SYMMETRIC; the Hare |
* | widening is parked on #5) | err
* dot_2level | field access via a3=b3=c3=struct |
* | (task #70, ken c3_chain3) | 0
* deref_alias_ptr | *p through pi2=pi=*int | 0
* idx/slice/range_ | index/slice/for-range over 2-level |
* 2level, slice_arg | alias bases (F0 8b) — cs cgen index |
* | family chased (idx_eff + base |
* | classify); ww half landed (#60, F2a |
* | batch 1 tichase) — graduated K_RUN | 0
* arg_2level_* | task #61: alias-NAMED struct PARAM |
* | classify (fwd-ref / lit-init / 40B |
* | 5-eightbyte / f64 SSE class legs + |
* | base control) | 0
* float_alias_param* / | ken-v3 leg: 2-level f64/str/slice |
* str_alias_2level / | aliases at the cgen KIND classifiers |
* slice_alias_param | (slice leg graduated, #60 F2a b1) | 0
* slicefield_* / | reviewer-F1 leg: 2-level alias of |
* strfield_store_2lvl | slice/str as a STRUCT FIELD type — |
* | cgen field gates chased (stores, |
* | struct-lit, walk leaves, reads); |
* | unprobed gates LOUD-tripwired (#73, |
* | K_BUILDERR_CS pin) | 0
* union_store_* + | task #62 Layer-2: alias-NAMED struct |
* union_push_arg | as union member — widen store/push |
* | word0-only; cs half c138605, ww half |
* | F2a batch-2 c2 — graduated K_RUN; |
* | base ctl + #54-bound `as` row loud | 0
* union_slit_* | task #92 (F2a batch-3 c3): alias- |
* | named struct LITERAL into a union — |
* | rhsstructpayload N_STRUCTLIT arm |
* | routed through structlookupchain; |
* | base ctl + 1/2-level + decl order | 0
* nested_alias_field_* | task #71: alias-typed nested-field |
* | store/read/addr-of walks fold to |
* | direct offsets (byte-id graduation, |
* | both decl orders) | 0
*
* K_RUN rows also assert cstage/wwstage asm byte-id (acceptance
* graduations land byte-identical — F0's accept side was wwstage).
* K_RUN_CS / K_BUILDERR_CS rows run the cstage driver only, each
* citing the task that graduates them. K_RUN_CS_WWERR rows also run
* the wwstage driver expecting a LOUD build failure (the bound row's
* job is preventing a silent ww regression while the leg is parked);
* K_RUN_NOID rows run both but waive the byte-id cell, citing the
* blocking task at the row. binop_alias_vs_alias is
* CS-only loud: the wwstage checker stays silent on typed mismatches
* by design (5-lite discipline) — cs pins the harec-parity reject.
* NNN<950, self-contained (/tmp, no imports) — rule-14's selfhost-
* sibling race does not apply (941/944 precedent).
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
static int
runwait(const char *cmd)
{
int rc = system(cmd);
if (rc == -1) return -1;
if (WIFEXITED(rc)) return WEXITSTATUS(rc);
return -1;
}
static int
slurp_eq(const char *a, const char *b)
{
FILE *fa = fopen(a, "rb");
FILE *fb = fopen(b, "rb");
if (!fa || !fb) { if (fa) fclose(fa); if (fb) fclose(fb); return -1; }
int rc = 0;
for (;;) {
int ca = fgetc(fa), cb = fgetc(fb);
if (ca != cb) { rc = -1; break; }
if (ca == EOF) break;
}
fclose(fa); fclose(fb);
return rc;
}
#define K_RUN 0 /* build+run BOTH drivers, exit==want, + byte-id */
#define K_BUILDERR 1 /* build FAILS with experr on BOTH drivers */
#define K_RUN_CS 2 /* cstage only — ww half pending (cite at row) */
#define K_BUILDERR_CS 3 /* cstage-only loud (ww silent by design) */
#define K_RUN_NOID 4 /* build+run BOTH, exit==want, byte-id
* SKIPPED — cite the blocking task */
#define K_RUN_CS_WWERR 5 /* LOUD-HOLD bound row: cstage build+run,
* exit==want; WWSTAGE build must FAIL
* with experr — cite the blocking task */
struct row { const char *label; const char *src; int want;
int kind; const char *experr; };
/* errlog_has — a BUILDERR row must fail WITH its diagnostic; any other
* failure (parse error, crash, hang-kill) is a vacuous reject (940
* precedent). */
static int
errlog_has(const char *path, const char *needle)
{
FILE *f = fopen(path, "rb");
if (!f) return 0;
char buf[8192];
size_t got = fread(buf, 1, sizeof buf - 1, f);
fclose(f);
buf[got] = '\0';
return strstr(buf, needle) != NULL;
}
static const struct row rows[] = {
{ "binop_alias_base",
"package main;\n"
"type myint = int;\n"
"export fn main() i32 = {\n"
" let a: myint = 5;\n"
" let b: int = 3;\n"
" let c = a + b;\n"
" if (c != 8) { return 1; };\n"
" let d: myint = 2;\n"
" if (a * d != 10) { return 2; };\n"
" if (a < b) { return 3; };\n"
" if (a - b != 2) { return 4; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
{ "binop_2level",
"package main;\n"
"type myint = int;\n"
"type myint2 = myint;\n"
"type myu = u32;\n"
"export fn main() i32 = {\n"
" let a: myint2 = 7;\n"
" let b: int = 2;\n"
" if (a % b != 1) { return 1; };\n"
" let u: myu = 10: u32;\n"
" let v: u32 = 3: u32;\n"
" if (u / v != 3: u32) { return 2; };\n"
" if (u + v != 13: u32) { return 3; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
{ "ret_through_2level",
"package main;\n"
"type myint = int;\n"
"type myint2 = myint;\n"
"fn dbl(x: myint2) int = {\n"
" return x * 2;\n"
"};\n"
"export fn main() i32 = {\n"
" let a: myint2 = 21;\n"
" if (dbl(a) != 42) { return 1; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
{ "assign_alias_alias",
"package main;\n"
"type k1 = int;\n"
"type k2 = int;\n"
"export fn main() i32 = {\n"
" let x: k1 = 5;\n"
" let y: k2 = x;\n"
" if (y != 5) { return 1; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
/* harec type_promote: ALIAS+ALIAS → NULL even on a shared base
* (ref/harec/src/check.c:1087-1089). wwstage's checker is silent
* on typed mismatches (5-lite) — cs-only pin. */
{ "binop_alias_vs_alias",
"package main;\n"
"type k1 = int;\n"
"type k2 = int;\n"
"export fn main() i32 = {\n"
" let x: k1 = 5;\n"
" let y: k2 = 3;\n"
" if (x + y != 8) { return 1; };\n"
" return 0;\n"
"};\n", 0, K_BUILDERR_CS, "operands have differing types" },
{ "cond_if",
"package main;\n"
"type myb = bool;\n"
"export fn main() i32 = {\n"
" let b: myb = true;\n"
" if (b) { return 0; };\n"
" return 1;\n"
"};\n", 0, K_RUN, NULL },
{ "cond_for",
"package main;\n"
"type myb = bool;\n"
"export fn main() i32 = {\n"
" let b: myb = true;\n"
" let i: int = 0;\n"
" for (b) {\n"
" i = i + 1;\n"
" if (i >= 3) { b = false; };\n"
" };\n"
" if (i != 3) { return 1; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
{ "cond_bang",
"package main;\n"
"type myb = bool;\n"
"export fn main() i32 = {\n"
" let b: myb = false;\n"
" let n = !b;\n"
" if (!n) { return 1; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
{ "cond_andor",
"package main;\n"
"type myb = bool;\n"
"export fn main() i32 = {\n"
" let b: myb = true;\n"
" let c: myb = false;\n"
" if (b && !c) { } else { return 1; };\n"
" if (c || b) { } else { return 2; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
{ "cond_fnparam",
"package main;\n"
"type myb = bool;\n"
"fn pick(b: myb) i32 = {\n"
" if (b) { return 0; };\n"
" return 1;\n"
"};\n"
"export fn main() i32 = {\n"
" let b: myb = true;\n"
" return pick(b);\n"
"};\n", 0, K_RUN, NULL },
{ "assert_stays_loud",
"package main;\n"
"type myb = bool;\n"
"export fn main() i32 = {\n"
" let b: myb = true;\n"
" assert(b);\n"
" return 0;\n"
"};\n", 0, K_BUILDERR, "assert: cond must be bool" },
{ "dot_2level",
"package main;\n"
"type a3 = b3;\n"
"type b3 = c3;\n"
"type c3 = struct { x: size, y: size, z: size };\n"
"export fn main() i32 = {\n"
" if (size(a3) != 24) { return 1; };\n"
" if (size((void | a3)) != 32) { return 2; };\n"
" let v: a3;\n"
" v.x = 1; v.y = 2; v.z = 3;\n"
" if (v.x + v.y + v.z != 6) { return 3; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
{ "deref_alias_ptr",
"package main;\n"
"type pi = *int;\n"
"type pi2 = pi;\n"
"export fn main() i32 = {\n"
" let v: int = 41;\n"
" let p: pi2 = &v;\n"
" if (*p != 41) { return 1; };\n"
" *p = 7;\n"
" if (v != 7) { return 2; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
/* ---- reviewer-F1 find: 2-level alias of slice/str as a STRUCT
* FIELD type. The acceptance above admits every construction; the
* cgen FIELD-TYPE gates single-peeled, so the slice/str 3-word
* arms fell to word0-only scalar tails — SILENT wrong (ww correct,
* every shape LOUD at pristine 738d7f4 = opened by this commit).
* Chased gates: single-dot store (+via-ptr), struct-lit fill,
* chained store-walk leaf, chained-ptr-field store, single-dot /
* via-ptr / chained-walk reads. Each row pins one gate; the
* noise() call clobbers BX/CX so stale-register luck can't pass a
* word0-only header. Unprobed sibling gates are LOUD-tripwired,
* pinned by the #73 row at the end of this block. Rows whose
* `.len` readback rides the chained-dot READ walk entered as
* K_RUN_CS (runtime-correct both stages; cs took the generic
* spine) and graduated to K_RUN with the #71 walk chase. */
{ "slicefield_store_2lvl",
"package main;\n"
"type sl = []int;\n"
"type sl2 = sl;\n"
"type box = struct { s: sl2, n: int };\n"
"export fn main() i32 = {\n"
" let a: [3]int = [700: int, 800: int, 900: int];\n"
" let b: box;\n"
" b.n = 5;\n"
" b.s = a[0:3];\n"
" if (b.n != 5) { return 9; };\n"
" if (b.s[0] != 700) { return 1; };\n"
" if (b.s[2] != 900) { return 2; };\n"
" if (b.s.len != 3) { return 3; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
{ "slicefield_range_2lvl",
"package main;\n"
"type sl = []int;\n"
"type sl2 = sl;\n"
"type box = struct { s: sl2, n: int };\n"
"export fn main() i32 = {\n"
" let a: [3]int = [700: int, 800: int, 900: int];\n"
" let b: box;\n"
" b.s = a[0:3];\n"
" b.n = 5;\n"
" if (b.s.len != 3) { return 1; };\n"
" if (b.s[2] != 900) { return 2; };\n"
" for (let x .. b.s) {\n"
" if (x < 700) { return 3; };\n"
" };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
{ "strfield_store_2lvl",
"package main;\n"
"type s1t = str;\n"
"type s2t = s1t;\n"
"type box = struct { s: s2t, n: int };\n"
"export fn main() i32 = {\n"
" let b: box;\n"
" b.s = \"hello\";\n"
" b.n = 5;\n"
" if (b.s.len != 5) { return 1; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
{ "slicefield_structlit_2lvl",
"package main;\n"
"type sl = []int;\n"
"type sl2 = sl;\n"
"type box = struct { s: sl2, n: int };\n"
"export fn main() i32 = {\n"
" let a: [3]int = [700: int, 800: int, 900: int];\n"
" let b: box = box { s = a[0:3], n = 5: int };\n"
" if (b.n != 5) { return 1; };\n"
" if (b.s.len != 3) { return 2; };\n"
" if (b.s[2] != 900) { return 3; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
{ "slicefield_viaptr_2lvl",
"package main;\n"
"type sl = []int;\n"
"type sl2 = sl;\n"
"type box = struct { s: sl2, n: int };\n"
"export fn main() i32 = {\n"
" let a: [3]int = [700: int, 800: int, 900: int];\n"
" let b: box;\n"
" let p = &b;\n"
" p.s = a[0:3];\n"
" if (p.s.len != 3) { return 1; };\n"
" if (p.s[2] != 900) { return 2; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
{ "slicefield_chainstore_2lvl",
"package main;\n"
"type sl = []int;\n"
"type sl2 = sl;\n"
"type inner = struct { s: sl2 };\n"
"type outer = struct { i: inner };\n"
"export fn main() i32 = {\n"
" let a: [3]int = [700: int, 800: int, 900: int];\n"
" let v: outer;\n"
" v.i.s = a[0:3];\n"
" if (v.i.s.len != 3) { return 1; };\n"
" if (v.i.s[2] != 900) { return 2; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
{ "slicefield_ptrchain_2lvl",
"package main;\n"
"type sl = []int;\n"
"type sl2 = sl;\n"
"type inner = struct { s: sl2, n: int };\n"
"type outer = struct { pi: *inner };\n"
"export fn main() i32 = {\n"
" let a: [3]int = [700: int, 800: int, 900: int];\n"
" let i: inner;\n"
" i.n = 1;\n"
" let v: outer;\n"
" v.pi = &i;\n"
" v.pi.s = a[0:3];\n"
" if (i.s.len != 3) { return 1; };\n"
" if (i.s[2] != 900) { return 2; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
{ "slicefield_chainread_2lvl",
"package main;\n"
"type sl = []int;\n"
"type sl2 = sl;\n"
"type inner = struct { s: sl2 };\n"
"type outer = struct { i: inner };\n"
"fn noise(x: int) int = {\n"
" return x * 7 + 3;\n"
"};\n"
"export fn main() i32 = {\n"
" let a: [3]int = [700: int, 800: int, 900: int];\n"
" let v: outer;\n"
" v.i.s = a[0:3];\n"
" let k = noise(9);\n"
" if (k != 66) { return 9; };\n"
" let w = v.i.s;\n"
" if (w.len != 3) { return 1; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
{ "slicefield_ptrread_2lvl",
"package main;\n"
"type sl = []int;\n"
"type sl2 = sl;\n"
"type box = struct { s: sl2, n: int };\n"
"fn noise(x: int) int = {\n"
" return x * 7 + 3;\n"
"};\n"
"export fn main() i32 = {\n"
" let a: [3]int = [700: int, 800: int, 900: int];\n"
" let b: box;\n"
" b.s = a[0:3];\n"
" let p = &b;\n"
" let k = noise(9);\n"
" if (k != 66) { return 9; };\n"
" let w = p.s;\n"
" if (w.len != 3) { return 1; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
/* whole-field read into a local: cs runtime-correct post-chase
* (the clobbered-register r1b probe). The `let w = b.s` receive
* spine divergence noted at pristine 738d7f4 no longer
* reproduces at the F1-merged base, and ww's `w[i]` read (the
* task-#60 esz half) landed in F2a batch 1 — byte-id + 0/0
* verified, graduated K_RUN. */
{ "slicefield_wholeread_2lvl",
"package main;\n"
"type sl = []int;\n"
"type sl2 = sl;\n"
"type box = struct { s: sl2, n: int };\n"
"fn noise(x: int) int = {\n"
" return x * 7 + 3;\n"
"};\n"
"export fn main() i32 = {\n"
" let a: [3]int = [700: int, 800: int, 900: int];\n"
" let b: box;\n"
" b.s = a[0:3];\n"
" let k = noise(9);\n"
" if (k != 66) { return 9; };\n"
" let w = b.s;\n"
" if (w.len != 3) { return 1; };\n"
" if (w[2] != 900) { return 2; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL }, /* graduated: #60 (F2a batch 1) */
/* #73 GRADUATED (B5-c2): the tripwired single-peel field gates
* (indexed-elem store/read, ptr-chain read, heap fill, tuple-elem
* read, static emit) now chase the field type — the loud bound
* flipped to working 0/0 byte-id. Per-gate-arm rows live in
* 944_alias_cgen_b5_run. */
{ "slicefield_idx_tripwire_73",
"package main;\n"
"type sl = []int;\n"
"type sl2 = sl;\n"
"type box = struct { s: sl2, n: int };\n"
"export fn main() i32 = {\n"
" let a: [3]int = [700: int, 800: int, 900: int];\n"
" let xs: [2]box;\n"
" xs[0].s = a[0:3];\n"
" if (xs[0].s.len != 3) { return 1; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL }, /* graduated: #73 (B5-c2) */
/* Values >255 break the esz=1 prefix-luck; the write-then-read
* pins the IMULQ stride on both the read and write spines. */
{ "idx_2level",
"package main;\n"
"type arr = [4]int;\n"
"type arr2 = arr;\n"
"export fn main() i32 = {\n"
" let a: arr2 = [1000: int, 2000: int, 3000: int, 4000: int];\n"
" if (a[2] != 3000) { return 1; };\n"
" a[1] = 9999;\n"
" if (a[1] != 9999) { return 2; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL }, /* graduated: #60 (F2a batch 1) */
{ "slice_2level",
"package main;\n"
"type sl = []int;\n"
"type sl2 = sl;\n"
"export fn main() i32 = {\n"
" let a: [4]int = [1000: int, 2000: int, 3000: int, 4000: int];\n"
" let s: sl2 = a[1:3];\n"
" if (s.len != 2) { return 1; };\n"
" if (s[0] != 2000) { return 2; };\n"
" s[1] = 7777;\n"
" if (a[2] != 7777) { return 3; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL }, /* graduated: #60 (F2a batch 1) */
{ "range_2level",
"package main;\n"
"type arr = [4]int;\n"
"type arr2 = arr;\n"
"export fn main() i32 = {\n"
" let a: arr2 = [1: int, 2: int, 3: int, 4: int];\n"
" let sum: int = 0;\n"
" for (let x .. a) {\n"
" sum = sum + x;\n"
" };\n"
" if (sum != 10) { return 1; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL }, /* graduated: #60 (F2a batch 1) */
{ "slice_of_alias_arg",
"package main;\n"
"type arr = [4]int;\n"
"type arr2 = arr;\n"
"fn sum(s: []int) int = {\n"
" let t: int = 0;\n"
" for (let x .. s) { t = t + x; };\n"
" return t;\n"
"};\n"
"export fn main() i32 = {\n"
" let a: arr2 = [1000: int, 2000: int, 3000: int, 4000: int];\n"
" let s = a[1:3];\n"
" if (s.len != 2) { return 1; };\n"
" if (s[1] != 3000) { return 2; };\n"
" if (sum(a[0:4]) != 10000) { return 3; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL }, /* graduated: #60 (F2a batch 1) */
/* ---- ken-v3 leg: the acceptance align above opens 2-level
* float/str/slice aliases to the cgen KIND classifiers
* (cg_isfloat/type_isf32/fld_isfloat/type_isstr/type_isslice),
* whose single peel classed them scalar/INT — the f64-alias param
* would read the wrong register class (cs exit 1 SILENT, ww
* correct). The classifiers chase IN THIS SAME COMMIT so the
* widening never ships a loud->silent flip (rule 7; ken root-
* verify /tmp/ken_f1, his v3 row below). */
{ "float_alias_param_kenv3",
"package main;\n"
"type fa = fb;\n"
"type fb = f64;\n"
"fn take(x: fa) f64 = {\n"
" return x * 2.0;\n"
"};\n"
"export fn main() i32 = {\n"
" if (take(1.5) != 3.0) { return 1; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
{ "float_alias_param",
"package main;\n"
"type f1t = f64;\n"
"type f2t = f1t;\n"
"fn half(x: f2t) f64 = {\n"
" return x / 2.0;\n"
"};\n"
"export fn main() i32 = {\n"
" let v: f2t = 5.0;\n"
" if (half(v) != 2.5) { return 1; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
{ "str_alias_2level",
"package main;\n"
"type s1t = str;\n"
"type s2t = s1t;\n"
"fn taillen(s: s2t) int = {\n"
" return (s.len: int);\n"
"};\n"
"export fn main() i32 = {\n"
" let v: s2t = \"hello\";\n"
" if (v.len != 5) { return 1; };\n"
" if (taillen(v) != 5) { return 2; };\n"
" let w: s2t = v;\n"
" if (w.len != 5) { return 3; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
/* slice leg: cs classify fixed; the ww half of the indexed read
* (task-#60 esz family) landed in F2a batch 1. Values >255
* break the esz=1 prefix-luck. */
{ "slice_alias_param",
"package main;\n"
"type b1 = []int;\n"
"type b2 = b1;\n"
"fn first(s: b2) int = {\n"
" return s[0];\n"
"};\n"
"export fn main() i32 = {\n"
" let a: [3]int = [1000: int, 2000: int, 3000: int];\n"
" let s: b2 = a[0:3];\n"
" if (first(s) != 1000) { return 1; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL }, /* graduated: #60 (F2a batch 1) */
/* ---- task #61: cstage alias-NAMED struct PARAM classify.
* The single peel classified a 2-level-alias param SCALAR: caller
* pushed and callee spilled ONE eightbyte, fields read saved-BP/
* return-address garbage (F0 m5_arg/m8b_arg1lit, cs exit 1 SILENT,
* ww correct). Fix = struct_arg_size/aggarg_size/struct_float_
* class + the prologue classify chase. Values are distinct and the
* LAST field is always checked (multi-eightbyte exit-checked). */
{ "arg_2level_fwdref",
"package main;\n"
"type ali = base;\n"
"type base = struct { a: size, b: size, c: size };\n"
"fn take(s: ali) size = {\n"
" return s.a + s.b + s.c;\n"
"};\n"
"export fn main() i32 = {\n"
" let x: ali;\n"
" x.a = 4; x.b = 9; x.c = 13;\n"
" if (take(x) != 26) { return 1; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
{ "arg_2level_litinit",
"package main;\n"
"type st = struct { a: size, b: size, c: size };\n"
"type row = st;\n"
"fn take(s: row) size = {\n"
" return s.a + s.b + s.c;\n"
"};\n"
"export fn main() i32 = {\n"
" let x: st = st { a = 4: size, b = 9: size, c = 13: size };\n"
" if (take(x) != 26) { return 1; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
/* 40B struct: 5 GP eightbytes through the aggarg (>16B) leg. */
{ "arg_2level_5word",
"package main;\n"
"type big = struct { a: size, b: size, c: size, d: size, e: size };\n"
"type big2 = big;\n"
"fn take(s: big2) size = {\n"
" return s.a + s.e;\n"
"};\n"
"export fn main() i32 = {\n"
" let v: big2;\n"
" v.a = 1000; v.b = 2; v.c = 3; v.d = 4; v.e = 5000;\n"
" if (take(v) != 6000) { return 1; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
/* f64-bearing 16B struct: the struct_float_class SSE leg. */
{ "arg_2level_floatclass",
"package main;\n"
"type fs = struct { x: f64, n: size };\n"
"type fs2 = fs;\n"
"fn take(s: fs2) size = {\n"
" if (s.x != 2.5) { return 99; };\n"
" return s.n;\n"
"};\n"
"export fn main() i32 = {\n"
" let v: fs2;\n"
" v.x = 2.5; v.n = 7;\n"
" if (take(v) != 7) { return 1; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
/* control: base-named param spelling stays green + byte-id. */
{ "arg_base_control",
"package main;\n"
"type base = struct { a: size, b: size, c: size };\n"
"fn take(s: base) size = {\n"
" return s.a + s.b + s.c;\n"
"};\n"
"export fn main() i32 = {\n"
" let x: base;\n"
" x.a = 4; x.b = 9; x.c = 13;\n"
" if (take(x) != 26) { return 1; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
/* ---- task #62 Layer-2: alias-NAMED struct as a UNION MEMBER.
* The widen store/push source classify fell past the struct arm
* to the scalar arm — word0-only payload (the banked rows
* /tmp/impl62r_layer2_rows.md; both-wrong-identical at normal
* decl order = gate-blind byte-id). cs half c138605
* (cg_widen_tagged_store/push su chase); ww half F2a batch-2 c2
* (rhsstructpayload -> structlookupchain) — K_RUN, byte-id.
* Values distinct per word; the LAST payload word is always
* checked. The RETURN-position leg stays both-stage divergent —
* cs cgreturn residual, task #89 (ww runtime-correct since c2;
* not pinned here until the cs half lands). */
{ "union_store_norm", /* banked row L2-1 (= F0 m5b_match1) */
"package main;\n"
"type base = struct { a: size, b: size };\n"
"type ali = base;\n"
"export fn main() i32 = {\n"
" let x: ali;\n"
" x.a = 4; x.b = 9;\n"
" let v: (void | ali) = x;\n"
" match (v) {\n"
" case let s: ali => {\n"
" if (s.a != 4) { return 1; };\n"
" if (s.b != 9) { return 2; };\n"
" };\n"
" case void => { return 3; };\n"
" };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
{ "union_store_fwd", /* banked row L2-2 (= F0 m5_match) */
"package main;\n"
"type ali = base;\n"
"type base = struct { a: size, b: size };\n"
"export fn main() i32 = {\n"
" let x: ali;\n"
" x.a = 4; x.b = 9;\n"
" let v: (void | ali) = x;\n"
" match (v) {\n"
" case let s: ali => {\n"
" if (s.a != 4) { return 1; };\n"
" if (s.b != 9) { return 2; };\n"
" };\n"
" case void => { return 3; };\n"
" };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
{ "union_store_3word", /* banked row L2-4: pins the width LOOP */
"package main;\n"
"type base = struct { a: size, b: size, c: size };\n"
"type ali = base;\n"
"export fn main() i32 = {\n"
" let x: ali;\n"
" x.a = 4; x.b = 9; x.c = 3;\n"
" let v: (void | ali) = x;\n"
" match (v) {\n"
" case let s: ali => {\n"
" if (s.a != 4) { return 1; };\n"
" if (s.c != 3) { return 2; };\n"
" };\n"
" case void => { return 3; };\n"
" };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
{ "union_push_arg", /* the cg_widen_tagged_push twin (F1 find) */
"package main;\n"
"type base = struct { a: size, b: size };\n"
"type ali = base;\n"
"fn peek(v: (void | ali)) size = {\n"
" match (v) {\n"
" case let s: ali => { return s.b; };\n"
" case void => { return 0; };\n"
" };\n"
"};\n"
"export fn main() i32 = {\n"
" let x: ali;\n"
" x.a = 4; x.b = 9;\n"
" if (peek(x) != 9) { return 1; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
/* banked row L2-5: the m5b_match0 gold invariant — base spelling
* indistinguishable (ken oracle PART 1.7). */
{ "union_store_base_ctl",
"package main;\n"
"type base = struct { a: size, b: size, c: size };\n"
"export fn main() i32 = {\n"
" let x: base;\n"
" x.a = 4; x.b = 9; x.c = 3;\n"
" let v: (void | base) = x;\n"
" match (v) {\n"
" case let s: base => {\n"
" if (s.a != 4) { return 1; };\n"
" if (s.c != 3) { return 2; };\n"
" };\n"
" case void => { return 3; };\n"
" };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
/* ---- F2a batch-3 c3 (task #92, reviewer-B2 find): the same
* rhsstructpayload widen, sourced from a struct LITERAL instead
* of a local ident — the N_STRUCTLIT arm still did bare
* structlookup, so `ali{...}` into a union fell to the scalar
* widen arm (cs 0 / ww EXIT 1, byte-id NO, pre-existing on
* master at 486f7f8). Graduated by routing the arm through
* structlookupchain (entry gate widened to the literal's N_IDENT
* type-ref leaf — consumer census in the commit body). Values
* distinct per word, LAST word checked. The alias struct-LIT
* LET-INIT zero-fill (task #63) does NOT green at this site —
* probed post-c3, documented there, deliberately no row here. */
{ "union_slit_base_ctl",
"package main;\n"
"type base = struct { a: size, b: size };\n"
"export fn main() i32 = {\n"
" let v: (void | base) = base{a=4000, b=9000};\n"
" match (v) {\n"
" case let s: base => {\n"
" if (s.a != 4000) { return 1; };\n"
" if (s.b != 9000) { return 2; };\n"
" };\n"
" case void => { return 3; };\n"
" };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
{ "union_slit_alias",
"package main;\n"
"type base = struct { a: size, b: size };\n"
"type ali = base;\n"
"export fn main() i32 = {\n"
" let v: (void | ali) = ali{a=4000, b=9000};\n"
" match (v) {\n"
" case let s: ali => {\n"
" if (s.a != 4000) { return 1; };\n"
" if (s.b != 9000) { return 2; };\n"
" };\n"
" case void => { return 3; };\n"
" };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
/* 2-level: the chain walk (structlookupchain's alias loop). */
{ "union_slit_alias2",
"package main;\n"
"type base = struct { a: size, b: size };\n"
"type ali = base;\n"
"type ali2 = ali;\n"
"export fn main() i32 = {\n"
" let v: (void | ali2) = ali2{a=4000, b=9000};\n"
" match (v) {\n"
" case let s: ali2 => {\n"
" if (s.a != 4000) { return 1; };\n"
" if (s.b != 9000) { return 2; };\n"
" };\n"
" case void => { return 3; };\n"
" };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
{ "union_slit_order",
"package main;\n"
"export fn main() i32 = {\n"
" let v: (void | ali) = ali{a=4000, b=9000};\n"
" match (v) {\n"
" case let s: ali => {\n"
" if (s.a != 4000) { return 1; };\n"
" if (s.b != 9000) { return 2; };\n"
" };\n"
" case void => { return 3; };\n"
" };\n"
" return 0;\n"
"};\n"
"type ali = base;\n"
"type base = struct { a: size, b: size };\n", 0, K_RUN, NULL },
/* ---- F2a batch-2 c3/B1: exprprimresolved's N_DOT base walk was
* a hand-rolled 2-peel — a 3-level alias base (or ptr-to-2-level)
* left the cast-source width unknowable on wwstage only, so the
* #33 identity clamp stayed emitted where cstage (castsrcprim,
* F1-chased) skipped it: runtime-correct both, byte-id NO.
* Graduated by the tichase walk; 1/2-level controls held all
* along (the 2-peel covered them by accident). */
{ "castprim_3lvl_base",
"package main;\n"
"type s1 = struct { f: u32 };\n"
"type s2 = s1;\n"
"type s3 = s2;\n"
"export fn main() i32 = {\n"
" let x: s3;\n"
" x.f = 70000;\n"
" let y: u64 = (x.f: u32): u64;\n"
" if (y != 70000) { return 1; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
{ "castprim_ptr2lvl_base",
"package main;\n"
"type s1 = struct { f: u32 };\n"
"type s2 = s1;\n"
"export fn main() i32 = {\n"
" let x: s2;\n"
" x.f = 70000;\n"
" let p: *s2 = &x;\n"
" let y: u64 = (p.f: u32): u64;\n"
" if (y != 70000) { return 1; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
/* 2-level control (was already byte-id pre-c3; pins the accident
* out of existence). */
{ "castprim_2lvl_base_ctl",
"package main;\n"
"type s1 = struct { f: u32 };\n"
"type s2 = s1;\n"
"export fn main() i32 = {\n"
" let x: s2;\n"
" x.f = 70000;\n"
" let y: u64 = (x.f: u32): u64;\n"
" if (y != 70000) { return 1; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
/* ---- F2a batch-2 c4 (rob FINAL RULING (i)): tyassignableuntyped
* full-chase — STRUCTURAL alignment to cs type.c:369-385 / harec
* type_is_assignable; ZERO acceptance graduations in this commit
* (graduations ride task #90). Holds + controls pin the chase as
* behavior-neutral on every reachable shape; the tagged-dst rows
* are the #33 pins (drill semantics unchanged). */
{ "untyped_hold33_pin", /* (void|T) untyped-int init — #33 fixed
* behavior, tagged-dst drill HOLD */
"package main;\n"
"export fn main() i32 = {\n"
" let mn: (void | size) = 5;\n"
" if (!(mn is size)) { return 1; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
{ "untyped_tagdst_2lvl_hold", /* 2-level alias TAGGED dst holds */
"package main;\n"
"type r1 = (void | size);\n"
"type r2 = r1;\n"
"export fn main() i32 = {\n"
" let v: r2 = 5;\n"
" if (!(v is size)) { return 1; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
{ "untyped_str2lvl_ctl", /* masked twin: ww stamps the str
* literal CONCRETE (#14 cluster), the
* shape fallback rescues the tag — 0/0
* all along; documents the rescue */
"package main;\n"
"type sa1 = str;\n"
"type sa2 = sa1;\n"
"export fn main() i32 = {\n"
" let v: (void | sa2) = \"hi\";\n"
" if (!(v is sa2)) { return 1; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
{ "untyped_int2lvl_ctl", /* typeisnum NAMED-recursion control */
"package main;\n"
"type ia1 = i64;\n"
"type ia2 = ia1;\n"
"export fn main() i32 = {\n"
" let v: (void | ia2) = 7;\n"
" if (!(v is ia2)) { return 1; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
{ "untyped_bool1lvl_ctl", /* 1 level: ww passes via the
* fallback's one peel — 0/0 observed */
"package main;\n"
"type ba1 = bool;\n"
"export fn main() i32 = {\n"
" let v: (void | ba1) = true;\n"
" if (!(v is ba1)) { return 1; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
/* GRADUATED at F2a batch-4 c2 (route-trace case (b)): the
* pass-2 full chase alone took this 0/0 byte-id — ww's CONCRETE
* bool (the #90 stamp divergence, still open at c2) now matches
* the 2-level alias variant through the chased structural
* fallback, converging with cs's untyped-funnel route on the
* same tag. #90's stamp flip pins its own rows (c5). */
{ "untyped_bool2lvl_bound90",
"package main;\n"
"type bb1 = bool;\n"
"type bb2 = bb1;\n"
"export fn main() i32 = {\n"
" let v: (void | bb2) = true;\n"
" if (!(v is bb2)) { return 1; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
/* ---- F2a batch-4 c2: flatvariantidxt/cg_tag_for_variant pass-2
* FULL CHASE, fused both stages (probe: v2_alias2 was exit 1/1
* BOTH-WRONG-IDENTICAL pre-fix — the one-level pu unwrap missed
* every pass on a 2-level alias variant, tag 0 silent). v2_ctrl
* pins the #15 io-vtable consumer (1-level, held throughout);
* v2_ambig pins drew's >=2-candidate hard-error applied to the
* CHASED match set. */
{ "v2_ctrl", /* bare *T into 1-LEVEL named-ptr variant (io shape) */
"package main;\n"
"type pc = *i64;\n"
"export fn main() i32 = {\n"
" let x: i64 = 7;\n"
" let v: (void | pc) = &x;\n"
" if (v is pc) { return 0; };\n"
" return 1;\n"
"};\n", 0, K_RUN, NULL },
{ "v2_alias2", /* bare *T into 2-LEVEL alias variant */
"package main;\n"
"type pa = *i64;\n"
"type pb = pa;\n"
"export fn main() i32 = {\n"
" let x: i64 = 7;\n"
" let v: (void | pb) = &x;\n"
" if (v is pb) { return 0; };\n"
" return 1;\n"
"};\n", 0, K_RUN, NULL },
{ "v2_struct2", /* bare (anonymous-let) struct into 2-level alias
* variant. NOID: asm diverges on 3 pre-existing
* cglet zero-fill lines (cs XORQ+2 stores, ww none
* — task #81 class, runtime-correct both, ORTHOGONAL
* to the variant tag). Flip to K_RUN when the
* zero-fill divergence closes. The adjacent
* NAMED-source shape is task #95 (ken b4-oracle),
* out of this fix's set. */
"package main;\n"
"type sa = struct { a: i64, };\n"
"type sb = sa;\n"
"export fn main() i32 = {\n"
" let s: struct { a: i64, } = sa{a=7};\n"
" let v: (void | sb) = s;\n"
" if (v is sb) { return 0; };\n"
" return 1;\n"
"};\n", 0, K_RUN_NOID, NULL },
{ "v2_ambig", /* bare source matching >=2 NAMED variants stays a
* hard error on the CHASED set (drew's proviso) */
"package main;\n"
"type p1 = *i64;\n"
"type p2 = *i64;\n"
"export fn main() i32 = {\n"
" let x: i64 = 7;\n"
" let v: (void | p1 | p2) = &x;\n"
" if (v is p1) { return 0; };\n"
" return 1;\n"
"};\n", 0, K_BUILDERR,
"bare source structurally matches >=2 NAMED variants" },
/* The RATIFIED acceptance-narrowing pin (FLAG-P1, kb4_v2_ambig2):
* 2-LEVEL twin variants. Pre-c2 the chase-less fallback matched
* NEITHER twin — the build ACCEPTED on both stages and ran a
* silent mis-tag (byte-identical, gate-blind). The chased set
* sees both twins structurally -> drew's >=2-candidate
* hard-error, BOTH stages. */
{ "v2_ambig2",
"package main;\n"
"type q1 = *i64;\n"
"type p1 = q1;\n"
"type q2 = *i64;\n"
"type p2 = q2;\n"
"export fn main() i32 = {\n"
" let x: i64 = 7;\n"
" let v: (void | p1 | p2) = &x;\n"
" if (v is p1) { return 0; };\n"
" return 1;\n"
"};\n", 0, K_BUILDERR,
"bare source structurally matches >=2 NAMED variants" },
/* ---- F2a batch-4 c3: check.ww behavior pair (ww-only align-up;
* both cs twins already full-chase: spread check.c:755, &len/cap
* check.c:1198-1201). */
{ "sp_alias1", /* 1-level spread control — held throughout */
"package main;\n"
"type inner = (i64 | str);\n"
"type outer = (...inner | void);\n"
"export fn main() i32 = {\n"
" let v: outer = 5: i64;\n"
" if (v is i64) { return 0; };\n"
" return 1;\n"
"};\n", 0, K_RUN, NULL },
{ "sp_alias2", /* 2-level-alias inner union spread into outer
* tagged: pre = runtime 0/0 BUT byte-DIVERGE (ww
* sized the box off the SURFACE member — $48 vs $32
* frame); post = 0/0 byte-id (spliced). */
"package main;\n"
"type inner = (i64 | str);\n"
"type inner2 = inner;\n"
"type outer = (...inner2 | void);\n"
"export fn main() i32 = {\n"
" let v: outer = 5: i64;\n"
" if (v is i64) { return 0; };\n"
" return 1;\n"
"};\n", 0, K_RUN, NULL },
{ "amplen_plain", /* &s.len plain []i64 base control */
"package main;\n"
"export fn main() i32 = {\n"
" let s: []i64 = [1, 2, 3];\n"
" let p: *i64 = &s.len;\n"
" if (*p == 3) { return 0; };\n"
" return 1;\n"
"};\n", 0, K_RUN, NULL },
/* &len/cap through alias bases (param route — the let-init
* spelling is blocked upstream by the #83-documented "let: not
* assignable" acceptance divergence): the c3-B2 chase aligns the
* CHECKER stamp to cs, but the ww cgen ADDRESS tail stays loud
* ("unsupported address-of shape") for ALL alias bases 1+ level —
* task #96 (ken b4-oracle), outside check.ww's grant. Rows
* graduate K_RUN when #96 lands. */
{ "amplen1_bound96",
"package main;\n"
"type sl1 = []i64;\n"
"fn check(s: sl1) i32 = {\n"
" let p: *i64 = &s.len;\n"
" if (*p == 3) { return 0; };\n"
" return 1;\n"
"};\n"
"export fn main() i32 = {\n"
" let b: []i64 = [1, 2, 3];\n"
" return check(b);\n"
"};\n", 0, K_RUN_CS_WWERR,
"unsupported address-of shape" }, /* ww: task #96 */
{ "amplen2_bound96",
"package main;\n"
"type sl1 = []i64;\n"
"type sl2 = sl1;\n"
"fn check(s: sl2) i32 = {\n"
" let p: *i64 = &s.len;\n"
" if (*p == 3) { return 0; };\n"
" return 1;\n"
"};\n"
"export fn main() i32 = {\n"
" let b: []i64 = [1, 2, 3];\n"
" return check(b);\n"
"};\n", 0, K_RUN_CS_WWERR,
"unsupported address-of shape" }, /* ww: task #96 */
{ "ampcap2_bound96",
"package main;\n"
"type sl1 = []i64;\n"
"type sl2 = sl1;\n"
"fn check(s: sl2) i32 = {\n"
" let p: *i64 = &s.cap;\n"
" if (*p == 3) { return 0; };\n"
" return 1;\n"
"};\n"
"export fn main() i32 = {\n"
" let b: []i64 = [1, 2, 3];\n"
" return check(b);\n"
"};\n", 0, K_RUN_CS_WWERR,
"unsupported address-of shape" }, /* ww: task #96 */
/* ---- F2a batch-4 c4 (#80): bare-binder N_FORRANGE over an
* alias-typed iterable — the binder type derivation read the
* scrutinee's type expr without dealiasing (N_TNAME missed the
* N_TSLICE/N_TARRAY tests), binder fell to the untyped fallback
* decl, `untyped_lit * rangevar` asserttyped-bailed on ww only
* (cs scope_define types the elem). Re-probed AFTER c1 per spec:
* still live (the chase set didn't cover this AST-keyed read).
* Tuple-destructure arm sibling FILED (task #97, double-masked). */
{ "rangevar_alias2", /* the #80 repro shape */
"package main;\n"
"type slk = []int;\n"
"export fn main() i32 = {\n"
" let a: [4]int = [10: int, 20: int, 30: int, 40: int];\n"
" let t: slk = a[2:];\n"
" if (t.len != 2) { return 1; };\n"
" if (t.cap != 2) { return 2; };\n"
" let sum: int = 0;\n"
" for (let x .. t) { sum = sum + 0 * x + 1; };\n"
" if (sum != 2) { return 3; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
{ "rangevar_plain_ctl", /* non-alias control — held throughout */
"package main;\n"
"export fn main() i32 = {\n"
" let a: [4]int = [10: int, 20: int, 30: int, 40: int];\n"
" let t: []int = a[2:];\n"
" let sum: int = 0;\n"
" for (let x .. t) { sum = sum + 0 * x + 1; };\n"
" if (sum != 2) { return 3; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
/* BOUND expected-state row (#199α + #90): untyped literal into a
* NESTED-tagged alias-wrapped variant. cs CHECKER loud-rejects —
* the #199α ww-stricter no-transitive-drill rule (type.c:316-324);
* ww's node-keyed checker ACCEPTS and the binary runs exit 0
* (observed post-c4; the harness has no cs-reject+ww-runs mode,
* so the ww half is pinned via #90's metadata, not here). The c4
* pu-chase aligned the CGEN drill structure to cs; the acceptance
* gate is check.ww — batch-4 aligns ww down, then this row flips
* to K_BUILDERR (loud BOTH). */
{ "untyped_nestvar_bound",
"package main;\n"
"type inner = (i64 | str);\n"
"type inner2 = inner;\n"
"export fn main() i32 = {\n"
" let v: (void | inner2) = 7;\n"
" if (v is void) { return 1; };\n"
" return 0;\n"
"};\n", 0, K_BUILDERR_CS, "not assignable" },
/* ---- task #71 (rob probe-ruled F1 enrollment): nested fields
* whose TYPES are aliases. The chained-dot store/read/addr-of
* walks single-peeled each hop, aborted on the alias, and fell
* to the generic PUSHQ/LEAQ/ADDQ/POPQ address spine — runtime-
* correct but byte-id NO vs wwstage's folded direct offsets.
* Chasing the walks converges cs onto the direct arm = ww's asm.
* Distinct values; the LAST field of the SECOND member checked. */
{ "nested_alias_field_norm",
"package main;\n"
"type fa = inner;\n"
"type inner = struct { a: size, b: size };\n"
"type outer = struct { x: fa, y: fa };\n"
"export fn main() i32 = {\n"
" let v: outer;\n"
" v.x.a = 4; v.x.b = 9;\n"
" v.y.a = 7; v.y.b = 3;\n"
" if (v.x.b != 9) { return 1; };\n"
" if (v.y.b != 3) { return 2; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
{ "nested_alias_field_fwd",
"package main;\n"
"type outer = struct { x: fa, y: fa };\n"
"type fa = inner;\n"
"type inner = struct { a: size, b: size };\n"
"export fn main() i32 = {\n"
" let v: outer;\n"
" v.x.a = 4; v.x.b = 9;\n"
" v.y.a = 7; v.y.b = 3;\n"
" if (v.x.b != 9) { return 1; };\n"
" if (v.y.b != 3) { return 2; };\n"
" let pa = &v.y.b;\n"
" *pa = 11;\n"
" if (v.y.b != 11) { return 3; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
/* banked row L2-3 (`v as ali` readback) trips task #54's as-binding
* aggregate-init bound — LOUD both stages today; fold the row into
* #54's pin set on its fold (do not drop). Pinned here as the
* loud-both bound so a silent regression can't hide. */
{ "union_as_bound_54",
"package main;\n"
"type base = struct { a: size, b: size };\n"
"type ali = base;\n"
"export fn main() i32 = {\n"
" let x: ali;\n"
" x.a = 4; x.b = 9;\n"
" let v: (void | ali) = x;\n"
" if (!(v is ali)) { return 1; };\n"
" let w = v as ali;\n"
" if (w.b != 9) { return 2; };\n"
" return 0;\n"
"};\n", 0, K_BUILDERR,
"aggregate init from unhandled rhs shape" },
};
static int
run_driver(const char *driver, const struct row *r, int i)
{
char tmpdir[96], src[160], errf[160], outbin[160], cmd[1024], rmcmd[200];
snprintf(tmpdir, sizeof tmpdir, "/tmp/aac_%d_d_%d", getpid(), i);
mkdir(tmpdir, 0755);
snprintf(src, sizeof src, "%s/aac_%d_%d.ww", tmpdir, getpid(), i);
snprintf(errf, sizeof errf, "%s/err", tmpdir);
snprintf(outbin, sizeof outbin, "%s/aac_%d_%d", tmpdir, getpid(), i);
snprintf(rmcmd, sizeof rmcmd, "rm -rf %s", tmpdir);
FILE *f = fopen(src, "wb");
if (!f) { runwait(rmcmd); return -1; }
fputs(r->src, f);
fclose(f);
/* #8: -o pins binary + .sepwork scratch under tmpdir; rm -rf on
* every exit path removes the now-non-empty dir. */
snprintf(cmd, sizeof cmd,
"timeout 20 %s build -o %s %s >/dev/null 2>%s",
driver, outbin, src, errf);
int brc = runwait(cmd);
if (r->kind == K_BUILDERR || r->kind == K_BUILDERR_CS) {
int ok = (brc != 0)
&& (r->experr == NULL || errlog_has(errf, r->experr));
if (!ok)
fprintf(stderr, "row[%s]: %s expected loud builderr "
"\"%s\" (brc=%d)\n", r->label, driver,
r->experr ? r->experr : "", brc);
runwait(rmcmd);
return ok ? 0 : 1;
}
if (brc != 0) {
fprintf(stderr, "row[%s]: build via %s failed\n",
r->label, driver);
runwait(rmcmd);
return -1;
}
int got = runwait(outbin);
runwait(rmcmd);
if (got != r->want) {
fprintf(stderr, "row[%s]: %s exit %d, want %d\n",
r->label, driver, got, r->want);
return 1;
}
return 0;
}
static int
asm_byte_identical(const char *bin, const struct row *r, int i)
{
char src[96], cs[96], ws[96], cmd[1024];
snprintf(src, sizeof src, "/tmp/aac_asm_%d_%d.ww", getpid(), i);
snprintf(cs, sizeof cs, "/tmp/aac_asm_%d_%d_c.s", getpid(), i);
snprintf(ws, sizeof ws, "/tmp/aac_asm_%d_%d_w.s", getpid(), i);
FILE *f = fopen(src, "wb");
if (!f) return -1;
fputs(r->src, f);
fclose(f);
snprintf(cmd, sizeof cmd, "%s/w6c -o %s %s 2>/dev/null", bin, cs, src);
if (runwait(cmd) != 0) {
fprintf(stderr, "row[%s]: w6c errored\n", r->label);
unlink(src);
return -1;
}
snprintf(cmd, sizeof cmd, "%s/w6c_ww -o %s %s 2>/dev/null",
bin, ws, src);
if (runwait(cmd) != 0) {
fprintf(stderr, "row[%s]: w6c_ww errored\n", r->label);
unlink(src); unlink(cs);
return -1;
}
int rc = slurp_eq(cs, ws);
if (rc != 0)
fprintf(stderr, "row[%s]: cstage vs wwstage asm differs\n",
r->label);
unlink(src); unlink(cs); unlink(ws);
return rc;
}
int
main(void)
{
const char *bin = getenv("BIN");
if (!bin) bin = "out/bin";
char absbin[2080];
if (bin[0] != '/') {
char cwd[1024];
if (getcwd(cwd, sizeof cwd) == NULL) return 1;
snprintf(absbin, sizeof absbin, "%s/%s", cwd, bin);
bin = absbin;
}
char cdrv[2120], wdrv[2120];
snprintf(cdrv, sizeof cdrv, "%s/ww", bin);
snprintf(wdrv, sizeof wdrv, "%s/ww_ww", bin);
int n = (int)(sizeof rows / sizeof rows[0]);
int total = 0, fail = 0;
for (int i = 0; i < n; i++) {
total++;
if (run_driver(cdrv, &rows[i], i) != 0) fail++;
}
if (access(wdrv, X_OK) == 0) {
for (int i = 0; i < n; i++) {
if (rows[i].kind == K_RUN_CS
|| rows[i].kind == K_BUILDERR_CS)
continue; /* K_RUN_NOID: ww half RUNS */
if (rows[i].kind == K_RUN_CS_WWERR) {
/* LOUD-HOLD: the parked ww leg must keep
* failing LOUD with experr — a silent ww
* accept-and-run is the regression this
* row exists to catch (cite at row). */
struct row tmp = rows[i];
tmp.kind = K_BUILDERR;
total++;
if (run_driver(wdrv, &tmp, i) != 0) fail++;
continue;
}
total++;
if (run_driver(wdrv, &rows[i], i) != 0) fail++;
}
for (int i = 0; i < n; i++) {
if (rows[i].kind != K_RUN)
continue;
total++;
if (asm_byte_identical(bin, &rows[i], i) != 0) fail++;
}
}
if (fail) {
fprintf(stderr, "alias_accept: %d/%d checks failed\n",
fail, total);
return 1;
}
printf("alias_accept: %d/%d ok\n", total, total);
return 0;
}