test: migrate Fam10 alias value tests to @test, carve divergences to pins (#5-C3)

fold-2 chunk C3 (drew's Fam8-13 plan): 8 alias value-row C drivers, 205 rows
re-homed with zero loss -- 177 value -> 8 test/lang/alias_*_test.ww @test
row-tables; 16 reject -> runww //ww:error carriers (both stages reject);
3 cs!=ww value rows -> 2 *_runonly_test.ww (T1, byte-id-excluded, #60/#81);
9 irreducible asymmetric rows -> slim C pins, each ticket-cited and
mutation-proven non-vacuous:
  - accept amplen1/2,ampcap2: cs runs / ww rejects 'unsupported address-of
    shape' (#96)
  - cgen_b5 g73_heapfill: cs!=ww .s + ww link-fails on self-contained alloc;
    compile-smoke pin (#24)
  - cgen_b6 fsarg2_bound: both reject, different msgs, each vs the correct
    stage (#271/#165 cs vs #272/#276/#277 ww)
  - emit_b7 slc/slcstr/slctag _2lvl + slc_plain_ctl: slice-literal static-init
    divergence (#120/#29-kin, ken-d2-oracle)
4 fully-migrated drivers deleted, 4 slimmed-in-place to hold only the
irreducible pins. LANGBYTEID floor 74->82 (8 new byte-id @test files); test
count 388->384 (4 deleted; 4 slimmed kept). do-not-auto-batch files not in
Fam10.
This commit is contained in:
2026-06-24 02:45:09 +09:00
parent 07b3c74ab0
commit 3ee1906497
35 changed files with 2627 additions and 4614 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,118 +1,19 @@
/*
* 944_alias_cgen_b5_run — #5 alias arc F2b (B5 train): cstage cgen
* helper + funnel internalization through type_chase_named (c1), the
* #73 tripwire graduation (c2), the #89 cgreturn return-position widen
* (c3) and the #93 deref-index pointee chase (c4). All cs-only: every
* graduation is a DIVERGE→byte-id flip (cs aligns UP to ww's already-
* chasing asm); zero selfhost/lib bytes move across the train, so the
* _ww binaries stay bit-identical (the crossing detector).
* 944_alias_cgen_b5_run — SLIM CARRIER (#5-C3 alias fold-2). The 27 K_RUN value
* rows migrated to test/lang/alias_cgen_b5_test.ww (@test, cs==ww byte-id); the
* symmetric K_BUILDERR rejects (fill0_ctl, fill2_loud, g73_static_str) to
* test/wcc/data/alias_{fill0_ctl,fill2_loud,g73_static_str}/case.ww runww.
*
* Row sources are ken's B5 oracle probes (/tmp/ken_b5/src,
* .ai/ken-b5-oracle.md + its c1-BOUNDARY ADDENDUM) and the c3/c4
* seeds (/tmp/ken_na, kb4).
*
* row | shape (oracle row) | cs/ww
* --------------------+-------------------------------------+------
* signed_ctl | kb5_signed: 2-lvl alias i8 field |
* | load (fld_issigned) — classifiers |
* | recurse, NO-mover control | 0/0
* targ_2lvl | kb5_targ: 2-lvl alias (void|i64) |
* | param ≤48B (tagged_arg_size) — was |
* | cs LIVE exit-1, c1 graduation | 0/0
* tmem_2lvl | kb5_tmem: >48B memarg twin |
* | (tagged_memarg_size) — graduation | 0/0
* wpush_2lvl | kb5_wpush: call-site widen, literal |
* | arg (:2905 du) — divergence flip | 0/0
* wstore_2lvl/_1lvl | kb5_wstore/wstore1: let-route |
* | controls (du arrives chased |
* | upstream — ken FLAG-1), NEUTRAL | 0/0
* wstore_a_2lvl | kb5_wstore_a: ASSIGN-route re-store |
* | — was both-correct divergent; the |
* | ident-lhs N_ASSIGN gate (:6359) is |
* | cgexpr INLINE, NOT the :2456 funnel |
* | (C1-CORR-2) — GRADUATED at B6-c1 | 0/0
* succ_2lvl | kb5_succ: `?`-success remap over |
* | 2-lvl alias result — was divergent |
* | at RETURN positions only (C1-CORR-1)|
* | — GRADUATED at c3 with the rt chase | 0/0
* null_2lvl | kb5_null: nullable fold + deref |
* | (type_isnullable/nullable_ptr_tag) |
* | — divergence flip | 0/0
* f32p_2lvl | kb5_f32p: nested 2-lvl-alias f64 |
* | field struct param |
* | (struct_float_class) — flip | 0/0
* fill0_ctl | kb5_fill0: named-struct array elem |
* | in struct lit — LOUD both stages |
* | (twin texts share the experr) | err/err
* fill2_loud | kb5_fill2: 1-alias-lvl elem — was |
* | both-wrong-IDENTICAL gate-blind, |
* | then cs-loud/ww-silent for the one |
* | R4-blessed train; #100's ww twin |
* | chase closed the window — LOUD-HOLD |
* | pair, twin texts share the experr | err/err
* tuparg_bound99 / | alias-tuple fn-arg (2-lvl / 1-lvl |
* tuparg1_bound99 / | / cast spelling) + alias-tuple |
* tuparg_cast_bound99/| global. #99 GRADUATED: cstage |
* tupglobal_bound99 | type.c chase accepts the coercion, |
* | wwstage cgendecl.ww spill chase |
* | sizes the alias param 16B (was |
* | dropping SI → t.1 garbage). All |
* | now 0/0 byte-id | 0/0
* ---- c2 (#73 graduation: tripwire deleted, 6 fu gates chased) --
* g73_idxstore / | slice / str / tagged 2-lvl alias |
* g73_strfield / | field at the indexed-elem STORE |
* g73_tagfield | gate — pre = loud "#73" fatal | 0/0
* g73_idxread / | slice arm at the indexed-elem READ, |
* g73_ptrread / | ptr-chain READ and tuple-elem READ |
* g73_tupread | gates — pre = loud "#73" fatal | 0/0
* g73_static_struct | nested-struct arm at the static |
* | struct-lit emit gate — pre = "#73" | 0/0
* g73_heapfill | str arm at the heap struct-lit fill |
* | gate — COMPILE-only pin: bare /tmp |
* | programs never link malloc (both |
* | stages, pre-existing infra) and the |
* | ww deref-field READ carries the |
* | #24-kin field(SB) leak, so run + |
* | byte-id cells are unavailable; the |
* | FILL bytes themselves verified |
* | byte-id by hand (= plain control) | asm
* g73_static_str | str-field static emit: the #73 |
* | fatal gave way to the #129 A.2 |
* | foldability loud — now fill0-class |
* | both-loud (twin texts) | err/err
* ---- c3 (#89: cgreturn return-position widen rt/vu chase) ------
* g89_ret_widen | alias-struct return into union — |
* | was cs word0-to-DX + CX zeroed |
* | (payload dropped, silent exit 1) | 0/0
* g89_ret_errunion | 1-LVL alias error-union return — |
* | cs MOVQ AX,DX dropped e.aux (the |
* | live-truncation seed) | 0/0
* g89_ret_named_ctl | bare NAMED struct return control — |
* | held 0/0 byte-id throughout | 0/0
* ---- c4 (#93: deref-index pointee chase, #263-polarity) --------
* g93_l2_local | `(*p)[2]` over *arr2 (arr2=arr= |
* | [3]int) — cs emitted ONE spurious |
* | MOVQ (AX),AX (pointee ARRAY skip |
* | missed at 2 levels), SEGV 139; ww |
* | was the runtime-correct side | 0/0
* g93_def | def twin: `(*p)[2]` over &D, D a |
* | 2-lvl alias def array (kb5_def93) | 0/0
* g93_1lvl_ctl | 1-level pointee control — held 0/0 |
* | byte-id throughout | 0/0
*
* K_RUN rows build+run BOTH drivers (cs exit==cswant, ww exit==wwwant)
* and assert cstage/wwstage asm byte-id. K_RUN_NOID asserts both run
* cells but waives byte-id — cite the blocking task/commit at the row.
* K_CSERR_WWRUN is the dual-cell bound kind (the inverse of
* 944_alias_accept_run's K_RUN_CS_WWERR): the cstage build must FAIL
* with experr AND the wwstage build+run must exit wwwant — both cells
* asserted so neither the cs loudness nor the ww behavior can drift
* silently while the cited task is parked. NNN<950, self-contained
* /tmp sources, no imports (944 precedent).
* What survives here is the one IRREDUCIBLE K_COMPILES row: both stages
* FRONTEND-compile (w6c / w6c_ww → .s, rc 0) but the asm diverges (the ww
* deref-field READ carries the #24 field(SB) leak) so run + byte-id cells are
* unavailable, and a full `ww build` can't link this self-contained `alloc()`
* case (no rt malloc) — runww //ww:compile links and so cannot host it. The
* pin is the ABSENCE of the pre-c2 cstage #73 fatal at the heap struct-lit
* str-arm fill; the ww-side leak rides task #24. Compile-smoke only.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
@@ -126,407 +27,40 @@ runwait(const char *cmd)
return -1;
}
/* both w6c and w6c_ww must FRONTEND-compile (rc 0); no run, no byte-id (#24). */
static int
slurp_eq(const char *a, const char *b)
run_row(const char *bin, const char *label, const char *src, int i)
{
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;
}
char dir[96], srcf[160], ss[160], rm[200], cmd[2048];
snprintf(dir, sizeof dir, "/tmp/ab5_%d_%d", getpid(), i);
mkdir(dir, 0755);
snprintf(srcf, sizeof srcf, "%s/c.ww", dir);
snprintf(ss, sizeof ss, "%s/o.s", dir);
snprintf(rm, sizeof rm, "rm -rf %s", dir);
#define K_RUN 0 /* build+run BOTH, exits==wants, + byte-id */
#define K_BUILDERR 1 /* build FAILS with experr on BOTH drivers */
#define K_RUN_NOID 2 /* build+run BOTH, exits==wants, byte-id
* SKIPPED — cite the blocking task */
#define K_CSERR_WWRUN 3 /* dual-cell bound row: cstage build must
* FAIL with experr; wwstage build+run,
* exit==wwwant — cite the blocking task */
#define K_COMPILES 4 /* w6c AND w6c_ww must COMPILE (no run, no
* byte-id) — cite why the other cells are
* unavailable at the row */
struct row { const char *label; const char *src;
int cswant; int wwwant; int kind; const char *experr; };
/* errlog_has — a builderr cell 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);
FILE *f = fopen(srcf, "wb");
if (!f) { runwait(rm); return -1; }
fputs(src, f);
fclose(f);
buf[got] = '\0';
return strstr(buf, needle) != NULL;
int ok = 1;
snprintf(cmd, sizeof cmd, "%s/w6c -o %s %s 2>/dev/null", bin, ss, srcf);
if (runwait(cmd) != 0) {
fprintf(stderr, "row[%s]: cstage frontend compile failed\n", label);
ok = 0;
}
snprintf(cmd, sizeof cmd, "%s/w6c_ww -o %s %s 2>/dev/null", bin, ss, srcf);
if (runwait(cmd) != 0) {
fprintf(stderr, "row[%s]: wwstage frontend compile failed\n", label);
ok = 0;
}
runwait(rm);
return ok ? 0 : 1;
}
struct row { const char *label; const char *src; };
static const struct row rows[] = {
/* ---- c1: helper + funnel internalization (the F2c-cs fuse) */
{ "signed_ctl",
"package main;\n"
"type s0 = i8;\n"
"type s1 = s0;\n"
"type st = struct { f: s1, g: s1 };\n"
"export fn main() i32 = {\n"
" let x: st;\n"
" x.f = -5;\n"
" x.g = 3;\n"
" if (x.f >= 0) { return 1; };\n"
" let w: i64 = x.f: i64;\n"
" if (w != -5) { return 2; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL },
/* LIVE c1 graduation: tagged_arg_size single-peeled the 2-level
* alias union param to 0 → wrong arg path (cs exit 1 SILENT, ww
* correct). */
{ "targ_2lvl",
"package main;\n"
"type u0 = (void | i64);\n"
"type u = u0;\n"
"fn h(v: u) i32 = {\n"
" match (v) {\n"
" case let n: i64 => { if (n != 42) { return 1; }; return 0; };\n"
" case void => { return 2; };\n"
" };\n"
"};\n"
"export fn main() i32 = {\n"
" let x: u = 42i64;\n"
" return h(x);\n"
"};\n", 0, 0, K_RUN, NULL },
/* LIVE c1 graduation: the >48B MEMORY-class twin
* (tagged_memarg_size). LAST payload word checked. */
{ "tmem_2lvl",
"package main;\n"
"type big = struct { a: i64, b: i64, c: i64, d: i64, e: i64, f: i64, g: i64 };\n"
"type m0 = (void | big);\n"
"type m = m0;\n"
"fn h(v: m) i32 = {\n"
" match (v) {\n"
" case let s: big => { if (s.g != 77) { return 1; }; return 0; };\n"
" case void => { return 2; };\n"
" };\n"
"};\n"
"export fn main() i32 = {\n"
" let s: big;\n"
" s.a = 11; s.b = 22; s.c = 33; s.d = 44; s.e = 55; s.f = 66; s.g = 77;\n"
" let x: m = s;\n"
" return h(x);\n"
"};\n", 0, 0, K_RUN, NULL },
{ "wpush_2lvl",
"package main;\n"
"type u0 = (void | i64);\n"
"type u = u0;\n"
"fn h(v: u) i32 = {\n"
" match (v) {\n"
" case let n: i64 => { if (n != 42) { return 1; }; return 0; };\n"
" case void => { return 2; };\n"
" };\n"
"};\n"
"export fn main() i32 = {\n"
" return h(42i64);\n"
"};\n", 0, 0, K_RUN, NULL },
{ "wstore_2lvl",
"package main;\n"
"type u0 = (void | i64);\n"
"type u = u0;\n"
"export fn main() i32 = {\n"
" let v: u = 42i64;\n"
" match (v) {\n"
" case let n: i64 => { if (n != 42) { return 1; }; };\n"
" case void => { return 2; };\n"
" };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL },
{ "wstore_1lvl",
"package main;\n"
"type u = (void | i64);\n"
"export fn main() i32 = {\n"
" let v: u = 42i64;\n"
" match (v) {\n"
" case let n: i64 => { if (n != 42) { return 1; }; };\n"
" case void => { return 2; };\n"
" };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL },
/* C1-CORR-2 → GRADUATED at B6-c1: the ident-lhs N_ASSIGN tagged
* store gate (:6359) was the cgexpr INLINE peel B5 could not
* reach; the B6-c1 chase closed it (pins-follow-the-layer, ken
* B6 oracle C1 seed). */
{ "wstore_a_2lvl",
"package main;\n"
"type u0 = (void | i64);\n"
"type u = u0;\n"
"export fn main() i32 = {\n"
" let v: u = void;\n"
" v = 42i64;\n"
" match (v) {\n"
" case let n: i64 => { if (n != 42) { return 1; }; };\n"
" case void => { return 2; };\n"
" };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL }, /* graduated: B6-c1 */
/* C1-CORR-1 → GRADUATED at c3: the residual divergence was
* exactly three paired return-position tag syntheses — the
* cgreturn return-route family; the c3 rt chase closed it
* (pins-follow-the-layer, ken c1-boundary addendum). */
{ "succ_2lvl",
"package main;\n"
"type e0 = !i64;\n"
"type r0 = (i64 | e0);\n"
"type r = r0;\n"
"fn w(bad: bool) r = {\n"
" if (bad) { return 7: e0; };\n"
" return 42;\n"
"};\n"
"fn outer() r = {\n"
" let v = w(false)?;\n"
" return v + 1;\n"
"};\n"
"export fn main() i32 = {\n"
" match (outer()) {\n"
" case let n: i64 => { if (n != 43) { return 1; }; };\n"
" case e0 => { return 2; };\n"
" };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL }, /* graduated: #89 (B5-c3) */
{ "null_2lvl",
"package main;\n"
"type np0 = (*i64 | void);\n"
"type np = np0;\n"
"export fn main() i32 = {\n"
" let n: i64 = 31;\n"
" let p: np = &n;\n"
" match (p) {\n"
" case let q: *i64 => { if (*q != 31) { return 1; }; };\n"
" case void => { return 2; };\n"
" };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL },
{ "f32p_2lvl",
"package main;\n"
"type in0 = struct { a: f64 };\n"
"type in1 = in0;\n"
"type pt = struct { x: in1, y: f64 };\n"
"fn g(p: pt) f64 = { return p.x.a + p.y; };\n"
"export fn main() i32 = {\n"
" let p: pt;\n"
" p.x.a = 2.5;\n"
" p.y = 1.5;\n"
" if (g(p) != 4.0) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL },
/* fill loudness control: named-struct array elem louds on BOTH
* stages with twin texts — the experr substring is shared. */
{ "fill0_ctl",
"package main;\n"
"type el0 = struct { a: i64 };\n"
"type S = struct { arr: [2]el0, n: i64 };\n"
"export fn main() i32 = {\n"
" let s = S { arr = [el0 { a = 5 }, el0 { a = 6 }], n = 3 };\n"
" if (s.arr[0].a + s.arr[1].a + s.n != 14) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_BUILDERR,
"has a str/slice/struct/tagged element" },
/* #100 GRADUATION (closes the B5 re-rule R4 designed divergence):
* pre-B5 this was both-wrong-IDENTICAL-silent (gate-blind #263
* class — both stages accepted and ran exit 1 byte-id); B5-c1's
* cs-only :3195 chase made it cs-loud/ww-silent-wrong for one
* train. The ww twin gate now keys off the chased stamped tinfo
* (cgenutil.ww, task #100) — LOUD-HOLD pair, twin texts share
* the experr tail (fill0-class). */
{ "fill2_loud",
"package main;\n"
"type el0 = struct { a: i64 };\n"
"type el = el0;\n"
"type S = struct { arr: [2]el, n: i64 };\n"
"export fn main() i32 = {\n"
" let s = S { arr = [el0 { a = 5 }, el0 { a = 6 }], n = 3 };\n"
" if (s.arr[0].a + s.arr[1].a + s.n != 14) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_BUILDERR,
"has a str/slice/struct/tagged element" },
/* #99 GRADUATION: both halves landed — the cstage type.c
* type_chase_named tuple-arm (init/fn-arg untyped->alias coercion
* reject->accept) AND the wwstage cgendecl.ww tuple-PARAM spill
* chase (alias param fell to the scalar path, dropped SI, t.1
* garbage). All four rows now build+run 0 on BOTH stages and the
* .s is byte-identical (full 0/0 byte-id, the designed path). */
{ "tuparg_bound99",
"package main;\n"
"type tp0 = (i64, i64);\n"
"type tp = tp0;\n"
"fn f(t: tp) i64 = { return t.0 + t.1; };\n"
"export fn main() i32 = {\n"
" let t: tp = (4, 9);\n"
" if (f(t) != 13) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL },
{ "tuparg1_bound99", /* 1-LEVEL identical — not alias-depth */
"package main;\n"
"type tp = (i64, i64);\n"
"fn f(t: tp) i64 = { return t.0 + t.1; };\n"
"export fn main() i32 = {\n"
" let t: tp = (4, 9);\n"
" if (f(t) != 13) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL },
/* cast spelling — was the LIVE-cs / wrong-ww K_RUN_NOID pin; the
* wwstage spill chase reds the old ww-1 cell and graduates it to
* full 0/0 byte-id alongside its siblings. */
{ "tuparg_cast_bound99",
"package main;\n"
"type tp0 = (i64, i64);\n"
"type tp = tp0;\n"
"fn f(t: tp) i64 = { return t.0 + t.1; };\n"
"export fn main() i32 = {\n"
" let t: tp = (4, 9): tp;\n"
" if (f(t) != 13) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL },
/* alias-tuple module-global — the cstage chase accepts the global
* init and ww already read it correctly; now both 0/0 byte-id. */
{ "tupglobal_bound99",
"package main;\n"
"type tp0 = (i64, i64);\n"
"type tp = tp0;\n"
"let G: tp = (4, 9);\n"
"export fn main() i32 = {\n"
" if (G.0 + G.1 != 13) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL },
/* ---- c2: #73 graduation — the F1 tripwire's containment
* replaced by the designed chase (close-by-construction). Each
* row was the loud "#73" fatal on cs at the c1 tip (ww ok/0);
* post-c2 the gates read the chased field type and every
* runnable arm lands 0/0 byte-id. Values exceed 255 / use the
* LAST element so a word0 tail can't pass by prefix-luck;
* noise() clobbers BX/CX on the read rows. */
{ "g73_idxstore",
"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, 0, K_RUN, NULL },
{ "g73_strfield",
"package main;\n"
"type s1t = str;\n"
"type s2t = s1t;\n"
"type box = struct { s: s2t, n: int };\n"
"fn noise(x: int) int = { return x * 7 + 3; };\n"
"export fn main() i32 = {\n"
" let xs: [2]box;\n"
" xs[1].s = \"hello\";\n"
" xs[1].n = 4;\n"
" let k = noise(9);\n"
" if (k != 66) { return 9; };\n"
" let w = xs[1].s;\n"
" if (w.len != 5) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL },
{ "g73_tagfield",
"package main;\n"
"type tu0 = (void | i64);\n"
"type tu = tu0;\n"
"type box = struct { u: tu, n: int };\n"
"export fn main() i32 = {\n"
" let xs: [2]box;\n"
" xs[0].n = 5;\n"
" xs[0].u = 42i64;\n"
" if (xs[0].n != 5) { return 1; };\n"
" match (xs[0].u) {\n"
" case let v: i64 => { if (v != 42) { return 2; }; };\n"
" case void => { return 3; };\n"
" };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL },
/* store rides the (F1-chased) single-dot via-ptr route so the
* indexed-elem READ gate fires in isolation. */
{ "g73_idxread",
"package main;\n"
"type sl = []int;\n"
"type sl2 = sl;\n"
"type box = struct { s: sl2, n: int };\n"
"fn noise(x: int) int = { return x * 7 + 3; };\n"
"export fn main() i32 = {\n"
" let a: [3]int = [700: int, 800: int, 900: int];\n"
" let xs: [2]box;\n"
" let p = &xs[1];\n"
" p.s = a[0:3];\n"
" p.n = 4;\n"
" let k = noise(9);\n"
" if (k != 66) { return 9; };\n"
" let w = xs[1].s;\n"
" if (w.len != 3) { return 1; };\n"
" if (w[2] != 900) { return 2; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL },
{ "g73_ptrread",
"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"
"fn noise(x: int) int = { return x * 7 + 3; };\n"
"export fn main() i32 = {\n"
" let a: [3]int = [700: int, 800: int, 900: int];\n"
" let i: inner;\n"
" i.s = a[0:3];\n"
" i.n = 1;\n"
" let v: outer;\n"
" v.pi = &i;\n"
" let k = noise(9);\n"
" if (k != 66) { return 9; };\n"
" let w = v.pi.s;\n"
" if (w.len != 3) { return 1; };\n"
" if (w[2] != 900) { return 2; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL },
{ "g73_tupread",
"package main;\n"
"type sl = []int;\n"
"type sl2 = sl;\n"
"export fn main() i32 = {\n"
" let a: [3]int = [700: int, 800: int, 900: int];\n"
" let t: (sl2, int) = (a[0:3], 5);\n"
" let s = t.0;\n"
" if (s.len != 3) { return 1; };\n"
" if (t.1 != 5) { return 2; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL },
{ "g73_static_struct",
"package main;\n"
"type in0 = struct { a: i64, b: i64 };\n"
"type in1 = in0;\n"
"type box = struct { i: in1, n: i64 };\n"
"let g: box = box { i = in0 { a = 4, b = 9 }, n = 5 };\n"
"export fn main() i32 = {\n"
" if (g.n != 5) { return 1; };\n"
" if (g.i.b != 9) { return 2; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL },
/* COMPILE-only pin: bare /tmp programs never link malloc (both
* stages, pre-existing infra) and the ww deref-field READ
* carries the #24-kin field(SB) leak — run + byte-id cells are
* unavailable. The chased FILL bytes were verified byte-id by
* hand against the plain control (/tmp/b5/work). Pre-c2 the cs
* cell was the "#73" fatal — this row pins its absence. */
{ "g73_heapfill",
"package main;\n"
"type s1t = str;\n"
@@ -537,223 +71,9 @@ static const struct row rows[] = {
" if (p.n != 5) { return 1; };\n"
" if (p.s.len != 5) { return 2; };\n"
" return 0;\n"
"};\n", 0, 0, K_COMPILES, NULL },
/* str-field static emit: the #73 fatal gave way to the
* pre-existing #129 A.2 foldability loud — both-loud twin texts
* now (the fill0 class), pinned so neither side regresses to a
* silent emit. */
{ "g73_static_str",
"package main;\n"
"type s1t = str;\n"
"type s2t = s1t;\n"
"type box = struct { s: s2t, n: int };\n"
"let g: box = box { s = \"hello\", n = 5: int };\n"
"export fn main() i32 = {\n"
" if (g.n != 5) { return 1; };\n"
" if (g.s.len != 5) { return 2; };\n"
" return 0;\n"
"};\n", 0, 0, K_BUILDERR,
"#129 A.2 scope" },
/* ---- c3: #89 — the cgreturn rt/vu single peels left a 2-level
* alias RETURN TYPE un-tagged (no tag synthesis at all, the succ
* shape) and an alias-struct SOURCE un-structed (the scalar arm
* shuffled word0 into DX and ZEROED the rest — s.b/e.aux
* dropped, cs silent exit 1, ww runtime-correct since B2-c2). */
{ "g89_ret_widen",
"package main;\n"
"type base = struct { a: size, b: size };\n"
"type ali = base;\n"
"fn mk() (void | ali) = {\n"
" let x: ali;\n"
" x.a = 4; x.b = 9;\n"
" return x;\n"
"};\n"
"export fn main() i32 = {\n"
" match (mk()) {\n"
" case let s: ali => { if (s.b != 9) { return 1; }; };\n"
" case void => { return 2; };\n"
" };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL },
{ "g89_ret_errunion",
"package main;\n"
"type failure = struct { code: i32, aux: size };\n"
"type myerr = failure;\n"
"fn work(bad: bool) (i32 | myerr) = {\n"
" if (bad) {\n"
" let e: myerr;\n"
" e.code = 7; e.aux = 99;\n"
" return e;\n"
" };\n"
" return 42;\n"
"};\n"
"export fn main() i32 = {\n"
" match (work(true)) {\n"
" case let e: myerr => { if (e.aux != 99) { return 1; }; };\n"
" case i32 => { return 2; };\n"
" };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL },
{ "g89_ret_named_ctl",
"package main;\n"
"type base = struct { a: size, b: size };\n"
"fn make() (void | base) = {\n"
" let x: base;\n"
" x.a = 4; x.b = 9;\n"
" return x;\n"
"};\n"
"export fn main() i32 = {\n"
" let v = make();\n"
" match (v) {\n"
" case let s: base => { if (s.b != 9) { return 1; }; };\n"
" case void => { return 2; };\n"
" };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL },
/* ---- c4: #93 — the N_UN(STAR) pointee classify single-peeled,
* so a 2-level alias ARRAY pointee missed the array skip (an
* array value IS its address, #270-1a) and the scalar load
* pulled a[0]'s VALUE as the index base — ONE spurious
* MOVQ (AX),AX, SIGSEGV on cs. ww chases (the runtime-correct
* reference, #263 polarity): cs converges on WW's asm. */
{ "g93_l2_local",
"package main;\n"
"type arr = [3]int;\n"
"type arr2 = arr;\n"
"export fn main() i32 = {\n"
" let a: arr2 = [1000: int, 2000: int, 3000: int];\n"
" let p: *arr2 = &a;\n"
" if ((*p)[2] != 3000) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL },
{ "g93_def",
"package main;\n"
"type arr0 = [3]i64;\n"
"type arr = arr0;\n"
"def D: arr = [18i64, 29i64, 40i64];\n"
"export fn main() i32 = {\n"
" let p: *arr = &D;\n"
" if ((*p)[2] != 40i64) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL },
{ "g93_1lvl_ctl",
"package main;\n"
"type arr = [3]int;\n"
"export fn main() i32 = {\n"
" let a: arr = [1000: int, 2000: int, 3000: int];\n"
" let p: *arr = &a;\n"
" if ((*p)[2] != 3000) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL },
"};\n" },
};
static int
run_driver(const char *driver, const struct row *r, int i, int expect_err,
int want)
{
char tmpdir[96], src[160], outbin[160], errf[160], rmcmd[176], cmd[1024];
snprintf(tmpdir, sizeof tmpdir, "/tmp/ab5_%d_d_%d", getpid(), i);
mkdir(tmpdir, 0755);
snprintf(src, sizeof src, "%s/ab5_%d_%d.ww", tmpdir, getpid(), i);
snprintf(outbin, sizeof outbin, "%s/ab5_%d_%d", tmpdir, getpid(), i);
snprintf(errf, sizeof errf, "%s/err", tmpdir);
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);
snprintf(cmd, sizeof cmd,
"timeout 20 %s build -o %s %s >/dev/null 2>%s",
driver, outbin, src, errf);
int brc = runwait(cmd);
if (expect_err) {
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 != want) {
fprintf(stderr, "row[%s]: %s exit %d, want %d\n",
r->label, driver, got, want);
return 1;
}
return 0;
}
/* asm_compiles — K_COMPILES cell: the named stage compiler must emit
* asm without a fatal. */
static int
asm_compiles(const char *bin, const char *cc, const struct row *r, int i)
{
char src[96], outs[96], cmd[1024];
snprintf(src, sizeof src, "/tmp/ab5_cmp_%d_%d.ww", getpid(), i);
snprintf(outs, sizeof outs, "/tmp/ab5_cmp_%d_%d.s", getpid(), i);
FILE *f = fopen(src, "wb");
if (!f) return -1;
fputs(r->src, f);
fclose(f);
snprintf(cmd, sizeof cmd, "%s/%s -o %s %s 2>/dev/null",
bin, cc, outs, src);
int rc = runwait(cmd);
if (rc != 0)
fprintf(stderr, "row[%s]: %s failed to compile\n",
r->label, cc);
unlink(src); unlink(outs);
return rc != 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/ab5_asm_%d_%d.ww", getpid(), i);
snprintf(cs, sizeof cs, "/tmp/ab5_asm_%d_%d_c.s", getpid(), i);
snprintf(ws, sizeof ws, "/tmp/ab5_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)
{
@@ -767,50 +87,15 @@ main(void)
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 (rows[i].kind == K_COMPILES) {
if (asm_compiles(bin, "w6c", &rows[i], i) != 0)
fail++;
continue;
}
int cs_err = rows[i].kind == K_BUILDERR
|| rows[i].kind == K_CSERR_WWRUN;
if (run_driver(cdrv, &rows[i], i, cs_err,
rows[i].cswant) != 0) fail++;
}
if (access(wdrv, X_OK) == 0) {
for (int i = 0; i < n; i++) {
total++;
if (rows[i].kind == K_COMPILES) {
if (asm_compiles(bin, "w6c_ww",
&rows[i], i) != 0) fail++;
continue;
}
int ww_err = rows[i].kind == K_BUILDERR;
if (run_driver(wdrv, &rows[i], i, ww_err,
rows[i].wwwant) != 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++;
}
}
int fail = 0;
for (int i = 0; i < n; i++)
if (run_row(bin, rows[i].label, rows[i].src, i) != 0) fail++;
if (fail) {
fprintf(stderr, "alias_cgen_b5: %d/%d checks failed\n",
fail, total);
fprintf(stderr, "alias_cgen_b5 (slim): %d/%d rows failed\n", fail, n);
return 1;
}
printf("alias_cgen_b5: %d/%d ok\n", total, total);
printf("alias_cgen_b5 (slim): %d/%d ok\n", n, n);
return 0;
}

View File

@@ -1,133 +1,16 @@
/*
* 944_alias_cgen_b6_run — #5 alias arc F2b (B6 train): the cgen.c
* cgexpr/cgstmt INLINE single-peel sweep through type_chase_named, by
* consumer family — c1 assign/reassign (9 lines), c2 call-arg (8),
* c3 addr-of/field-walk/index spine (14), c4 cast/is/try (10),
* c5 reads/len/globals (8). All cs-only: every graduation is a
* DIVERGE→byte-id flip (cs aligns UP to ww's already-chasing asm);
* zero selfhost/lib bytes move across the train, so the _ww binaries
* stay bit-identical (the crossing detector).
* 944_alias_cgen_b6_run — SLIM CARRIER (#5-C3 alias fold-2). The 23 K_RUN value
* rows migrated to test/lang/alias_cgen_b6_test.ww (@test, cs==ww byte-id); the
* symmetric K_BUILDERR rejects (fsarg0_loud_ctl, try_loud_38b) to
* test/wcc/data/alias_{fsarg0_loud,try_loud_38b}/case.ww runww.
*
* Row sources are ken's B6 first-position oracle probes
* (/tmp/ken_b5/src/kb6_*, .ai/ken-b6-oracle.md, matrix at 4cac1cb).
*
* row | shape (oracle row) | cs/ww
* --------------------+-------------------------------------+------
* ---- c1 (assign/reassign: :6359 :6403/:6405 :6460/:6462 -------
* :6518 + cgstmt :11696 :12047 :13625) -------------------
* streassign_2lvl | kb6_streassign: 2-lvl alias str |
* | reassign `b = a` — cs copied WORD0 |
* | (ptr) ONLY, len/cap stale (silent |
* | exit 1); the :6518 lu gate fell to |
* | the scalar default. LIVE graduation | 0/0
* wstore_a (B5 file) | kb5_wstore_a graduates K_RUN_NOID → |
* | K_RUN in 944_alias_cgen_b5_run.c — |
* | the ident-lhs N_ASSIGN tagged gate |
* | (:6359) was the divergence (ken |
* | C1-CORR-2, he owns the flip) | 0/0
* sreassign_2lvl | kb6_sreassign: whole-struct alias |
* | reassign — latent control | 0/0
* dassign_2lvl | kb6_dassign: (*p).f= over alias ptr |
* | — latent control | 0/0
* ---- c2 (call-arg: :8402 :8435 :8561/:8563/:8577/:8579 --------
* + LOUD-PRESERVING :8829 :8934) ------------------------
* fsarg0_loud_ctl | kb6_fsarg0: PLAIN float-struct from |
* | a non-ident source — #271/#165 loud |
* | BOTH stages (control, twin texts) | err/err
* fsarg2_bound | kb6_fsarg2: 1-alias-level respell — |
* | pre-c2 the :8829 single-peel let |
* | the alias DODGE the fatal; cs GP- |
* | passed by self-consistent luck. |
* | DESIGNED NARROWING: cs now louds |
* | with the pinned #271/#165 text |
* | ("widen what the gate SEES, never |
* | what it ACCEPTS"). ww's loud is its |
* | own alias-return bound (#272/#277 |
* | class, experr_ww) — per-stage texts | err/err
* fsarg_ident_ctl | kb6_fsarg: IDENT-source alias twin |
* | — ident domain out of the :8829 |
* | gate, latent control | 0/0
* sarg_2lvl | kb6_sarg: >16B alias struct arg — |
* | latent (B5 helper chases carry the |
* | type layer) | 0/0
* strarg_2lvl | kb6_strarg: alias str arg — latent | 0/0
* (:8934 tuple loud is WATCH-ONLY: alias spellings are |
* checker-blocked upstream (#86/#99) — the pin is the b5 |
* suite's tuparg_cast_bound99 two-key cells, which must |
* not move.) |
* ---- c3 (addr-of/field-walk/index spine: :3949 :4006 ---------
* :4124/:4128 :5029/:5035/:5052 :5937 :10953/:10956 -----
* :11046/:11052/:11067 :11285, numbering at 4cac1cb) ----
* idxf_2lvl / | kb6_idxf (indexed-elem struct field |
* ampf_2lvl | write+read) / kb6_ampf (&p.b over |
* | alias ptr): the c3 chase moved cs |
* | onto the PLAIN-canonical dedicated |
* | shape (cs_alias == ww_PLAIN, bit- |
* | proven, ken c3-STOP addendum) — and |
* | WWSTAGE was the alias-blind side at |
* | these two sites (generic-but-correct |
* | routes). GRADUATED to full byte-id |
* | by the W2 ww fold, task #102 (the |
* | two gates now chase the alias chain |
* | via structlookupchain). ampf's |
* | pre-c3 byte-id was both-on-generic |
* | identity, not latency (oracle |
* | self-correction) | 0/0
* idxf_plain_ctl / | plain no-alias twins — pin the |
* ampf_plain_ctl | canonical dedicated shape byte-id |
* | BOTH stages (the convergence target |
* | the NOID rows graduate onto) | 0/0
* ampv_2lvl / | W2-review-found #102 sibling: &x.f |
* ampv_plain_ctl | over an alias-NAMED VALUE struct — |
* | the leg one below the &p.f gate had |
* | the same alias-blind bare lookup |
* | (ww_alias != ww_plain; cs_alias == |
* | ww_plain, same bit-proven mechanism).|
* | Chased in the W2 review amendment | 0/0
* chdot_2lvl | kb6_chdot: chained dot over alias |
* | hops — latent control | 0/0
* esub_2lvl | kb6_esub: [3]my32b narrow-elem index |
* | (#61/#101-kin at the INDEX sites) — |
* | latent control | 0/0
* ---- c4 (cast/is/try: :9422 :9598 :9674 :9718 :9819 ----------
* :9986/:9991 :10103/:10105 :10131, numbering at 4cac1cb) -
* strcast_2lvl | kb6_strcast: str→[]u8 over 2-lvl |
* | alias — was both-correct divergent; |
* | the :10103/:10105 tu/fu chase FLIPS |
* | it (cs → ww's unchanged asm, #263 |
* | polarity; alias == plain shape) | 0/0
* idcast_2lvl | kb6_idcast: identity cast over alias |
* | union (Family-C peel) — latent | 0/0
* is_2lvl | kb6_is: `is` over alias union — |
* | latent control | 0/0
* try_loud_38b | kb6_try: `?` on a >48B sret-class |
* | call result — the #38b loud is |
* | ALIAS-INDEPENDENT (documented bound);|
* | :9819's chase is loud-preserving |
* | ONLY — twin texts, shared experr | err/err
* ---- c5 (reads/len/globals: :3820 :7201 :7807 :7900 :9944 ----
* :10224 :10750 :10873, numbering at 4cac1cb) ------------
* tfread_2lvl | kb6_tfread: tagged-union field load |
* | direct + through-ptr over alias |
* | struct — was both-correct divergent; |
* | the :10750/:10873 tag_fu chases FLIP |
* | it (cs → ww's unchanged asm, #263 |
* | polarity; alias == plain shape) | 0/0
* len_2lvl | kb6_len: str+array len over 2-lvl |
* | alias — latent control | 0/0
* gref_2lvl | kb6_gref: alias scalar global value- |
* | ref — latent control | 0/0
* memread_40b | kb6_memread: 40B union, the :9944 |
* | #37 cap-watch row — the `is` chase |
* | keys the cap test on the CHASED size |
* | (mirrors ww taggedmemread); byte- |
* | NEUTRALITY here is the regression net| 0/0
*
* K_RUN rows build+run BOTH drivers (cs exit==cswant, ww exit==wwwant)
* and assert cstage/wwstage asm byte-id. K_BUILDERR rows must FAIL
* with experr on BOTH drivers; experr_ww overrides the ww-side text
* when the two stages loud at DIFFERENT sites (per-stage texts).
* NNN<950, self-contained /tmp sources, no imports (944 precedent).
* What survives here is the one IRREDUCIBLE Group-B row: BOTH stages reject the
* same input but with DIFFERENT diagnostics — a held cs!=ww divergence (a
* rule-10 smell, tracked not silently merged). A single-substring runww
* //ww:error would erase the distinction; this carrier asserts EACH stage's own
* substring. cstage rejects with the #271/#165 SSE-eightbyte-transport reason;
* wwstage rejects with the #272/#276/#277 aggregate-return scalar-default
* reason (the float-bearing alias struct arg from a non-ident source).
*/
#include <stdio.h>
#include <stdlib.h>
@@ -145,35 +28,6 @@ runwait(const char *cmd)
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, exits==wants, + byte-id */
#define K_BUILDERR 1 /* build FAILS with experr on BOTH drivers;
* experr_ww overrides the ww-side text */
#define K_RUN_NOID 2 /* build+run BOTH, exits==wants, byte-id
* SKIPPED — cite the blocking task */
struct row { const char *label; const char *src;
int cswant; int wwwant; int kind;
const char *experr; const char *experr_ww; };
/* errlog_has — a builderr cell 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)
{
@@ -186,69 +40,48 @@ errlog_has(const char *path, const char *needle)
return strstr(buf, needle) != NULL;
}
/* cstage (w6c) rejects with cserr; wwstage (w6c_ww) rejects with wwerr. */
static int
run_row(const char *bin, const char *label, const char *src,
const char *cserr, const char *wwerr, int i)
{
char dir[96], srcf[160], cse[160], wwe[160], ss[160], rm[200], cmd[2048];
snprintf(dir, sizeof dir, "/tmp/ab6_%d_%d", getpid(), i);
mkdir(dir, 0755);
snprintf(srcf, sizeof srcf, "%s/c.ww", dir);
snprintf(cse, sizeof cse, "%s/cs.err", dir);
snprintf(wwe, sizeof wwe, "%s/ww.err", dir);
snprintf(ss, sizeof ss, "%s/o.s", dir);
snprintf(rm, sizeof rm, "rm -rf %s", dir);
FILE *f = fopen(srcf, "wb");
if (!f) { runwait(rm); return -1; }
fputs(src, f);
fclose(f);
int ok = 1;
snprintf(cmd, sizeof cmd, "%s/w6c -o %s %s 2>%s", bin, ss, srcf, cse);
int crc = runwait(cmd);
if (!(crc != 0 && errlog_has(cse, cserr))) {
fprintf(stderr, "row[%s]: cstage expected reject \"%s\" (rc=%d)\n",
label, cserr, crc);
ok = 0;
}
snprintf(cmd, sizeof cmd, "%s/w6c_ww -o %s %s 2>%s", bin, ss, srcf, wwe);
int wrc = runwait(cmd);
if (!(wrc != 0 && errlog_has(wwe, wwerr))) {
fprintf(stderr, "row[%s]: wwstage expected reject \"%s\" (rc=%d)\n",
label, wwerr, wrc);
ok = 0;
}
runwait(rm);
return ok ? 0 : 1;
}
struct row { const char *label; const char *src; const char *cserr;
const char *wwerr; };
static const struct row rows[] = {
/* ---- c1: assign/reassign family */
/* LIVE c1 graduation: the :6518 reassign gate single-peeled the
* 2-level alias str lhs, missed the TY_STR kind test, and fell
* to the scalar default — ONE MOVQ stored the ptr word, len/cap
* kept the dead value's header (cs silent exit 1, ww correct:
* full 3-word {ptr,len,cap} store, Hare value semantics). */
{ "streassign_2lvl",
"package main;\n"
"type ms0 = str;\n"
"type ms = ms0;\n"
"export fn main() i32 = {\n"
" let a: ms = \"hello\";\n"
" let b: ms = \"x\";\n"
" b = a;\n"
" if (len(b) != 5) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL, NULL },
{ "sreassign_2lvl",
"package main;\n"
"type st0 = struct { a: i64, b: i64, c: i64 };\n"
"type st = st0;\n"
"export fn main() i32 = {\n"
" let x: st; x.a = 1; x.b = 2; x.c = 3;\n"
" let y: st; y.a = 0; y.b = 0; y.c = 0;\n"
" y = x;\n"
" if (y.c != 3 || y.b != 2) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL, NULL },
{ "dassign_2lvl",
"package main;\n"
"type st0 = struct { a: i64, b: i64 };\n"
"type st = st0;\n"
"export fn main() i32 = {\n"
" let x: st; x.a = 1; x.b = 2;\n"
" let p: *st = &x;\n"
" (*p).b = 9;\n"
" if (x.b != 9) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL, NULL },
/* ---- c2: call-arg family */
{ "fsarg0_loud_ctl",
"package main;\n"
"type fs0 = struct { x: f64 };\n"
"fn mk() fs0 = {\n"
" let s: fs0; s.x = 2.5;\n"
" return s;\n"
"};\n"
"fn g(p: fs0) f64 = { return p.x; };\n"
"export fn main() i32 = {\n"
" if (g(mk()) != 2.5) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_BUILDERR,
"#271/#165: float-bearing struct arg from a non-ident source",
NULL },
/* DESIGNED ACCEPTANCE NARROWING (B6-c2): pre-c2 cs accepted and
* GP-passed this float struct correct-by-self-consistent-luck
* (caller+callee agreed on the wrong transport) — the :8829
* single peel let a 1-level alias dodge the rule-7 fatal. The
* chase widens what the gate SEES; the loud stays loud for the
* shapes it guards. ww's cell was ALREADY loud at its own
* alias-return bound (#272/#276/#277 class) — different site,
* per-stage experr. */
{ "fsarg2_bound",
"package main;\n"
"type fs0 = struct { x: f64 };\n"
@@ -261,381 +94,11 @@ static const struct row rows[] = {
"export fn main() i32 = {\n"
" if (g(mk()) != 2.5) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_BUILDERR,
"};\n",
"#271/#165: float-bearing struct arg from a non-ident source",
"#272/#276/#277: aggregate return reaches scalar default" },
{ "fsarg_ident_ctl",
"package main;\n"
"type fs0 = struct { x: f64 };\n"
"type fs = fs0;\n"
"fn mk() fs0 = {\n"
" let s: fs0; s.x = 2.5;\n"
" return s;\n"
"};\n"
"fn g(p: fs) f64 = { return p.x; };\n"
"export fn main() i32 = {\n"
" let v: fs = mk();\n"
" if (g(v) != 2.5) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL, NULL },
{ "sarg_2lvl",
"package main;\n"
"type big0 = struct { a: i64, b: i64, c: i64 };\n"
"type big = big0;\n"
"fn g(p: big) i64 = { return p.a + p.c; };\n"
"export fn main() i32 = {\n"
" let s: big; s.a = 4; s.b = 5; s.c = 9;\n"
" if (g(s) != 13) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL, NULL },
{ "strarg_2lvl",
"package main;\n"
"type ms0 = str;\n"
"type ms = ms0;\n"
"fn g(s: ms) i64 = { return len(s): i64; };\n"
"export fn main() i32 = {\n"
" let a: ms = \"hello\";\n"
" if (g(a) != 5) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL, NULL },
/* ---- c3: addr-of/field-walk/index spine */
/* The c3 chase put cs on the PLAIN-canonical dedicated shape
* (cs_alias == ww_PLAIN, bit-proven — ken c3-STOP addendum);
* WWSTAGE was the alias-blind side here: its indexed-elem
* struct-field store gate fell to a generic-but-correct route
* on alias bases. GRADUATED: the W2 ww fold (task #102) chases
* the alias chain (structlookupchain), restoring full byte-id —
* idxf_plain_ctl pins the canonical shape both rows now share. */
{ "idxf_2lvl",
"package main;\n"
"type el0 = struct { a: i64, b: i64 };\n"
"type el = el0;\n"
"export fn main() i32 = {\n"
" let xs: [2]el;\n"
" xs[0].a = 1; xs[0].b = 2;\n"
" xs[1].a = 3; xs[1].b = 4;\n"
" if (xs[1].b != 4 || xs[0].b != 2) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL, NULL }, /* graduated: #102 (W2) */
{ "idxf_plain_ctl",
"package main;\n"
"type el0 = struct { a: i64, b: i64 };\n"
"export fn main() i32 = {\n"
" let xs: [2]el0;\n"
" xs[0].a = 1; xs[0].b = 2;\n"
" xs[1].a = 3; xs[1].b = 4;\n"
" if (xs[1].b != 4 || xs[0].b != 2) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL, NULL },
/* &p.b ptr-field fallback twin of the same re-attribution: the
* pre-c3 byte-id here was BOTH stages on the generic spine
* (gate-blind identity, not M5 latency — oracle self-correction
* banked in ken's c3-STOP addendum). GRADUATED with #102 (W2). */
{ "ampf_2lvl",
"package main;\n"
"type st0 = struct { a: i64, b: i64 };\n"
"type st = st0;\n"
"export fn main() i32 = {\n"
" let x: st; x.a = 1; x.b = 2;\n"
" let p: *st = &x;\n"
" let q: *i64 = &p.b;\n"
" *q = 9;\n"
" if (x.b != 9) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL, NULL }, /* graduated: #102 (W2) */
{ "ampf_plain_ctl",
"package main;\n"
"type st0 = struct { a: i64, b: i64 };\n"
"export fn main() i32 = {\n"
" let x: st0; x.a = 1; x.b = 2;\n"
" let p: *st0 = &x;\n"
" let q: *i64 = &p.b;\n"
" *q = 9;\n"
" if (x.b != 9) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL, NULL },
/* W2-review-found #102 sibling: the value-struct &x.f leg sits
* one leg below the &p.f gate in the same cgun single-DOT arm
* and had the same alias-blind bare structlookup (ww_alias !=
* ww_plain, cs_alias == ww_plain — the c3-STOP bit-test
* mechanism verbatim). Chased in the W2 review amendment. */
{ "ampv_2lvl",
"package main;\n"
"type st0 = struct { a: i64, b: i64 };\n"
"type st = st0;\n"
"export fn main() i32 = {\n"
" let x: st; x.a = 1; x.b = 2;\n"
" let q: *i64 = &x.b;\n"
" *q = 9;\n"
" if (x.b != 9) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL, NULL }, /* amendment: #102 (W2) */
{ "ampv_plain_ctl",
"package main;\n"
"type st0 = struct { a: i64, b: i64 };\n"
"export fn main() i32 = {\n"
" let x: st0; x.a = 1; x.b = 2;\n"
" let q: *i64 = &x.b;\n"
" *q = 9;\n"
" if (x.b != 9) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL, NULL },
{ "chdot_2lvl",
"package main;\n"
"type in0 = struct { v: i64 };\n"
"type in1 = in0;\n"
"type out0 = struct { inner: in1, n: i64 };\n"
"type out1 = out0;\n"
"export fn main() i32 = {\n"
" let s: out1; s.inner.v = 7; s.n = 3;\n"
" let p: *out1 = &s;\n"
" if (p.inner.v != 7) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL, NULL },
{ "esub_2lvl",
"package main;\n"
"type my32 = u32;\n"
"type my32b = my32;\n"
"export fn main() i32 = {\n"
" let xs: [3]my32b;\n"
" xs[0] = 5; xs[1] = 6; xs[2] = 7;\n"
" if (xs[0]: i64 + xs[1]: i64 + xs[2]: i64 != 18) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL, NULL },
/* #101: NARROW-alias struct-FILL stride (the cgstructlitfill
* :4791 leg, twin of esub_2lvl's INDEX leg). Pre-fold ww sized
* the [3]my32 element off primsize("my32")=0 → 8B-default stride,
* so the fill stored at -24/-16/-8 and field n collided with
* arr[2] (run exit 1); cs chased my32→u32→4 (MOVL stride-4). The
* aliasprimsize route aligns ww UP — kw1_101 was the SOLE corpus
* mover (cs0/ww1 byteid-NO → byteid-YES + run 0). */
{ "kw1_101",
"package main;\n"
"type my32 = u32;\n"
"type S = struct { arr: [3]my32, n: int };\n"
"export fn main() i32 = {\n"
" let s = S { arr = [10u32, 20u32, 30u32], n = 4 };\n"
" if (s.arr[0] + s.arr[1] + s.arr[2] != 60u32) { return 1; };\n"
" if (s.n != 4) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL, NULL },
/* #101 control: a DIFFERENT narrow width (u16, stride-2 MOVW)
* proves the routed esz is width-general, not a 4-only patch.
* fld n must survive the fill untouched. */
{ "kw1_ctl16",
"package main;\n"
"type my16 = u16;\n"
"type S2 = struct { arr: [4]my16, n: int };\n"
"export fn main() i32 = {\n"
" let s = S2 { arr = [1u16, 2u16, 3u16, 4u16], n = 9 };\n"
" if (s.arr[0] + s.arr[1] + s.arr[2] + s.arr[3] != 10u16) { return 1; };\n"
" if (s.n != 9) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL, NULL },
/* ---- c4: cast/is/try family */
{ "strcast_2lvl",
"package main;\n"
"type ms0 = str;\n"
"type ms = ms0;\n"
"export fn main() i32 = {\n"
" let a: ms = \"hey\";\n"
" let b: []u8 = a: []u8;\n"
" if (len(b) != 3) { return 1; };\n"
" if (b[0] != 'h') { return 2; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL, NULL },
{ "idcast_2lvl",
"package main;\n"
"type u0 = (void | i64);\n"
"type u = u0;\n"
"export fn main() i32 = {\n"
" let v: u = 42i64;\n"
" let w: u = (v: u);\n"
" match (w) {\n"
" case let n: i64 => { if (n != 42) { return 1; }; };\n"
" case void => { return 2; };\n"
" };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL, NULL },
{ "is_2lvl",
"package main;\n"
"type u0 = (void | i64);\n"
"type u = u0;\n"
"export fn main() i32 = {\n"
" let v: u = 42i64;\n"
" if (!(v is i64)) { return 1; };\n"
" if (v is void) { return 2; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL, NULL },
/* ALIAS-INDEPENDENT #38b bound (ken's row is >48B sret-class):
* the :9819 chase must stay loud-preserving — this pins the
* fatal so a future chase can't silently green it. */
{ "try_loud_38b",
"package main;\n"
"type e0 = !i64;\n"
"type big = struct { a: i64, b: i64, c: i64, d: i64, e: i64, f: i64, g: i64 };\n"
"type r0 = (big | e0);\n"
"type r = r0;\n"
"fn w() r = {\n"
" let s: big;\n"
" s.a = 1; s.b = 2; s.c = 3; s.d = 4; s.e = 5; s.f = 6; s.g = 77;\n"
" return s;\n"
"};\n"
"fn outer() (i64 | e0) = {\n"
" let v = w()?;\n"
" return v.g;\n"
"};\n"
"export fn main() i32 = {\n"
" match (outer()) {\n"
" case let n: i64 => { if (n != 77) { return 1; }; };\n"
" case e0 => { return 2; };\n"
" };\n"
" return 0;\n"
"};\n", 0, 0, K_BUILDERR,
"#38b: `?`/`!` on an sret-class call result unwired", NULL },
/* ---- c5: reads/len/globals family */
{ "tfread_2lvl",
"package main;\n"
"type u0 = (void | i64);\n"
"type u = u0;\n"
"type st0 = struct { f: u, n: i64 };\n"
"type st = st0;\n"
"export fn main() i32 = {\n"
" let s: st;\n"
" s.f = 42i64;\n"
" s.n = 3;\n"
" if (!(s.f is i64)) { return 1; };\n"
" let p: *st = &s;\n"
" if (!(p.f is i64)) { return 2; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL, NULL },
{ "len_2lvl",
"package main;\n"
"type ms0 = str;\n"
"type ms = ms0;\n"
"type ar0 = [4]i64;\n"
"type ar = ar0;\n"
"export fn main() i32 = {\n"
" let a: ms = \"hello\";\n"
" if (len(a) != 5) { return 1; };\n"
" let xs: ar = [1, 2, 3, 4];\n"
" if (len(xs) != 4) { return 2; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL, NULL },
{ "gref_2lvl",
"package main;\n"
"type my64 = i64;\n"
"type my64b = my64;\n"
"let G: my64b = 7;\n"
"export fn main() i32 = {\n"
" if (G != 7) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL, NULL },
/* :9944 #37 cap-watch: the `is` site's >32B mem-read predicate
* must key the CHASED size — byte-neutrality of this 40B-union
* row across the c5 chase is the regression net. */
{ "memread_40b",
"package main;\n"
"type big = struct { a: i64, b: i64, c: i64, d: i64, e: i64 };\n"
"type m0 = (void | big);\n"
"type m = m0;\n"
"export fn main() i32 = {\n"
" let s: big;\n"
" s.a = 1; s.b = 2; s.c = 3; s.d = 4; s.e = 55;\n"
" let v: m = s;\n"
" if (!(v is big)) { return 1; };\n"
" match (v) {\n"
" case let w: big => { if (w.e != 55) { return 2; }; };\n"
" case void => { return 3; };\n"
" };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL, NULL },
};
static int
run_driver(const char *driver, const struct row *r, int i, int expect_err,
int want, const char *experr)
{
char tmpdir[96], src[128], outbin[128], errf[128], rmcmd[160];
char cmd[1024];
snprintf(tmpdir, sizeof tmpdir, "/tmp/ab6_%d_d_%d", getpid(), i);
mkdir(tmpdir, 0755);
snprintf(src, sizeof src, "%s/ab6_%d_%d.ww", tmpdir, getpid(), i);
snprintf(outbin, sizeof outbin, "%s/ab6_%d_%d", tmpdir, getpid(), i);
snprintf(errf, sizeof errf, "%s/err", tmpdir);
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);
snprintf(cmd, sizeof cmd,
"timeout 20 %s build -o %s %s >/dev/null 2>%s",
driver, outbin, src, errf);
int brc = runwait(cmd);
if (expect_err) {
int ok = (brc != 0)
&& (experr == NULL || errlog_has(errf, experr));
if (!ok)
fprintf(stderr, "row[%s]: %s expected loud builderr "
"\"%s\" (brc=%d)\n", r->label, driver,
experr ? 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 != want) {
fprintf(stderr, "row[%s]: %s exit %d, want %d\n",
r->label, driver, got, 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/ab6_asm_%d_%d.ww", getpid(), i);
snprintf(cs, sizeof cs, "/tmp/ab6_asm_%d_%d_c.s", getpid(), i);
snprintf(ws, sizeof ws, "/tmp/ab6_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)
{
@@ -649,41 +112,17 @@ main(void)
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++;
int cs_err = rows[i].kind == K_BUILDERR;
if (run_driver(cdrv, &rows[i], i, cs_err,
rows[i].cswant, rows[i].experr) != 0) fail++;
}
if (access(wdrv, X_OK) == 0) {
for (int i = 0; i < n; i++) {
total++;
int ww_err = rows[i].kind == K_BUILDERR;
const char *we = rows[i].experr_ww
? rows[i].experr_ww : rows[i].experr;
if (run_driver(wdrv, &rows[i], i, ww_err,
rows[i].wwwant, we) != 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++;
}
}
int fail = 0;
for (int i = 0; i < n; i++)
if (run_row(bin, rows[i].label, rows[i].src, rows[i].cserr,
rows[i].wwerr, i) != 0)
fail++;
if (fail) {
fprintf(stderr, "alias_cgen_b6: %d/%d checks failed\n",
fail, total);
fprintf(stderr, "alias_cgen_b6 (slim): %d/%d rows failed\n", fail, n);
return 1;
}
printf("alias_cgen_b6: %d/%d ok\n", total, total);
printf("alias_cgen_b6 (slim): %d/%d ok\n", n, n);
return 0;
}

View File

@@ -1,426 +0,0 @@
/*
* 944_alias_decl_order_size_run — #62 rider (alias arc pre-F1): type-
* table layout must be DECL-ORDER-INDEPENDENT. cstage check_file used
* to resolve typedecl bodies in file order with an eager under->size
* copy, so any body referencing a typedecl declared LATER read its
* size-0 placeholder and baked it in: alias size 0, tagged-union
* maxsz 0 (the F0 m5_match $48-frame under-allocated box), struct
* field offsets collapsed, array element stride 0. wwstage (demand-
* driven tinfofornode) was order-independent on every row — the
* measured-sound side cstage now mirrors via resolve_typedecl's
* resolve-on-first-reference. Oracle: ken /tmp/ken_62_oracle.md
* (size((void|ali)) = 8B tag + roundup8(chased member size); every
* behavior indistinguishable from the (void|base) spelling).
*
* row | shape | want
* -----------------+-----------------------------------------+-----
* sizes_norm | base,ali decl order; size(base/ali/ |
* | (void|ali)) = 16/16/24 | 0
* sizes_fwd | ali BEFORE base (fwd-ref); same asserts | 0
* union_decl_norm | named u=(void|ali) declared LAST | 0
* union_decl_fwd | named u=(void|ali) declared FIRST | 0
* field_fwd | outer{i,j:inner} before inner — total |
* | size AND j.b offset readback (4/9/7/3 |
* | break prefix-luck; last word checked) | 0
* field_norm | inner before outer; same asserts | 0
* arrelem_fwd | arr=[2]base before base — stride + |
* | a[1].b last-word readback | 0
* arrelem_norm | base before arr; same asserts | 0
* chain2_fwd | a2=a1=base full fwd chain; 16/16 | 0
* chain2_norm | base,a1,a2 decl order; same asserts | 0
* union_base_ctl | (void|base) match payload readback — |
* | the m5b_match0 no-regress control | 0
* cycle_alias | type a=b; type b=a — loud BUILDERR |
* | both stages (#69: pre-fix cs silent-0, |
* | ww HANG) | err
* cycle_self | type a=a — loud BUILDERR both stages | err
* cycle_struct_value | s1{x:s2}/s2{x:s1} — loud BUILDERR |
* | both stages (pre-fix ww stack overflow) | err
* ptr_selfref_ok | node{v,next:*node} legal self-ref stays |
* | accepted + byte-id (guard no-over-fire) | 0
*
* NOT pinned here: the alias-in-union match payload readback
* (m5b_match1) — its word0-only box STORE is the Layer-2 cgen family
* (cstage cg_widen_tagged_store single NAMED peel; wwstage
* rhsstructpayload name-keyed structlookup without alias chase),
* EXPECTED-FAIL until the F1/F2 copy-width fix lands. See task #62.
*
* Every row also asserts cstage/wwstage asm byte-id, except rows
* flagged nobyteid (arrelem_fwd — the pre-existing task-#60 index-
* over-alias divergence; see the row comment). NNN<950,
* self-contained (/tmp, no imports) — rule-14's selfhost-sibling
* race does not apply (941 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, + cs==ww byte-id */
#define K_BUILDERR 1 /* build must FAIL with experr on BOTH drivers (rule 7) */
/* nobyteid: the row's RUNTIME behavior is pinned on both stages but
* its asm is excluded from the byte-id sweep — cite the filed task at
* the row. */
struct row { const char *label; const char *src; int want; int nobyteid;
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[] = {
{ "sizes_norm",
"package main;\n"
"type base = struct { a: size, b: size };\n"
"type ali = base;\n"
"export fn main() i32 = {\n"
" if (size(base) != 16) { return 1; };\n"
" if (size(ali) != 16) { return 2; };\n"
" if (size((void | ali)) != 24) { return 3; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL },
{ "sizes_fwd",
"package main;\n"
"type ali = base;\n"
"type base = struct { a: size, b: size };\n"
"export fn main() i32 = {\n"
" if (size(base) != 16) { return 1; };\n"
" if (size(ali) != 16) { return 2; };\n"
" if (size((void | ali)) != 24) { return 3; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL },
{ "union_decl_norm",
"package main;\n"
"type base = struct { a: size, b: size };\n"
"type ali = base;\n"
"type u = (void | ali);\n"
"export fn main() i32 = {\n"
" if (size(u) != 24) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL },
{ "union_decl_fwd",
"package main;\n"
"type u = (void | ali);\n"
"type ali = base;\n"
"type base = struct { a: size, b: size };\n"
"export fn main() i32 = {\n"
" if (size(u) != 24) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL },
/* fwd field: a size-0 inner collapsed outer's offsets too — pin
* the LAST word of the SECOND field, values all distinct. */
{ "field_fwd",
"package main;\n"
"type outer = struct { i: inner, j: inner };\n"
"type inner = struct { a: size, b: size };\n"
"export fn main() i32 = {\n"
" if (size(inner) != 16) { return 1; };\n"
" if (size(outer) != 32) { return 2; };\n"
" let o: outer;\n"
" o.i.a = 4; o.i.b = 9; o.j.a = 7; o.j.b = 3;\n"
" if (o.i.a != 4) { return 3; };\n"
" if (o.i.b != 9) { return 4; };\n"
" if (o.j.a != 7) { return 5; };\n"
" if (o.j.b != 3) { return 6; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL },
{ "field_norm",
"package main;\n"
"type inner = struct { a: size, b: size };\n"
"type outer = struct { i: inner, j: inner };\n"
"export fn main() i32 = {\n"
" if (size(inner) != 16) { return 1; };\n"
" if (size(outer) != 32) { return 2; };\n"
" let o: outer;\n"
" o.i.a = 4; o.i.b = 9; o.j.a = 7; o.j.b = 3;\n"
" if (o.i.a != 4) { return 3; };\n"
" if (o.i.b != 9) { return 4; };\n"
" if (o.j.a != 7) { return 5; };\n"
" if (o.j.b != 3) { return 6; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL },
/* nobyteid: indexing an alias-NAMED array local is the task-#60
* family — wwstage emits a ptr-load/ADDQ spine vs cstage's direct
* 8(BX); PRE-EXISTING on master, order-independent, runtime-
* correct here (8B-multiple elements). The size assert + element
* readback below stay pinned on both stages; flip this flag when
* #60 lands. */
{ "arrelem_fwd",
"package main;\n"
"type arr = [2]base;\n"
"type base = struct { a: size, b: size };\n"
"export fn main() i32 = {\n"
" if (size(arr) != 32) { return 1; };\n"
" let a: arr;\n"
" a[0].a = 4; a[0].b = 9; a[1].a = 7; a[1].b = 3;\n"
" if (a[0].b != 9) { return 2; };\n"
" if (a[1].a != 7) { return 3; };\n"
" if (a[1].b != 3) { return 4; };\n"
" return 0;\n"
"};\n", 0, 1, K_RUN, NULL },
/* nobyteid: same #60 cite as arrelem_fwd — the index-over-alias
* divergence is order-INDEPENDENT (verified on master). */
{ "arrelem_norm",
"package main;\n"
"type base = struct { a: size, b: size };\n"
"type arr = [2]base;\n"
"export fn main() i32 = {\n"
" if (size(arr) != 32) { return 1; };\n"
" let a: arr;\n"
" a[0].a = 4; a[0].b = 9; a[1].a = 7; a[1].b = 3;\n"
" if (a[0].b != 9) { return 2; };\n"
" if (a[1].a != 7) { return 3; };\n"
" if (a[1].b != 3) { return 4; };\n"
" return 0;\n"
"};\n", 0, 1, K_RUN, NULL },
{ "chain2_fwd",
"package main;\n"
"type a2 = a1;\n"
"type a1 = base;\n"
"type base = struct { a: size, b: size };\n"
"export fn main() i32 = {\n"
" if (size(a1) != 16) { return 1; };\n"
" if (size(a2) != 16) { return 2; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL },
{ "chain2_norm",
"package main;\n"
"type base = struct { a: size, b: size };\n"
"type a1 = base;\n"
"type a2 = a1;\n"
"export fn main() i32 = {\n"
" if (size(a1) != 16) { return 1; };\n"
" if (size(a2) != 16) { return 2; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL },
/* m5b_match0 no-regress control: direct base member, full payload
* readback through the box, last word checked. */
{ "union_base_ctl",
"package main;\n"
"type base = struct { a: size, b: size };\n"
"export fn main() i32 = {\n"
" let x: base;\n"
" x.a = 4; x.b = 9;\n"
" let v: (void | base) = x;\n"
" match (v) {\n"
" case let s: base => {\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, 0, K_RUN, NULL },
/* #62/#69 cycle guard (rob's rider condition): TRUE typedecl
* cycles loud-reject on BOTH stages — pre-guard cs silently sized
* them 0 and wwstage HUNG (alias cycle) / stack-overflowed (struct
* value cycle). harec cite: check.c:4767 "Circular dependency". */
{ "cycle_alias",
"package main;\n"
"type a = b;\n"
"type b = a;\n"
"export fn main() i32 = {\n"
" if (size(a) != 8) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_BUILDERR, "circular type dependency" },
{ "cycle_self",
"package main;\n"
"type a = a;\n"
"export fn main() i32 = {\n"
" if (size(a) != 8) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_BUILDERR, "circular type dependency" },
{ "cycle_struct_value",
"package main;\n"
"type s1 = struct { x: s2 };\n"
"type s2 = struct { x: s1 };\n"
"export fn main() i32 = {\n"
" if (size(s1) != 8) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_BUILDERR, "circular type dependency" },
/* The LEGAL self-reference (pointer field never reads the
* target's size) must stay accepted — the io.stream / list-node
* shape the cycle guard is forbidden from breaking. */
{ "ptr_selfref_ok",
"package main;\n"
"type node = struct { v: size, next: *node };\n"
"export fn main() i32 = {\n"
" let n: node;\n"
" n.v = 7;\n"
" n.next = &n;\n"
" if (size(node) != 16) { return 1; };\n"
" if (n.v != 7) { return 2; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL },
};
/* build+run via a driver (ww / ww_ww); returns 0 pass, nonzero fail. */
static int
run_driver(const char *driver, const struct row *r, int i)
{
char tmpdir[96], src[160], outbin[160], errf[160], rmcmd[160], cmd[1024];
snprintf(tmpdir, sizeof tmpdir, "/tmp/ados_%d_d_%d", getpid(), i);
mkdir(tmpdir, 0755);
snprintf(src, sizeof src, "%s/ados_%d_%d.ww", tmpdir, getpid(), i);
snprintf(outbin, sizeof outbin, "%s/ados_%d_%d", tmpdir, getpid(), i);
snprintf(errf, sizeof errf, "%s/err", tmpdir);
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);
/* timeout: the pre-#69 wwstage HANG on a cycle must fail the row,
* not wedge the suite. */
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) {
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;
}
/* cs==ww .s byte-id (rule 10). */
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/ados_asm_%d_%d.ww", getpid(), i);
snprintf(cs, sizeof cs, "/tmp/ados_asm_%d_%d_c.s", getpid(), i);
snprintf(ws, sizeof ws, "/tmp/ados_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++) {
total++;
if (run_driver(wdrv, &rows[i], i) != 0) fail++;
}
for (int i = 0; i < n; i++) {
if (rows[i].nobyteid || rows[i].kind == K_BUILDERR)
continue;
total++;
if (asm_byte_identical(bin, &rows[i], i) != 0) fail++;
}
}
if (fail) {
fprintf(stderr, "alias_decl_order_size: %d/%d checks failed\n",
fail, total);
return 1;
}
printf("alias_decl_order_size: %d/%d ok\n", total, total);
return 0;
}

View File

@@ -1,88 +1,22 @@
/*
* 944_alias_emit_b7_run — #5 alias arc B7 (finale): the four cgen.c
* static-DATA emitter ELEM-type chases. All four sites already chased
* the OUTER type; the residual single peel was on the ELEMENT type
* (u->sub), so a 2-level-elem-alias global missed the TY_STRUCT /
* TY_STR / TY_TAGGED kind tests and fell off the foldable-literal
* path. cs-only: every graduation is a cs-side flip onto ww's
* already-correct emit (align cs UP); _ww binaries bit-identical
* across the commit (comment-only ww annotation bytes are
* codegen-inert).
* 944_alias_emit_b7_run — SLIM CARRIER (#5-C3 alias fold-2). The 8 K_RUN value
* rows migrated to test/lang/alias_emit_b7_test.ww (@test, cs==ww byte-id); the
* symmetric K_BUILDERR rejects (slcstr_plain_ctl, slcslc_2lvl) to
* test/wcc/data/alias_{slcstr_plain,slcslc}/case.ww runww //ww:error.
*
* Sites (numbering at 05f7af7): emit_array_lit_bytes:14356 (struct
* arm + raw-bytes path), emit_strarray_data:14574 (str DATAW+DATAR
* rows), emit_slice_data:14788 (3-way slice-of-{str,slice,tagged}
* fatal), let_pre_intern:15088 (the :14574 row's label-order leg —
* MUST chase in the same commit or _S_ labels intern in emit order,
* not decl order; strarr_2lvl's byte-id IS the coupling proof).
*
* Row sources: ken's B7 first-position oracle (/tmp/ken_b5/src/kb7_*,
* .ai/ken-b7-oracle.md, matrix at 05f7af7) + impl pre-state probes.
* NOTE: `type el = el0` where el0 is itself a type decl is ALREADY two
* NAMED layers (NAMED(el)→NAMED(el0)→struct), so the "_1lvl" struct
* spelling graduates with the 2-level rows; only a direct alias of a
* primitive (type ms = str) is a true single layer.
*
* row | shape | cs/ww
* -------------------+--------------------------------------+------
* sarr_2lvl | kb7_sarr [2]el 2-lvl alias struct |
* | elem: cs emitted NO DATA (eu peel |
* | missed TY_STRUCT → return 0 → caller |
* | skipped the def) → link-loud. LIVE |
* | graduation → 0/0 byte-id | 0/0
* sarr_1lvl | [2]el, el = el0 — two NAMED layers |
* | by construction; same graduation | 0/0
* sarr_plain_ctl | kb7_sarr0 [2]el0 control | 0/0
* sarr_unref_2lvl | NEVER-REFERENCED 2-lvl-elem global: |
* | pre-B7 cs silently lacked DATA (no |
* | reference → no link error → latent |
* | silence, ken's caveat). Closure pin: |
* | byte-id vs ww (which always emitted) | 0/0
* strarr_2lvl | kb7_strarr [2]ms 2-lvl alias str: |
* | eu != TY_STR → generic path can't |
* | fold strlits → link-loud. Graduation |
* | + the :15088 intern-order coupling | 0/0
* strarr_1lvl_ctl | type ms = str — TRUE 1-level; worked |
* | pre-B7, byte-NEUTRAL regression net | 0/0
* strarr_plain_ctl | kb7_strarr0 [2]str control | 0/0
* scalararr_2lvl | [3]my64b raw-bytes path: scalar fold |
* | never consulted eu — worked pre-B7, |
* | byte-NEUTRAL regression net | 0/0
* slc_2lvl | kb7_slc []my64b: cs ok (synthesized- |
* | array choke-point + mirrored esz), |
* | ww checker-rejects ALL slice-literal |
* | globals ("let: not assignable", |
* | pre-existing acceptance divergence, |
* | #66-R2/#29 kin) — ww cell MUST NOT |
* | move across B7 | 0/err
* slc_plain_ctl | kb7_slc0 []i64 — same split | 0/err
* slcstr_2lvl | kb7_slcstr []ms: pre-B7 the alias |
* | ESCAPED the 3-way fatal and hit the |
* | downstream "not a foldable constant" |
* | — loud but WRONG DIAGNOSTIC. Post: |
* | the intended 3-way text (== control) | err/err
* slcstr_plain_ctl | kb7_slcstr0 []str pins the 3-way |
* | text on the control | err/err
* slctag_2lvl | []u1 2-lvl alias tagged elem: pre-B7 |
* | the alias DODGED the 3-way fatal |
* | ENTIRELY — silent accept + run |
* | (wrong-DATA latency). DESIGNED |
* | NARROWING: post-B7 louds with the |
* | 3-way text ("widen what the gate |
* | SEES", B6-c2 fsarg2 precedent) | err/err
* slcslc_2lvl | []ms (ms = []i64): nested slice-lit |
* | rejected UPSTREAM by the cs checker |
* | ("let G init not assignable") — the |
* | TY_SLICE arm of the 3-way is not |
* | reachable via a literal; pin the |
* | checker bound (alias-independent) | err/err
*
* K_RUN rows build+run BOTH drivers (exit==want) and assert cs/ww asm
* byte-id. K_BUILDERR rows must FAIL with experr on BOTH drivers;
* experr_ww overrides the ww text when the stages loud at different
* sites. K_CSRUN_WWERR rows run on the cs driver and must FAIL with
* experr_ww on the ww driver (ken's observation cells; byte-id N/A).
* NNN<950, self-contained /tmp sources, no imports (944 precedent).
* What survives here are the 4 IRREDUCIBLE per-stage rows neither in-language
* surface can host (ken's emit_slice_data observation cells — load-bearing
* codegen pins, MUST NOT move):
* • slc_2lvl / slc_plain_ctl (Group A): cstage builds+RUNS exit 0; wwstage
* LOUD-REJECTS at the let checker ("let: not assignable"). cstage emits the
* []my64b / []i64 slice-literal global DATA and runs; the ww checker
* rejects every slice-literal global (the #120/#29-kin acceptance
* divergence, ken-d2-oracle; pre-slim #66-R2/#29). @test needs ww to
* build, //ww:error needs cs to fail — neither fits.
* • slcstr_2lvl / slctag_2lvl (Group B): BOTH reject but with DIFFERENT
* diagnostics (cs at emit_slice_data 3-way "static-init unsupported"; ww at
* the let checker "not assignable") — a held cs!=ww divergence; the two
* messages ARE the pin, so each stage's own substring is asserted.
*/
#include <stdio.h>
#include <stdlib.h>
@@ -100,37 +34,6 @@ runwait(const char *cmd)
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, exits==wants, + byte-id */
#define K_BUILDERR 1 /* build FAILS with experr on BOTH drivers;
* experr_ww overrides the ww-side text */
#define K_CSRUN_WWERR 2 /* cs builds+runs (exit==cswant); ww must
* FAIL with experr_ww (pre-existing
* acceptance divergence cell); byte-id
* N/A — ww emits nothing */
struct row { const char *label; const char *src;
int cswant; int wwwant; int kind;
const char *experr; const char *experr_ww; };
/* errlog_has — a builderr cell 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)
{
@@ -143,90 +46,65 @@ errlog_has(const char *path, const char *needle)
return strstr(buf, needle) != NULL;
}
#define ERR_3WAY "slice-of-{str,slice,tagged} literal static-init unsupported"
#define ERR_WWLET "let: not assignable"
#define M_CSRUN_WWERR 0 /* cstage build+run exit 0; wwstage w6c_ww rejects wwerr */
#define M_BOTHERR 1 /* cstage w6c rejects cserr; wwstage w6c_ww rejects wwerr */
struct row { const char *label; const char *src; int mode;
const char *cserr; const char *wwerr; };
static int
run_row(const char *bin, const struct row *r, int i)
{
char dir[96], srcf[160], outbin[160], cse[160], wwe[160], ss[160],
rm[200], cmd[2048];
snprintf(dir, sizeof dir, "/tmp/ab7_%d_%d", getpid(), i);
mkdir(dir, 0755);
snprintf(srcf, sizeof srcf, "%s/c.ww", dir);
snprintf(outbin, sizeof outbin, "%s/bin", dir);
snprintf(cse, sizeof cse, "%s/cs.err", dir);
snprintf(wwe, sizeof wwe, "%s/ww.err", dir);
snprintf(ss, sizeof ss, "%s/o.s", dir);
snprintf(rm, sizeof rm, "rm -rf %s", dir);
FILE *f = fopen(srcf, "wb");
if (!f) { runwait(rm); return -1; }
fputs(r->src, f);
fclose(f);
int ok = 1;
if (r->mode == M_CSRUN_WWERR) {
snprintf(cmd, sizeof cmd,
"timeout 20 %s/ww build -o %s %s >/dev/null 2>&1",
bin, outbin, srcf);
if (runwait(cmd) != 0) {
fprintf(stderr, "row[%s]: cstage build failed (want run)\n",
r->label);
ok = 0;
} else if (runwait(outbin) != 0) {
fprintf(stderr, "row[%s]: cstage run != 0\n", r->label);
ok = 0;
}
} else {
snprintf(cmd, sizeof cmd, "%s/w6c -o %s %s 2>%s", bin, ss, srcf, cse);
int crc = runwait(cmd);
if (!(crc != 0 && errlog_has(cse, r->cserr))) {
fprintf(stderr, "row[%s]: cstage expected reject \"%s\" (rc=%d)\n",
r->label, r->cserr, crc);
ok = 0;
}
}
snprintf(cmd, sizeof cmd, "%s/w6c_ww -o %s %s 2>%s", bin, ss, srcf, wwe);
int wrc = runwait(cmd);
if (!(wrc != 0 && errlog_has(wwe, r->wwerr))) {
fprintf(stderr, "row[%s]: wwstage expected reject \"%s\" (rc=%d)\n",
r->label, r->wwerr, wrc);
ok = 0;
}
runwait(rm);
return ok ? 0 : 1;
}
static const struct row rows[] = {
/* ---- emit_array_lit_bytes struct arm (:14356) */
{ "sarr_2lvl",
"package main;\n"
"type el0 = struct { a: i64, b: i64 };\n"
"type el1 = el0;\n"
"type el = el1;\n"
"let G: [2]el = [el0 { a = 1, b = 2 }, el0 { a = 3, b = 4 }];\n"
"export fn main() i32 = {\n"
" if (G[0].a + G[0].b + G[1].a + G[1].b != 10) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL, NULL },
{ "sarr_1lvl",
"package main;\n"
"type el0 = struct { a: i64, b: i64 };\n"
"type el = el0;\n"
"let G: [2]el = [el0 { a = 1, b = 2 }, el0 { a = 3, b = 4 }];\n"
"export fn main() i32 = {\n"
" if (G[0].a + G[0].b + G[1].a + G[1].b != 10) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL, NULL },
{ "sarr_plain_ctl",
"package main;\n"
"type el0 = struct { a: i64, b: i64 };\n"
"let G: [2]el0 = [el0 { a = 1, b = 2 }, el0 { a = 3, b = 4 }];\n"
"export fn main() i32 = {\n"
" if (G[0].a + G[0].b + G[1].a + G[1].b != 10) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL, NULL },
/* Zero-consumer latent silence (ken's caveat): unreferenced, so
* the pre-B7 missing DATA never linked-loud — the byte-id cell
* vs ww (which always emitted the row) is the closure pin. */
{ "sarr_unref_2lvl",
"package main;\n"
"type el0 = struct { a: i64, b: i64 };\n"
"type el1 = el0;\n"
"type el = el1;\n"
"let G: [2]el = [el0 { a = 1, b = 2 }, el0 { a = 3, b = 4 }];\n"
"export fn main() i32 = {\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL, NULL },
/* ---- emit_strarray_data (:14574) + let_pre_intern (:15088) */
{ "strarr_2lvl",
"package main;\n"
"type ms0 = str;\n"
"type ms = ms0;\n"
"let G: [2]ms = [\"aa\", \"bbb\"];\n"
"export fn main() i32 = {\n"
" if (len(G[0]) != 2) { return 1; };\n"
" if (len(G[1]) != 3) { return 2; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL, NULL },
{ "strarr_1lvl_ctl",
"package main;\n"
"type ms = str;\n"
"let G: [2]ms = [\"aa\", \"bbb\"];\n"
"export fn main() i32 = {\n"
" if (len(G[0]) != 2) { return 1; };\n"
" if (len(G[1]) != 3) { return 2; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL, NULL },
{ "strarr_plain_ctl",
"package main;\n"
"let G: [2]str = [\"aa\", \"bbb\"];\n"
"export fn main() i32 = {\n"
" if (len(G[0]) != 2) { return 1; };\n"
" if (len(G[1]) != 3) { return 2; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL, NULL },
/* Raw-bytes scalar fold never consulted eu — byte-NEUTRAL net. */
{ "scalararr_2lvl",
"package main;\n"
"type my64 = i64;\n"
"type my64b = my64;\n"
"let G: [3]my64b = [5, 6, 7];\n"
"export fn main() i32 = {\n"
" if (G[0] + G[1] + G[2] != 18) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL, NULL },
/* ---- emit_slice_data (:14788) — ken's ww observation cells
* (checker-rejects every slice-literal global) MUST NOT move. */
{ "slc_2lvl",
"package main;\n"
"type my64 = i64;\n"
@@ -236,7 +114,7 @@ static const struct row rows[] = {
" if (G[0] + G[1] + G[2] != 18) { return 1; };\n"
" if (len(G) != 3) { return 2; };\n"
" return 0;\n"
"};\n", 0, 1, K_CSRUN_WWERR, NULL, ERR_WWLET },
"};\n", M_CSRUN_WWERR, NULL, "let: not assignable" },
{ "slc_plain_ctl",
"package main;\n"
"let G: []i64 = [5, 6, 7];\n"
@@ -244,10 +122,7 @@ static const struct row rows[] = {
" if (G[0] + G[1] + G[2] != 18) { return 1; };\n"
" if (len(G) != 3) { return 2; };\n"
" return 0;\n"
"};\n", 0, 1, K_CSRUN_WWERR, NULL, ERR_WWLET },
/* Diagnostic-routing fix: pre-B7 the 2-lvl alias escaped the
* 3-way fatal onto the downstream "not a foldable constant"
* text — loud either way, wrong message. Post: == control. */
"};\n", M_CSRUN_WWERR, NULL, "let: not assignable" },
{ "slcstr_2lvl",
"package main;\n"
"type ms0 = str;\n"
@@ -256,22 +131,9 @@ static const struct row rows[] = {
"export fn main() i32 = {\n"
" if (len(G[0]) != 2) { return 1; };\n"
" return 0;\n"
"};\n", 1, 1, K_BUILDERR, ERR_3WAY, ERR_WWLET },
/* ww cell observed: plain []str PASSES the ww checker and louds
* at ww's own emitslicedata 3-way — the shared needle pins both
* stages' texts (cs "emit_slice_data:", ww "emitslicedata:");
* only ALIAS slice spellings reject at the ww checker. */
{ "slcstr_plain_ctl",
"package main;\n"
"let G: []str = [\"aa\", \"bbb\"];\n"
"export fn main() i32 = {\n"
" if (len(G[0]) != 2) { return 1; };\n"
" return 0;\n"
"};\n", 1, 1, K_BUILDERR, ERR_3WAY, NULL },
/* DESIGNED NARROWING: pre-B7 the tagged-elem alias dodged the
* 3-way fatal entirely — cs silently accepted and ran (wrong-
* DATA latency). The chase widens what the gate SEES (B6-c2
* fsarg2 precedent); the loud stays loud for what it guards. */
"};\n", M_BOTHERR,
"slice-of-{str,slice,tagged} literal static-init unsupported",
"let: not assignable" },
{ "slctag_2lvl",
"package main;\n"
"type u0 = (void | i64);\n"
@@ -280,104 +142,11 @@ static const struct row rows[] = {
"export fn main() i32 = {\n"
" if (len(G) != 2) { return 1; };\n"
" return 0;\n"
"};\n", 1, 1, K_BUILDERR, ERR_3WAY, ERR_WWLET },
/* Slice-of-slice literal never reaches the emitter: the cs
* checker bounds it upstream, alias-independent. Pin the bound
* so a checker widening re-opens this row deliberately. */
{ "slcslc_2lvl",
"package main;\n"
"type ms0 = []i64;\n"
"type ms = ms0;\n"
"let G: []ms = [[1, 2], [3]];\n"
"export fn main() i32 = {\n"
" if (len(G) != 2) { return 1; };\n"
" return 0;\n"
"};\n", 1, 1, K_BUILDERR, "let G init not assignable", ERR_WWLET },
"};\n", M_BOTHERR,
"slice-of-{str,slice,tagged} literal static-init unsupported",
"let: not assignable" },
};
static int
run_driver(const char *driver, const struct row *r, int i, int expect_err,
int want, const char *experr)
{
char tmpdir[96], src[160], outbin[160], errf[160], rmcmd[160], cmd[1024];
snprintf(tmpdir, sizeof tmpdir, "/tmp/ab7_%d_d_%d", getpid(), i);
mkdir(tmpdir, 0755);
snprintf(src, sizeof src, "%s/ab7_%d_%d.ww", tmpdir, getpid(), i);
snprintf(outbin, sizeof outbin, "%s/ab7_%d_%d", tmpdir, getpid(), i);
snprintf(errf, sizeof errf, "%s/err", tmpdir);
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);
snprintf(cmd, sizeof cmd,
"timeout 20 %s build -o %s %s >/dev/null 2>%s",
driver, outbin, src, errf);
int brc = runwait(cmd);
if (expect_err) {
int ok = (brc != 0)
&& (experr == NULL || errlog_has(errf, experr));
if (!ok)
fprintf(stderr, "row[%s]: %s expected loud builderr "
"\"%s\" (brc=%d)\n", r->label, driver,
experr ? 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 != want) {
fprintf(stderr, "row[%s]: %s exit %d, want %d\n",
r->label, driver, got, 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/ab7_asm_%d_%d.ww", getpid(), i);
snprintf(cs, sizeof cs, "/tmp/ab7_asm_%d_%d_c.s", getpid(), i);
snprintf(ws, sizeof ws, "/tmp/ab7_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)
{
@@ -391,42 +160,15 @@ main(void)
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++;
int cs_err = rows[i].kind == K_BUILDERR;
if (run_driver(cdrv, &rows[i], i, cs_err,
rows[i].cswant, rows[i].experr) != 0) fail++;
}
if (access(wdrv, X_OK) == 0) {
for (int i = 0; i < n; i++) {
total++;
int ww_err = rows[i].kind == K_BUILDERR
|| rows[i].kind == K_CSRUN_WWERR;
const char *we = rows[i].experr_ww
? rows[i].experr_ww : rows[i].experr;
if (run_driver(wdrv, &rows[i], i, ww_err,
rows[i].wwwant, we) != 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++;
}
}
int fail = 0;
for (int i = 0; i < n; i++)
if (run_row(bin, &rows[i], i) != 0) fail++;
if (fail) {
fprintf(stderr, "alias_emit_b7: %d/%d checks failed\n",
fail, total);
fprintf(stderr, "alias_emit_b7 (slim): %d/%d rows failed\n", fail, n);
return 1;
}
printf("alias_emit_b7: %d/%d ok\n", total, total);
printf("alias_emit_b7 (slim): %d/%d ok\n", n, n);
return 0;
}

View File

@@ -1,451 +0,0 @@
/*
* 944_alias_global_decl_run — g-fold (#77 + #78 fused): alias-typed
* GLOBAL declarations, both stages. The decl/emit dispatch was
* alias-blind on both sides:
*
* cs (#78): the let_* helper family (let_emit_size + the five kind
* predicates, cgen.c) single-peeled — a 2-level alias chain (or ONE
* user alias over a named struct) left the type TY_NAMED, so the
* global was never registered, no DATA was emitted, and reads fell
* to the frame-local path at offset 0: silent saved-BP reads (garr2
* exit-wrong, gst1 SEGV, gstr2/gsl2 silent-wrong). The routed-to
* DATA emitters re-peeled at entry and return-0'd into the silent
* skip (condition-3 members, enrollment ruling in
* .ai/rob-gfold-spec.md).
*
* ww (#77): emitletdataw's array gates + letpreintern's array leg
* keyed on the UNCHASED N_TARRAY tnode — an alias-typed global's
* N_TNAME matched no arm and the skip-policy ate the decl: loud
* `w6l: undefined reference to main.g` on every alias-global ARRAY
* row. Fix: ONE tichase at the dispatch entry (dti), array gates +
* emitarraydata read it.
*
* THIS TABLE IS THE PERMANENT GUARD, not scaffolding: the global decl
* path is lint-invisible to the future peellint — the ww side was a
* NO-PEEL consumer (zero `.under` tokens; nothing for a peel-shape
* lint to flag), and the cs helpers now spell the one chased accessor.
* Only a runtime+byte-id row pins this behavior.
*
* Train trajectory (two commits, one gated train; per-leg states were
* probe-verified, banked /tmp/implG_probes.md):
* pre-G1: garr2 cs EXIT-WRONG / gst1 cs SEGV / gstr2+gsl2+gstlit cs
* silent-wrong / gsc2+gflt2 cs loud / ww array rows link-ERR
* post-G1 (cs half): every cs row runs 0; ww array rows STILL
* link-ERR (loud, documented)
* post-G2 (ww half): every row 0/0 byte-id — this file's assertion.
*
* Probe-OUT, documented NOT pinned (failed at a DIFFERENT site, filed):
* named-tuple global init — cs checker loud-reject, ww accepts (#86)
* plain tagged global — cs silent-wrong, ww loud-reject (#87, not
* alias-family; control row fails)
*
* row | shape | want
* -------------+----------------------------------------------+-----
* ctl_plain | control: plain [4]int global r/w | 0
* garr1_read | alias arr 1-lvl, read first+LAST | 0
* garr1_wr | alias arr 1-lvl, write+read | 0
* garr_ord | alias arr, type decl AFTER let | 0
* garr2_read | alias arr 2-LVL read (#78 saved-BP row) | 0
* garr2_ordwr | alias arr 2-lvl, order-permuted, w+r | 0
* garr_u32 | alias [4]u32 w+r LAST (narrow esz anti-luck) | 0
* gsc2 | alias int 2-lvl r/w | 0
* gsc2_ord | alias int 2-lvl read, decl-after-let | 0
* gstr2 | alias str 2-lvl, len readback | 0
* gflt2 | alias f64 2-lvl | 0
* gflt2_f32 | alias f32 2-lvl (load-width pin) | 0
* gst1 | alias of named struct, field w/r (SEGV row) | 0
* gst2 | alias-of-alias named struct | 0
* gstlit | alias struct, STRUCTLIT init | 0
* gsl2 | alias slice 2-lvl, literal init + idx read | 0
* gstrarr1 | alias [2]str 1-lvl (letpreintern label leg) | 0
* gstrarr2 | alias [2]str 2-LVL | 0
* gdef_a2 | DEF: 2-lvl alias array, index read | 0
* gdef_st | DEF: alias struct, structlit + field read | 0
* gdef_f2 | DEF: 2-lvl alias f64 | 0
* hold_slice1 | alias global SLICE 1-lvl (pre-fold green) | 0
* hold_elem | alias ELEMENT type [2]row (batch-1 win) | 0
*
* Values exceed 255 (no little-endian prefix-luck) and readbacks
* assert the LAST element. Every row runs BOTH drivers and asserts
* cstage/wwstage asm byte-identity. NNN<950, self-contained /tmp
* sources, no imports (944 precedent).
*/
#include <stdio.h>
#include <stdlib.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;
}
struct row { const char *label; const char *src; int want; };
static const struct row rows[] = {
{ "ctl_plain",
"package main;\n"
"let g: [4]int = [1001: int, 1002: int, 1003: int, 1004: int];\n"
"export fn main() i32 = {\n"
" if (g[3] != 1004) { return 1; };\n"
" g[3] = 9999;\n"
" if (g[3] != 9999) { return 2; };\n"
" return 0;\n"
"};\n", 0 },
{ "garr1_read",
"package main;\n"
"type arr = [4]int;\n"
"let g: arr = [1001: int, 1002: int, 1003: int, 1004: int];\n"
"export fn main() i32 = {\n"
" if (g[0] != 1001) { return 1; };\n"
" if (g[3] != 1004) { return 2; };\n"
" return 0;\n"
"};\n", 0 },
{ "garr1_wr",
"package main;\n"
"type arr = [4]int;\n"
"let g: arr = [1001: int, 1002: int, 1003: int, 1004: int];\n"
"export fn main() i32 = {\n"
" g[3] = 8888;\n"
" if (g[3] != 8888) { return 1; };\n"
" if (g[2] != 1003) { return 2; };\n"
" return 0;\n"
"};\n", 0 },
{ "garr_ord",
"package main;\n"
"let g: arr = [1001: int, 1002: int, 1003: int, 1004: int];\n"
"type arr = [4]int;\n"
"export fn main() i32 = {\n"
" if (g[3] != 1004) { return 1; };\n"
" return 0;\n"
"};\n", 0 },
/* #78 headline: pre-fix cs emitted NO DATA, never referenced
* main.g, and resolved g frame-local at offset 0 — LEAQ (BP) read
* the saved-BP word, exiting silently wrong. */
{ "garr2_read",
"package main;\n"
"type arr = [4]int;\n"
"type arr2 = arr;\n"
"let g: arr2 = [1001: int, 1002: int, 1003: int, 1004: int];\n"
"export fn main() i32 = {\n"
" if (g[0] != 1001) { return 1; };\n"
" if (g[3] != 1004) { return 2; };\n"
" return 0;\n"
"};\n", 0 },
{ "garr2_ordwr",
"package main;\n"
"let g: arr2 = [1001: int, 1002: int, 1003: int, 1004: int];\n"
"type arr2 = arr;\n"
"type arr = [4]int;\n"
"export fn main() i32 = {\n"
" if (g[3] != 1004) { return 1; };\n"
" g[1] = 7777;\n"
" if (g[1] != 7777) { return 2; };\n"
" return 0;\n"
"};\n", 0 },
{ "garr_u32",
"package main;\n"
"type au = [4]u32;\n"
"let g: au = [1001: u32, 1002: u32, 1003: u32, 1004: u32];\n"
"export fn main() i32 = {\n"
" if (g[3] != 1004) { return 1; };\n"
" g[3] = 8888;\n"
" if (g[3] != 8888) { return 2; };\n"
" if (g[2] != 1003) { return 3; };\n"
" return 0;\n"
"};\n", 0 },
{ "gsc2",
"package main;\n"
"type myint = int;\n"
"type myint2 = myint;\n"
"let g: myint2 = 4242;\n"
"export fn main() i32 = {\n"
" if (g != 4242) { return 1; };\n"
" g = 9999;\n"
" if (g != 9999) { return 2; };\n"
" return 0;\n"
"};\n", 0 },
{ "gsc2_ord",
"package main;\n"
"let g: myint2 = 4242;\n"
"type myint2 = myint;\n"
"type myint = int;\n"
"export fn main() i32 = {\n"
" if (g != 4242) { return 1; };\n"
" return 0;\n"
"};\n", 0 },
{ "gstr2",
"package main;\n"
"type ms = str;\n"
"type ms2 = ms;\n"
"let g: ms2 = \"hello\";\n"
"export fn main() i32 = {\n"
" if (g.len != 5) { return 1; };\n"
" return 0;\n"
"};\n", 0 },
{ "gflt2",
"package main;\n"
"type mf = f64;\n"
"type mf2 = mf;\n"
"let g: mf2 = 1.5;\n"
"export fn main() i32 = {\n"
" if (g != 1.5) { return 1; };\n"
" return 0;\n"
"};\n", 0 },
{ "gflt2_f32",
"package main;\n"
"type mg = f32;\n"
"type mg2 = mg;\n"
"let g: mg2 = 1.5f32;\n"
"export fn main() i32 = {\n"
" if (g != 1.5f32) { return 1; };\n"
" return 0;\n"
"};\n", 0 },
/* ONE user alias level sufficed to SEGV cs pre-fix: the named
* struct already costs the single peel, so `pt1 = pt` is two
* TY_NAMED layers at the decl. */
{ "gst1",
"package main;\n"
"type pt = struct { x: int, y: int };\n"
"type pt1 = pt;\n"
"let g: pt1;\n"
"export fn main() i32 = {\n"
" g.y = 2002;\n"
" if (g.y != 2002) { return 1; };\n"
" return 0;\n"
"};\n", 0 },
{ "gst2",
"package main;\n"
"type pt = struct { x: int, y: int };\n"
"type pt1 = pt;\n"
"type pt2 = pt1;\n"
"let g: pt2;\n"
"export fn main() i32 = {\n"
" g.y = 2002;\n"
" if (g.y != 2002) { return 1; };\n"
" return 0;\n"
"};\n", 0 },
{ "gstlit",
"package main;\n"
"type pt = struct { x: int, y: int };\n"
"type pt1 = pt;\n"
"let g: pt1 = pt { x = 1001, y = 2002 };\n"
"export fn main() i32 = {\n"
" if (g.y != 2002) { return 1; };\n"
" return 0;\n"
"};\n", 0 },
{ "gsl2",
"package main;\n"
"type sl = []int;\n"
"type sl2 = sl;\n"
"let g: sl2 = [1001: int, 1002: int, 1003: int];\n"
"export fn main() i32 = {\n"
" if (g.len != 3) { return 1; };\n"
" if (g[2] != 1003) { return 2; };\n"
" return 0;\n"
"};\n", 0 },
/* [N]str rows also pin letpreintern's chased array-leg gate: a
* missed pre-intern desyncs _S_ label order vs cstage (byte-id
* would catch it as a label-number diff). */
{ "gstrarr1",
"package main;\n"
"type sa = [2]str;\n"
"let g: sa = [\"hello\", \"worlds!\"];\n"
"export fn main() i32 = {\n"
" if (g[1].len != 7) { return 1; };\n"
" return 0;\n"
"};\n", 0 },
{ "gstrarr2",
"package main;\n"
"type sa = [2]str;\n"
"type sa2 = sa;\n"
"let g: sa2 = [\"hello\", \"worlds!\"];\n"
"export fn main() i32 = {\n"
" if (g[1].len != 7) { return 1; };\n"
" return 0;\n"
"};\n", 0 },
{ "gdef_a2",
"package main;\n"
"type arr = [4]int;\n"
"type arr2 = arr;\n"
"def G: arr2 = [1001: int, 1002: int, 1003: int, 1004: int];\n"
"export fn main() i32 = {\n"
" if (G[3] != 1004) { return 1; };\n"
" return 0;\n"
"};\n", 0 },
{ "gdef_st",
"package main;\n"
"type pt = struct { x: int, y: int };\n"
"type pt1 = pt;\n"
"def G: pt1 = pt { x = 1001, y = 2002 };\n"
"export fn main() i32 = {\n"
" if (G.y != 2002) { return 1; };\n"
" return 0;\n"
"};\n", 0 },
{ "gdef_f2",
"package main;\n"
"type mf = f64;\n"
"type mf2 = mf;\n"
"def G: mf2 = 1.5;\n"
"export fn main() i32 = {\n"
" if (G != 1.5) { return 1; };\n"
" return 0;\n"
"};\n", 0 },
/* No-regression holds: alias global SLICE (green before this
* fold) and alias ELEMENT type (batch-1 win). */
{ "hold_slice1",
"package main;\n"
"type sl = []int;\n"
"let g: sl = [1001: int, 1002: int, 1003: int];\n"
"export fn main() i32 = {\n"
" if (g.len != 3) { return 1; };\n"
" if (g[2] != 1003) { return 2; };\n"
" return 0;\n"
"};\n", 0 },
{ "hold_elem",
"package main;\n"
"type row = [3]int;\n"
"let g: [2]row = [[1010: int, 1020: int, 1030: int], [1040: int, 1050: int, 1060: int]];\n"
"export fn main() i32 = {\n"
" if (g[0][0] != 1010) { return 1; };\n"
" if (g[1][2] != 1060) { return 2; };\n"
" return 0;\n"
"};\n", 0 },
};
static int
run_driver(const char *driver, const struct row *r, int i)
{
char tmpdir[96], src[160], outbin[160], errf[160], rmcmd[176], cmd[1024];
snprintf(tmpdir, sizeof tmpdir, "/tmp/agd_%d_d_%d", getpid(), i);
mkdir(tmpdir, 0755);
snprintf(src, sizeof src, "%s/agd_%d_%d.ww", tmpdir, getpid(), i);
snprintf(outbin, sizeof outbin, "%s/agd_%d_%d", tmpdir, getpid(), i);
snprintf(errf, sizeof errf, "%s/err", tmpdir);
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);
snprintf(cmd, sizeof cmd,
"timeout 20 %s build -o %s %s >/dev/null 2>%s",
driver, outbin, src, errf);
int brc = runwait(cmd);
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/agd_asm_%d_%d.ww", getpid(), i);
snprintf(cs, sizeof cs, "/tmp/agd_asm_%d_%d_c.s", getpid(), i);
snprintf(ws, sizeof ws, "/tmp/agd_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++) {
total++;
if (run_driver(wdrv, &rows[i], i) != 0) fail++;
}
for (int i = 0; i < n; i++) {
total++;
if (asm_byte_identical(bin, &rows[i], i) != 0) fail++;
}
}
if (fail) {
fprintf(stderr, "alias_global_decl: %d/%d checks failed\n",
fail, total);
return 1;
}
printf("alias_global_decl: %d/%d ok\n", total, total);
return 0;
}

View File

@@ -1,470 +0,0 @@
/*
* 944_alias_idx_family_run — #5 alias arc F2a batch 1 (task #60 +
* the #79 init-store rider): wwstage INDEX / SLICE / FOR-RANGE /
* LITERAL-INIT over an alias-NAMED base type. The tnode-keyed cgen
* walks saw only the N_TNAME leaf — esz fell to the 1-sentinel (8 on
* the init-store side) and the base classified as a POINTER (MOVQ of
* array words + no IMULQ): m8b_idx1/range1 SEGV 139, m8b_slice1
* silent-wrong past prefix-luck (m8c_slice1big exit 2), alias-[4]u32
* literal-init MOVQ stride-8 over a stride-4 slot = saved-BP/RIP
* smash (#79, masked when esz==8). cstage reads everything off the
* chased stamped type (type_chase_named/idx_eff, post-F1), so it is
* the runtime-correct reference; the fix re-keys the ww sites off
* tichase'd stamped tinfos (cgindex/cgassign-N_INDEX/cgslice/
* cgbasecap in cgenexpr.ww, cgforrange + cgarrlitfillbp + bare-let
* classify in cgenstmt.ww, pusharg N_SLICE in cgenutil.ww) and every
* row graduates to 0/0 byte-id.
*
* row | shape | want
* ------------------+------------------------------------------+-----
* idx0_ctl | named [4]int base read/store (control) | 0
* idx1_alias | m8b_idx1: r/w via 1-level alias arr | 0
* idx2_2level | write+read via arr2 = arr (944 pin) | 0
* idx_fwdref | decl-order permuted chain + compound += | 0
* init_u32_alias | #79: type A=[4]u32 literal-init, LAST |
* | elem readback (pre-fix BP/RIP smash) | 0
* initrep_u32_alias | #79: alias `[v...]` repeat fill — bound |
* | off the chased alen, LAST elem | 0
* loopfill_1024 | uninit alias [1024]int + loop-fill, LAST |
* | elem (pins the bare-let array classify: |
* | no composite zero-fill, cs-identical) | 0
* slice0_ctl | named base slice (control) | 0
* slice1_alias | m8b_slice1 + 1-level alias ARRAY base: |
* | sl dest + store + readback | 0
* slice2_2level | sl2 = sl, len/read/store + RE-SLICE of |
* | the alias slice | 0
* slice1big | m8c: 1000 elems, values > 255, LAST-elem |
* | readback + default-hi + .cap + range cnt | 0
* slice_fwdref | decl-after-use chain over 2-level alias |
* | array base, s[1] *= 3 compound | 0
* range0_ctl | named [4]int range (control) | 0
* range1_alias | m8b_range1: sum over alias arr | 0
* range2_2level | sum over arr2 = arr | 0
* range_slicealias | for-range over an alias SLICE | 0
* m7c_global2d | global [2]row (row = [3]int): g[1][2] | 0
* gslice_alias | GLOBAL alias-slice: .len + indexed read | 0
* slicearg_alias | slice-of-alias as CALL ARG (pusharg leg) | 0
*
* Values exceed 255 so an esz=1 byte-load cannot pass by little-endian
* prefix-luck; readbacks assert the LAST element. Every row runs BOTH
* drivers and asserts cstage/wwstage asm byte-identity (alias rows are
* graduations: ww aligned UP to the cs runtime-correct side). NNN<950,
* self-contained /tmp sources, no imports (944 precedent).
*
* Deliberately NOT pinned (g-fold territory, tasks #77/#78): any
* DIRECT alias-typed global ARRAY row. Expected state at this commit,
* probe-verified UNCHANGED by the fix: `let g: arr = [...]` — ww
* link-ERR (no DATA emitted for the alias-typed global), cs 1-level
* runs 0, cs 2-level runs WRONG (silent).
*/
#include <stdio.h>
#include <stdlib.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;
}
struct row { const char *label; const char *src; int want; };
static const struct row rows[] = {
{ "idx0_ctl",
"package main;\n"
"export fn main() i32 = {\n"
" let a: [4]int = [1000: int, 2000: int, 3000: int, 4000: int];\n"
" if (a[3] != 4000) { return 1; };\n"
" a[3] = 9999;\n"
" if (a[3] != 9999) { return 2; };\n"
" return 0;\n"
"};\n", 0 },
{ "idx1_alias",
"package main;\n"
"type arr = [4]int;\n"
"export fn main() i32 = {\n"
" let a: arr = [1000: int, 2000: int, 3000: int, 4000: int];\n"
" if (a[2] != 3000) { return 1; };\n"
" if (a[3] != 4000) { return 2; };\n"
" a[3] = 8888;\n"
" if (a[3] != 8888) { return 3; };\n"
" return 0;\n"
"};\n", 0 },
{ "idx2_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"
" if (a[3] != 4000) { return 3; };\n"
" return 0;\n"
"};\n", 0 },
{ "idx_fwdref",
"package main;\n"
"type arr2 = arr;\n"
"type arr = [4]int;\n"
"export fn main() i32 = {\n"
" let a: arr2 = [1000: int, 2000: int, 3000: int, 4000: int];\n"
" if (a[3] != 4000) { return 1; };\n"
" a[3] += 500;\n"
" if (a[3] != 4500) { return 2; };\n"
" return 0;\n"
"};\n", 0 },
/* #79: narrow-elem alias literal-init. Pre-fix the per-element
* store rode the esz=8 sentinel + MOVQ over a stride-4 slot —
* elements 2/3 landed at 0(BP)/+8(BP) = saved-BP/RIP smash
* (masked when esz==8). LAST element read back. */
{ "init_u32_alias",
"package main;\n"
"type A = [4]u32;\n"
"export fn main() i32 = {\n"
" let a: A = [1: u32, 2: u32, 3: u32, 4: u32];\n"
" if (a[3] != 4) { return 1; };\n"
" if (a[0] != 1) { return 2; };\n"
" return 0;\n"
"};\n", 0 },
/* #79 repeat leg: the `[v...]` fill bound comes off the chased
* tinfo's alen (an alias arrtn has no length tnode). */
{ "initrep_u32_alias",
"package main;\n"
"type A = [6]u32;\n"
"export fn main() i32 = {\n"
" let a: A = [7: u32...];\n"
" if (a[5] != 7) { return 1; };\n"
" if (a[0] != 7) { return 2; };\n"
" return 0;\n"
"};\n", 0 },
/* Uninit alias array + per-index loop fill. Also pins the
* bare-let classify: an alias-to-array keeps the per-index-write
* contract (no composite zero-fill — cstage-identical asm). */
{ "loopfill_1024",
"package main;\n"
"type arrk = [1024]int;\n"
"export fn main() i32 = {\n"
" let a: arrk;\n"
" let i: int = 0;\n"
" for (i < 1024) {\n"
" a[i] = i * 3 + 1000;\n"
" i += 1;\n"
" };\n"
" if (a[1023] != 1023 * 3 + 1000) { return 1; };\n"
" return 0;\n"
"};\n", 0 },
{ "slice0_ctl",
"package main;\n"
"export fn main() i32 = {\n"
" let a: [4]int = [1000: int, 2000: int, 3000: int, 4000: int];\n"
" let s: []int = a[1:3];\n"
" if (s.len != 2) { return 1; };\n"
" if (s[1] != 3000) { return 2; };\n"
" return 0;\n"
"};\n", 0 },
/* alias slice DEST over a 1-level alias ARRAY base (slice-expr
* over alias base, 1-level leg). */
{ "slice1_alias",
"package main;\n"
"type arr = [4]int;\n"
"type sl = []int;\n"
"export fn main() i32 = {\n"
" let a: arr = [1000: int, 2000: int, 3000: int, 4000: int];\n"
" let s: sl = 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 },
/* 2-level alias slice dest + RE-SLICE of the alias slice (the
* cgslice alias-SLICE-base leg). */
{ "slice2_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"
" if (s[1] != 7777) { return 4; };\n"
" let r: sl = s[0:2];\n"
" if (r.len != 2) { return 5; };\n"
" if (r[1] != 7777) { return 6; };\n"
" return 0;\n"
"};\n", 0 },
/* 1000 elements, values 300..7293: an esz=1 stride/byte load
* cannot land on the right word, and the LAST-element readback
* breaks prefix-luck (m8c). Also pins alias default-hi (a[2:]),
* .cap via the chased cgbasecap leg, and range over the
* 2-level-alias sub-slice. Base array stays plain [1000]int so
* this row pins the slice legs in isolation — the alias bare-let
* + loop-fill shape is loopfill_1024's pin (the #79-rider
* bare-let array classify). */
{ "slice1big",
"package main;\n"
"type slk = []int;\n"
"type slk2 = slk;\n"
"export fn main() i32 = {\n"
" let a: [1000]int;\n"
" let i: int = 0;\n"
" for (i < 1000) {\n"
" a[i] = i * 7 + 300;\n"
" i += 1;\n"
" };\n"
" let s: slk = a[1:1000];\n"
" if (s.len != 999) { return 1; };\n"
" if (s[998] != 999 * 7 + 300) { return 2; };\n"
" s[998] = 123456;\n"
" if (a[999] != 123456) { return 3; };\n"
" let t: slk2 = a[2:];\n"
" if (t.len != 998) { return 4; };\n"
" if (t.cap != 998) { return 5; };\n"
" if (t[997] != 123456) { return 6; };\n"
" let cnt: int = 0;\n"
" for (let x .. t) { cnt = cnt + 1; if (x < 0) { return 8; }; };\n"
" if (cnt != 998) { return 7; };\n"
" return 0;\n"
"};\n", 0 },
{ "slice_fwdref",
"package main;\n"
"export fn main() i32 = {\n"
" let a: arr2 = [1000: int, 2000: int, 3000: int, 4000: int];\n"
" let s: sl2 = a[1:3];\n"
" if (s[1] != 3000) { return 1; };\n"
" s[1] *= 3;\n"
" if (a[2] != 9000) { return 2; };\n"
" return 0;\n"
"};\n"
"type sl2 = sl;\n"
"type sl = []int;\n"
"type arr2 = arr;\n"
"type arr = [4]int;\n", 0 },
{ "range0_ctl",
"package main;\n"
"export fn main() i32 = {\n"
" let a: [4]int = [1: int, 2: int, 3: int, 4: int];\n"
" let sum: int = 0;\n"
" for (let x .. a) { sum = sum + x; };\n"
" if (sum != 10) { return 1; };\n"
" return 0;\n"
"};\n", 0 },
{ "range1_alias",
"package main;\n"
"type arr = [4]int;\n"
"export fn main() i32 = {\n"
" let a: arr = [1000: int, 2000: int, 3000: int, 4000: int];\n"
" let sum: int = 0;\n"
" for (let x .. a) { sum = sum + x; };\n"
" if (sum != 10000) { return 1; };\n"
" return 0;\n"
"};\n", 0 },
{ "range2_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"
" let sum: int = 0;\n"
" for (let x .. a) { sum = sum + x; };\n"
" if (sum != 10000) { return 1; };\n"
" return 0;\n"
"};\n", 0 },
{ "range_slicealias",
"package main;\n"
"type sl = []int;\n"
"export fn main() i32 = {\n"
" let a: [4]int = [1000: int, 2000: int, 3000: int, 4000: int];\n"
" let t: sl = a[0:4];\n"
" let sum: int = 0;\n"
" for (let x .. t) { sum = sum + x; };\n"
" if (sum != 10000) { return 1; };\n"
" return 0;\n"
"};\n", 0 },
/* m7c: the BASE is a plain [2]row global — the alias sits on the
* ELEMENT (row = [3]int). elemisarrayc's node walk can't see
* through the element's N_TNAME, so g[0] loaded a VALUE where the
* sub-array ADDRESS was needed (ww SEGV on the read; DATA emit
* was already correct both stages, F0). LAST element checked. */
{ "m7c_global2d",
"package main;\n"
"type row = [3]int;\n"
"let g: [2]row = [[10: int, 20: int, 30: int], [40: int, 50: int, 60: int]];\n"
"export fn main() i32 = {\n"
" if (g[0][0] != 10) { return 1; };\n"
" if (g[1][2] != 60) { return 2; };\n"
" return 0;\n"
"};\n", 0 },
/* GLOBAL alias-typed SLICE: DATA emit + .len + indexed read all
* resolve (the global ARRAY twin does NOT — see the header note;
* g-fold #77/#78). */
{ "gslice_alias",
"package main;\n"
"type sl = []int;\n"
"let g: sl = [1000: int, 2000: int, 3000: int];\n"
"export fn main() i32 = {\n"
" if (g.len != 3) { return 1; };\n"
" if (g[2] != 3000) { return 2; };\n"
" return 0;\n"
"};\n", 0 },
/* slice-of-alias-array as a CALL ARG exercises the pusharg
* N_SLICE leg (cgenutil.ww), a distinct lowering from cgslice;
* plus the inferred-let receive of an alias-base slice. */
{ "slicearg_alias",
"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 },
};
static int
run_driver(const char *driver, const struct row *r, int i)
{
char src[128], tmpdir[96], outbin[128], errf[128], rmcmd[160], cmd[1024];
snprintf(tmpdir, sizeof tmpdir, "/tmp/aif_%d_d_%d", getpid(), i);
mkdir(tmpdir, 0755);
snprintf(src, sizeof src, "%s/aif_%d_%d.ww", tmpdir, getpid(), i);
snprintf(outbin, sizeof outbin, "%s/aif_%d_%d", tmpdir, getpid(), i);
snprintf(errf, sizeof errf, "%s/err", tmpdir);
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);
snprintf(cmd, sizeof cmd,
"timeout 20 %s build -o %s %s >/dev/null 2>%s",
driver, outbin, src, errf);
int brc = runwait(cmd);
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/aif_asm_%d_%d.ww", getpid(), i);
snprintf(cs, sizeof cs, "/tmp/aif_asm_%d_%d_c.s", getpid(), i);
snprintf(ws, sizeof ws, "/tmp/aif_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++) {
total++;
if (run_driver(wdrv, &rows[i], i) != 0) fail++;
}
for (int i = 0; i < n; i++) {
total++;
if (asm_byte_identical(bin, &rows[i], i) != 0) fail++;
}
}
if (fail) {
fprintf(stderr, "alias_idx_family: %d/%d checks failed\n",
fail, total);
return 1;
}
printf("alias_idx_family: %d/%d ok\n", total, total);
return 0;
}

View File

@@ -1,248 +0,0 @@
/*
* 944_alias_structlit_init_run — #63: let-init from an alias-NAMED
* struct LITERAL. wwstage's cglet N_STRUCTLIT arm resolved the struct
* by a BARE structlookup(c, sname): for an alias `type rep2 = rep`
* only the base `rep` is registered, so the lookup returned nil and
* the field-fill never fired. The nil then split by slot size —
* • <=8B: the small-let scalar default zeroed the slot and DROPPED
* the literal (SILENT wrong: `let r = rep2{id=6}` read 0), and
* • >8B: no fill arm matched -> the cglet "unhandled rhs shape"
* LOUD (task #7/rule-7).
* Same root, two symptoms. The fix routes the arm through
* structlookupchain (the #92/W2 SSoT already used at cgenstmt:1974 /
* :2687), which chases the alias chain to the base struct. cstage
* operates on the resolved Type* via type_chase_named and was always
* correct, so this is ww-only align-UP; cs UNTOUCHED. Oracle: ken
* .ai/ken-63-oracle.md.
*
* The N_IDENT-copy (cgenstmt:2625) and N_CALL-recv (:2511) sibling
* arms are also bare-structlookup but are NOT in scope: the copy
* falls through to a generic path byte-identical with cstage (both
* stages run correct), and the recv is blocked upstream by the
* aggregate-return shape (#272/#277), and the ≤24B return (:1363)
* likewise louds via the scalar-default catch. The >24B sret RETURN
* (:1250) had NO such catch — it was silently wrong (returned an
* uninitialised sret buffer); reviewer-63 routed it through
* structlookupchain in the same commit (see sret_return_alias32).
* The N_IDENT struct-copy (:2625) falls through to a generic path
* both stages run correct (asm divergence is the #81/#65 alias
* field-READ class). See the #63 ledger.
*
* row | shape | want
* -------------------+---------------------------------------+-----
* letinit_typed | type rep2=rep(8B); let r: rep2 = |
* | rep2{id=6}; read r.id (was silent 0) | 6
* letinit_untyped | inferred: let r = rep2{id=6}; r.id | 6
* letlit_alias16 | type row=st(16B); let a: row = |
* | row{a=3,b=4}; read a.a+a.b (was LOUD) | 7
* control_direct | non-alias pt2{...} 16B let-init — the |
* | no-regress control (alias hop is the |
* | trigger), byte-id both stages | 7
* sret_return_alias32| type biga=big(32B); mk() returns |
* | biga{...}; the >24B sret RETURN twin |
* | (:1250, was silent 0) | 10
*
* Every row asserts cstage/wwstage asm byte-id (rule 10). 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 <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;
}
struct row { const char *label; const char *src; int want; };
static const struct row rows[] = {
{ "letinit_typed",
"package main;\n"
"type rep = struct { id: size };\n"
"type rep2 = rep;\n"
"export fn main() i32 = {\n"
" let r: rep2 = rep2{id=6};\n"
" return r.id: i32;\n"
"};\n", 6 },
{ "letinit_untyped",
"package main;\n"
"type rep = struct { id: size };\n"
"type rep2 = rep;\n"
"export fn main() i32 = {\n"
" let r = rep2{id=6};\n"
" return r.id: i32;\n"
"};\n", 6 },
{ "letlit_alias16",
"package main;\n"
"type st = struct { a: size, b: size };\n"
"type row = st;\n"
"export fn main() i32 = {\n"
" let a: row = row{a=3, b=4};\n"
" return (a.a + a.b): i32;\n"
"};\n", 7 },
{ "control_direct",
"package main;\n"
"type pt2 = struct { a: size, b: size };\n"
"export fn main() i32 = {\n"
" let x: pt2 = pt2{a=3, b=4};\n"
" return (x.a + x.b): i32;\n"
"};\n", 7 },
/* reviewer-63 survivor leg: the >24B sret-RETURN twin of the
* let-init site (cgenstmt:1250). sretretsize chases the alias for
* the size gate so the sret arm fires, but the field-fill used a
* bare structlookup(sname) that missed the alias name -> the fill
* was SKIPPED and the callee returned an uninitialised sret buffer
* (ww silent 0; cs correct 10). The impl ledger wrongly declined
* :1250 as "already chases"; routed through structlookupchain. */
{ "sret_return_alias32",
"package main;\n"
"type big = struct { a: size, b: size, c: size, d: size };\n"
"type biga = big;\n"
"fn mk() biga = { return biga{a=1, b=2, c=3, d=4}; };\n"
"export fn main() i32 = {\n"
" let r: biga = mk();\n"
" return (r.a + r.b + r.c + r.d): i32;\n"
"};\n", 10 },
};
/* build+run via a driver (ww / ww_ww); returns 0 pass, nonzero fail. */
static int
run_driver(const char *driver, const struct row *r, int i)
{
char tmpdir[96], src[128], outbin[128], errf[128], rmcmd[128], cmd[1024];
snprintf(tmpdir, sizeof tmpdir, "/tmp/asli_%d_d_%d", getpid(), i);
mkdir(tmpdir, 0755);
snprintf(src, sizeof src, "%s/asli_%d_%d.ww", tmpdir, getpid(), i);
snprintf(outbin, sizeof outbin, "%s/asli_%d_%d", tmpdir, getpid(), i);
snprintf(errf, sizeof errf, "%s/err", tmpdir);
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);
snprintf(cmd, sizeof cmd,
"timeout 20 %s build -o %s %s >/dev/null 2>%s",
driver, outbin, src, errf);
int brc = runwait(cmd);
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;
}
/* cs==ww .s byte-id (rule 10). */
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/asli_asm_%d_%d.ww", getpid(), i);
snprintf(cs, sizeof cs, "/tmp/asli_asm_%d_%d_c.s", getpid(), i);
snprintf(ws, sizeof ws, "/tmp/asli_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++) {
total++;
if (run_driver(wdrv, &rows[i], i) != 0) fail++;
}
for (int i = 0; i < n; i++) {
total++;
if (asm_byte_identical(bin, &rows[i], i) != 0) fail++;
}
}
if (fail) {
fprintf(stderr, "alias_structlit_init: %d/%d checks failed\n",
fail, total);
return 1;
}
printf("alias_structlit_init: %d/%d ok\n", total, total);
return 0;
}

View File

@@ -0,0 +1,8 @@
//ww:error "assert: cond must be bool"
package main;
type myb = bool;
export fn main() i32 = {
let b: myb = true;
assert(b);
return 0;
};

View File

@@ -0,0 +1,13 @@
//ww:error "operands have differing types"
// #5-C3 Q4: the historical "cs loud / ww silent by design" tag is SUPERSEDED
// — at HEAD 07b3c74 BOTH stages reject with this substring (divergence closed).
// Do NOT re-split this into a cs-only pin: the reject is now symmetric.
package main;
type k1 = int;
type k2 = int;
export fn main() i32 = {
let a: k1 = 3;
let b: k2 = 4;
let c = a + b;
return c: i32;
};

View File

@@ -0,0 +1,8 @@
//ww:error "circular type dependency"
package main;
type a = b;
type b = a;
export fn main() i32 = {
if (size(a) != 8) { return 1; };
return 0;
};

View File

@@ -0,0 +1,7 @@
//ww:error "circular type dependency"
package main;
type a = a;
export fn main() i32 = {
if (size(a) != 8) { return 1; };
return 0;
};

View File

@@ -0,0 +1,8 @@
//ww:error "circular type dependency"
package main;
type s1 = struct { x: s2 };
type s2 = struct { x: s1 };
export fn main() i32 = {
if (size(s1) != 8) { return 1; };
return 0;
};

View File

@@ -0,0 +1,9 @@
//ww:error "has a str/slice/struct/tagged element"
package main;
type el0 = struct { a: i64 };
type S = struct { arr: [2]el0, n: i64 };
export fn main() i32 = {
let s = S { arr = [el0 { a = 5 }, el0 { a = 6 }], n = 3 };
if (s.arr[0].a + s.arr[1].a + s.n != 14) { return 1; };
return 0;
};

View File

@@ -0,0 +1,10 @@
//ww:error "has a str/slice/struct/tagged element"
package main;
type el0 = struct { a: i64 };
type el = el0;
type S = struct { arr: [2]el, n: i64 };
export fn main() i32 = {
let s = S { arr = [el0 { a = 5 }, el0 { a = 6 }], n = 3 };
if (s.arr[0].a + s.arr[1].a + s.n != 14) { return 1; };
return 0;
};

View File

@@ -0,0 +1,12 @@
//ww:error "float-bearing struct arg from a non-ident source"
package main;
type fs0 = struct { x: f64 };
fn mk() fs0 = {
let s: fs0; s.x = 2.5;
return s;
};
fn g(p: fs0) f64 = { return p.x; };
export fn main() i32 = {
if (g(mk()) != 2.5) { return 1; };
return 0;
};

View File

@@ -0,0 +1,11 @@
//ww:error "#129 A.2 scope"
package main;
type s1t = str;
type s2t = s1t;
type box = struct { s: s2t, n: int };
let g: box = box { s = "hello", n = 5: int };
export fn main() i32 = {
if (g.n != 5) { return 1; };
if (g.s.len != 5) { return 2; };
return 0;
};

View File

@@ -0,0 +1,9 @@
//ww:error "not assignable"
package main;
type ms0 = []i64;
type ms = ms0;
let G: []ms = [[1, 2], [3]];
export fn main() i32 = {
if (len(G) != 2) { return 1; };
return 0;
};

View File

@@ -0,0 +1,7 @@
//ww:error "slice-of-{str,slice,tagged} literal static-init unsupported"
package main;
let G: []str = ["aa", "bbb"];
export fn main() i32 = {
if (len(G[0]) != 2) { return 1; };
return 0;
};

View File

@@ -0,0 +1,22 @@
//ww:error "sret-class call result unwired"
package main;
type e0 = !i64;
type big = struct { a: i64, b: i64, c: i64, d: i64, e: i64, f: i64, g: i64 };
type r0 = (big | e0);
type r = r0;
fn w() r = {
let s: big;
s.a = 1; s.b = 2; s.c = 3; s.d = 4; s.e = 5; s.f = 6; s.g = 77;
return s;
};
fn outer() (i64 | e0) = {
let v = w()?;
return v.g;
};
export fn main() i32 = {
match (outer()) {
case let n: i64 => { if (n != 77) { return 1; }; };
case e0 => { return 2; };
};
return 0;
};

View File

@@ -0,0 +1,13 @@
//ww:error "aggregate init from unhandled rhs shape"
package main;
type base = struct { a: size, b: size };
type ali = base;
export fn main() i32 = {
let x: ali;
x.a = 4; x.b = 9;
let v: (void | ali) = x;
if (!(v is ali)) { return 1; };
let w = v as ali;
if (w.b != 9) { return 2; };
return 0;
};

View File

@@ -0,0 +1,12 @@
//ww:error "not assignable"
// #5-C3 Q4: the historical "cs loud / ww silent by design" tag is SUPERSEDED
// — at HEAD 07b3c74 BOTH stages reject (common substring "not assignable";
// divergence closed). Do NOT re-split into a cs-only pin.
package main;
type inner = (i64 | str);
type inner2 = inner;
export fn main() i32 = {
let v: (void | inner2) = 7;
if (v is void) { return 1; };
return 0;
};

View File

@@ -0,0 +1,10 @@
//ww:error "bare source structurally matches >=2 NAMED variants"
package main;
type p1 = *i64;
type p2 = *i64;
export fn main() i32 = {
let x: i64 = 7;
let v: (void | p1 | p2) = &x;
if (v is p1) { return 0; };
return 1;
};

View File

@@ -0,0 +1,12 @@
//ww:error "bare source structurally matches >=2 NAMED variants"
package main;
type q1 = *i64;
type p1 = q1;
type q2 = *i64;
type p2 = q2;
export fn main() i32 = {
let x: i64 = 7;
let v: (void | p1 | p2) = &x;
if (v is p1) { return 0; };
return 1;
};