/* * 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 #include #include #include #include #include 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; }