Files
ww/test/wcc/944_alias_accept_run.c
Hojun-Cho 4e174099bd cgen: c2 variant pass-2 structural fallback chases the full NAMED chain — both stages fused
F2a batch-4 c2. Site: cgenutil.ww flatvariantidxt pass-2 (was :2895
at 74195ac, :2903 at 4adf914 post-batch-3) + cs twin cg_tag_for_variant
(cmd/w6c/cgen.c:920-933).

The structural fallback matched a bare source against a NAMED variant
by peeling exactly ONE level (pu.under compare) — a 2-level-alias
variant (type a=*X; type b=a) missed every pass and the widen
defaulted to tag 0, SILENT (the legacy-#17-comment class; that
comment's "task #17" label is retired here — current task #17 is the
unrelated arrlit item).

cs-twin probe DECIDED THE FUSE (spec obligation): v2_alias2 (bare
*i64 into 2-level ptr-alias variant) ran exit 1/1 BOTH-WRONG-IDENTICAL
byte-id pre-fix — cs has the identical single peel, so both stages fix
in this commit (NOT ww-only align-up). NOTE: the cs BINARY is NOT
frozen this train — this commit legitimately moves cstage codegen;
movers must stay bounded to the c2 family (verdict-sweep obligation).
Fix: typeeq/type_eq against tichase/type_chase_named of the variant;
the TY_NAMED gate keeps bare variants in pass-1's exact domain; drew's
>=2-candidate hard-error now guards the CHASED match set (v2_ambig
pins it HOLDING; v2_ambig2 pins the RATIFIED acceptance NARROWING —
2-level twins flip build-accepted-silent-mis-tag -> hard-error BOTH
stages, FLAG-P1/kb4_v2_ambig2). Not nominal-sensitive beyond the
documented proviso — the chase only deepens the structural compare;
nominal choice among >=2 candidates still hard-errors (#209/#211 hold
condition does not trip).

ROUTE-TRACE (rob's §3 ruling) — outcome (b): post-c2 the c4_bool2
shape (2-level bool alias variant, concrete-bool source on ww) runs
0/0 fully BYTE-ID — ww's concrete bool (the #90 stamp divergence,
still open) now reaches the variant through the chased structural
fallback and converges with cs's untyped-funnel route on the same
tag. The graduation therefore belongs to THIS commit: 944
untyped_bool2lvl_bound90 flips K_RUN_CS -> K_RUN here; c5 (#90 stamp
flip) pins its own acceptance rows.

Pin rows (944, all OBSERVED at the c1 base):
  v2_ctrl    bare *T into 1-level NAMED-*T (io vtable shape)
             pre 0/0 byte-id -> post HOLDS (the #15 consumer);
  v2_alias2  bare *T into 2-level alias variant
             pre cs1/ww1 byte-id (both-wrong) -> post 0/0 byte-id;
  v2_struct2 bare anonymous-let struct into 2-level alias variant
             pre cs1/ww1 -> post 0/0 runtime; byte-id SKIPPED via new
             K_RUN_NOID row kind: asm diverges on 3 PRE-EXISTING cglet
             zero-fill lines (cs XORQ+2 stores, ww none — #81 class,
             runtime-correct both, orthogonal to the tag; observed
             identical pre/post). Flip to K_RUN when that closes. The
             adjacent NAMED-source shape is task #95 (ken b4-oracle),
             OUT of this set;
  v2_ambig   bare source matching >=2 NAMED variants (1-level twins)
             -> hard-error HOLDS both stages (K_BUILDERR, diag pinned);
  v2_ambig2  2-LEVEL twin variants — the RATIFIED narrowing pin:
             pre build-ACCEPTED both stages (chase-less fallback
             matched neither twin; silent mis-tag, byte-identical)
             -> post HARD-ERROR both stages (K_BUILDERR, diag pinned).

Corpus: five-mains NEUTRAL vs the c1 build on identical inputs (both
stages — the 2-level variant shape is zero-in-corpus, as the old
comment predicted); cs==ww byte-id holds; 944 181/181.
combined.ww regens ride along.
2026-06-06 01:03:22 +09:00

1229 lines
42 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. 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 */
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 tripwire pin: the UNPROBED single-peel field gates
* (indexed-elem store/read, ptr-chain read, heap fill, tuple-elem
* read, static emit) hard-error on a 2+-level alias over an
* aggregate base instead of emitting a word0 tail. ww accepts and
* runs these — cs-only loud until #73's chase. 1-level controls
* verified per gate (/tmp/revF1 t*c probes). */
{ "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_BUILDERR_CS,
"unswept single-peel gate (#73)" },
/* 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" },
/* 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 src[96], tmpdir[96], errf[96], cmd[1024];
snprintf(src, sizeof src, "/tmp/aac_%d_%d.ww", getpid(), i);
snprintf(tmpdir, sizeof tmpdir, "/tmp/aac_%d_d_%d", getpid(), i);
snprintf(errf, sizeof errf, "/tmp/aac_%d_e_%d", getpid(), i);
FILE *f = fopen(src, "wb");
if (!f) return -1;
fputs(r->src, f);
fclose(f);
mkdir(tmpdir, 0755);
snprintf(cmd, sizeof cmd,
"cd %s && timeout 20 %s build %s >/dev/null 2>%s",
tmpdir, driver, 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);
unlink(src); unlink(errf); rmdir(tmpdir);
return ok ? 0 : 1;
}
if (brc != 0) {
fprintf(stderr, "row[%s]: build via %s failed\n",
r->label, driver);
unlink(src); unlink(errf); rmdir(tmpdir);
return -1;
}
const char *base = strrchr(src, '/');
base = base ? base + 1 : src;
char outbin[256];
snprintf(outbin, sizeof outbin, "%s/%s", tmpdir, base);
char *dot = strrchr(outbin, '.');
if (dot && strcmp(dot, ".ww") == 0) *dot = '\0';
int got = runwait(outbin);
unlink(src); unlink(outbin); unlink(errf); rmdir(tmpdir);
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 */
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;
}