The N_STRUCTLIT arm still did bare structlookup on the literal's type
name — an alias-named struct LITERAL widened into a union (`type ali =
base; let v: (void|ali) = ali{...}`) missed the registered structinfo
and fell to the scalar widen arm: word0-only/dropped payload, cs 0 /
ww EXIT 1, byte-id NO (reviewer-B2 find, pre-existing at 486f7f8's
parent). Exactly the class batch-2 c2 closed for the N_IDENT-local arm
of the SAME function; same funnel fix — route through structlookupchain
(cgenutil.ww:1758) and return si.sname so every consumer's re-lookup
hits the REGISTERED name.
One pre-authorized rider: structlookupchain's entry gate accepted only
N_TNAME, but a struct literal's type ref parses as N_IDENT (expression
position, lib/ww/parse/expr.ww builds s.lhs as N_IDENT — OBSERVED).
Widened to `N_TNAME || N_IDENT`; the entry-kind predicate is spelled
twice (the early-return and the chain loop's first iteration — the
loop reassigns cur to aliaslookup results, which are always N_TNAME,
so later iterations are untouched). Consumer census, all 10 call
sites: cgenutil:3187(+this arm; post-commit position), cgenexpr:2927/3006/8775/9011,
cgenstmt:3033 guard on N_TNAME explicitly before calling;
cgenexpr:5756 (etnode = type-spec .lhs), cgenstmt:1978 (arrtn.lhs or
the synthesized #79 N_TNAME), cgenstmt:2695 (cglet n.lhs declared
type spec) pass parsetype products only — parsetype builds zero
N_IDENT nodes (lib/ww/parse/parse.ww). No existing caller can pass
N_IDENT: the widening is strictly accepting-more; existing callers
unmoved. NO second inline chase in the arm (close-by-construction).
Base spellings byte-id: structlookup hits at the chain entry and
si.sname == the literal's own name — same string out, same asm.
Pin: 944_alias_accept_run union_slit_{base_ctl,alias,alias2,order} —
base control holds 0/0; 1/2-level alias + permuted decl order graduate
cs0/ww1-byte-id-NO -> 0/0 byte-id. #63 PROBED post-c3 per the
enrollment rule: does NOT green at this site (8B alias struct-lit
let-init still ww silent-zero-fill exit 1; 16B still loud "aggregate
init from unhandled rhs shape") — its miss is the cgenstmt let-init
dispatch, not rhsstructpayload; documented on task #63, left red, no
row enrolled.
Light gates: test-unit 290 green; sizelint 0; 989 ratchet zero flips;
five-mains NEUTRAL vs master-74195ac scratch on identical inputs +
cs==ww on all five. combined.ww regens ride along (#110).
1154 lines
39 KiB
C
1154 lines
39 KiB
C
/*
|
||
* 944_alias_accept_run — #5 alias arc F1: cstage acceptance ALIGN-UP
|
||
* through the transitive TY_NAMED chase (type_chase_named, promoted to
|
||
* cmd/wcc/type.c). harec dealiases at every promotion/cond/assign
|
||
* consumer (ref/harec/src/types.c:53 type_dealias; :989-996
|
||
* type_is_assignable; src/check.c:1083-1105 type_promote; :2141 if,
|
||
* :2515 for, :3229 &&/||, :3572 !) — wwstage already accepted these
|
||
* shapes AND ran them Hare-right (F0 census /tmp/f0/livelist.md), so
|
||
* the cstage single-peel rejects were the lean side aligned UP.
|
||
*
|
||
* row | shape | want
|
||
* ---------------------+--------------------------------------+-----
|
||
* binop_alias_base | myint + int (F0 m1_binop) | 0
|
||
* binop_2level | myint2 % int, myu / u32 (m1_binop2) | 0
|
||
* ret_through_2level | fn(x: myint2) int = x * 2 | 0
|
||
* assign_alias_alias | k1 → k2 (same base; harec dealias- |
|
||
* | both admits) | 0
|
||
* binop_alias_vs_alias | k1 + k2 — cstage stays LOUD per |
|
||
* | harec type_promote ALIAS+ALIAS→NULL | err(cs)
|
||
* cond_if/for/bang/ | alias-of-bool at every cond consumer |
|
||
* andor/fnparam | (F0 m2_* family) | 0
|
||
* assert_stays_loud | alias-bool assert — BOTH stages loud |
|
||
* | (F0 2a DISSOLVED-SYMMETRIC; the Hare |
|
||
* | widening is parked on #5) | err
|
||
* dot_2level | field access via a3=b3=c3=struct |
|
||
* | (task #70, ken c3_chain3) | 0
|
||
* deref_alias_ptr | *p through pi2=pi=*int | 0
|
||
* idx/slice/range_ | index/slice/for-range over 2-level |
|
||
* 2level, slice_arg | alias bases (F0 8b) — cs cgen index |
|
||
* | family chased (idx_eff + base |
|
||
* | classify); ww half landed (#60, F2a |
|
||
* | batch 1 tichase) — graduated K_RUN | 0
|
||
* arg_2level_* | task #61: alias-NAMED struct PARAM |
|
||
* | classify (fwd-ref / lit-init / 40B |
|
||
* | 5-eightbyte / f64 SSE class legs + |
|
||
* | base control) | 0
|
||
* float_alias_param* / | ken-v3 leg: 2-level f64/str/slice |
|
||
* str_alias_2level / | aliases at the cgen KIND classifiers |
|
||
* slice_alias_param | (slice leg graduated, #60 F2a b1) | 0
|
||
* slicefield_* / | reviewer-F1 leg: 2-level alias of |
|
||
* strfield_store_2lvl | slice/str as a STRUCT FIELD type — |
|
||
* | cgen field gates chased (stores, |
|
||
* | struct-lit, walk leaves, reads); |
|
||
* | unprobed gates LOUD-tripwired (#73, |
|
||
* | K_BUILDERR_CS pin) | 0
|
||
* union_store_* + | task #62 Layer-2: alias-NAMED struct |
|
||
* union_push_arg | as union member — widen store/push |
|
||
* | word0-only; cs half c138605, ww half |
|
||
* | F2a batch-2 c2 — graduated K_RUN; |
|
||
* | base ctl + #54-bound `as` row loud | 0
|
||
* union_slit_* | task #92 (F2a batch-3 c3): alias- |
|
||
* | named struct LITERAL into a union — |
|
||
* | rhsstructpayload N_STRUCTLIT arm |
|
||
* | routed through structlookupchain; |
|
||
* | base ctl + 1/2-level + decl order | 0
|
||
* nested_alias_field_* | task #71: alias-typed nested-field |
|
||
* | store/read/addr-of walks fold to |
|
||
* | direct offsets (byte-id graduation, |
|
||
* | both decl orders) | 0
|
||
*
|
||
* K_RUN rows also assert cstage/wwstage asm byte-id (acceptance
|
||
* graduations land byte-identical — F0's accept side was wwstage).
|
||
* K_RUN_CS / K_BUILDERR_CS rows run the cstage driver only, each
|
||
* citing the task that graduates them. binop_alias_vs_alias is
|
||
* CS-only loud: the wwstage checker stays silent on typed mismatches
|
||
* by design (5-lite discipline) — cs pins the harec-parity reject.
|
||
* NNN<950, self-contained (/tmp, no imports) — rule-14's selfhost-
|
||
* sibling race does not apply (941/944 precedent).
|
||
*/
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <unistd.h>
|
||
#include <sys/stat.h>
|
||
#include <sys/wait.h>
|
||
|
||
static int
|
||
runwait(const char *cmd)
|
||
{
|
||
int rc = system(cmd);
|
||
if (rc == -1) return -1;
|
||
if (WIFEXITED(rc)) return WEXITSTATUS(rc);
|
||
return -1;
|
||
}
|
||
|
||
static int
|
||
slurp_eq(const char *a, const char *b)
|
||
{
|
||
FILE *fa = fopen(a, "rb");
|
||
FILE *fb = fopen(b, "rb");
|
||
if (!fa || !fb) { if (fa) fclose(fa); if (fb) fclose(fb); return -1; }
|
||
int rc = 0;
|
||
for (;;) {
|
||
int ca = fgetc(fa), cb = fgetc(fb);
|
||
if (ca != cb) { rc = -1; break; }
|
||
if (ca == EOF) break;
|
||
}
|
||
fclose(fa); fclose(fb);
|
||
return rc;
|
||
}
|
||
|
||
#define K_RUN 0 /* build+run BOTH drivers, exit==want, + byte-id */
|
||
#define K_BUILDERR 1 /* build FAILS with experr on BOTH drivers */
|
||
#define K_RUN_CS 2 /* cstage only — ww half pending (cite at row) */
|
||
#define K_BUILDERR_CS 3 /* cstage-only loud (ww silent by design) */
|
||
|
||
struct row { const char *label; const char *src; int want;
|
||
int kind; const char *experr; };
|
||
|
||
/* errlog_has — a BUILDERR row must fail WITH its diagnostic; any other
|
||
* failure (parse error, crash, hang-kill) is a vacuous reject (940
|
||
* precedent). */
|
||
static int
|
||
errlog_has(const char *path, const char *needle)
|
||
{
|
||
FILE *f = fopen(path, "rb");
|
||
if (!f) return 0;
|
||
char buf[8192];
|
||
size_t got = fread(buf, 1, sizeof buf - 1, f);
|
||
fclose(f);
|
||
buf[got] = '\0';
|
||
return strstr(buf, needle) != NULL;
|
||
}
|
||
|
||
static const struct row rows[] = {
|
||
{ "binop_alias_base",
|
||
"package main;\n"
|
||
"type myint = int;\n"
|
||
"export fn main() i32 = {\n"
|
||
" let a: myint = 5;\n"
|
||
" let b: int = 3;\n"
|
||
" let c = a + b;\n"
|
||
" if (c != 8) { return 1; };\n"
|
||
" let d: myint = 2;\n"
|
||
" if (a * d != 10) { return 2; };\n"
|
||
" if (a < b) { return 3; };\n"
|
||
" if (a - b != 2) { return 4; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
{ "binop_2level",
|
||
"package main;\n"
|
||
"type myint = int;\n"
|
||
"type myint2 = myint;\n"
|
||
"type myu = u32;\n"
|
||
"export fn main() i32 = {\n"
|
||
" let a: myint2 = 7;\n"
|
||
" let b: int = 2;\n"
|
||
" if (a % b != 1) { return 1; };\n"
|
||
" let u: myu = 10: u32;\n"
|
||
" let v: u32 = 3: u32;\n"
|
||
" if (u / v != 3: u32) { return 2; };\n"
|
||
" if (u + v != 13: u32) { return 3; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
{ "ret_through_2level",
|
||
"package main;\n"
|
||
"type myint = int;\n"
|
||
"type myint2 = myint;\n"
|
||
"fn dbl(x: myint2) int = {\n"
|
||
" return x * 2;\n"
|
||
"};\n"
|
||
"export fn main() i32 = {\n"
|
||
" let a: myint2 = 21;\n"
|
||
" if (dbl(a) != 42) { return 1; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
{ "assign_alias_alias",
|
||
"package main;\n"
|
||
"type k1 = int;\n"
|
||
"type k2 = int;\n"
|
||
"export fn main() i32 = {\n"
|
||
" let x: k1 = 5;\n"
|
||
" let y: k2 = x;\n"
|
||
" if (y != 5) { return 1; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
/* harec type_promote: ALIAS+ALIAS → NULL even on a shared base
|
||
* (ref/harec/src/check.c:1087-1089). wwstage's checker is silent
|
||
* on typed mismatches (5-lite) — cs-only pin. */
|
||
{ "binop_alias_vs_alias",
|
||
"package main;\n"
|
||
"type k1 = int;\n"
|
||
"type k2 = int;\n"
|
||
"export fn main() i32 = {\n"
|
||
" let x: k1 = 5;\n"
|
||
" let y: k2 = 3;\n"
|
||
" if (x + y != 8) { return 1; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_BUILDERR_CS, "operands have differing types" },
|
||
{ "cond_if",
|
||
"package main;\n"
|
||
"type myb = bool;\n"
|
||
"export fn main() i32 = {\n"
|
||
" let b: myb = true;\n"
|
||
" if (b) { return 0; };\n"
|
||
" return 1;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
{ "cond_for",
|
||
"package main;\n"
|
||
"type myb = bool;\n"
|
||
"export fn main() i32 = {\n"
|
||
" let b: myb = true;\n"
|
||
" let i: int = 0;\n"
|
||
" for (b) {\n"
|
||
" i = i + 1;\n"
|
||
" if (i >= 3) { b = false; };\n"
|
||
" };\n"
|
||
" if (i != 3) { return 1; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
{ "cond_bang",
|
||
"package main;\n"
|
||
"type myb = bool;\n"
|
||
"export fn main() i32 = {\n"
|
||
" let b: myb = false;\n"
|
||
" let n = !b;\n"
|
||
" if (!n) { return 1; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
{ "cond_andor",
|
||
"package main;\n"
|
||
"type myb = bool;\n"
|
||
"export fn main() i32 = {\n"
|
||
" let b: myb = true;\n"
|
||
" let c: myb = false;\n"
|
||
" if (b && !c) { } else { return 1; };\n"
|
||
" if (c || b) { } else { return 2; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
{ "cond_fnparam",
|
||
"package main;\n"
|
||
"type myb = bool;\n"
|
||
"fn pick(b: myb) i32 = {\n"
|
||
" if (b) { return 0; };\n"
|
||
" return 1;\n"
|
||
"};\n"
|
||
"export fn main() i32 = {\n"
|
||
" let b: myb = true;\n"
|
||
" return pick(b);\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
{ "assert_stays_loud",
|
||
"package main;\n"
|
||
"type myb = bool;\n"
|
||
"export fn main() i32 = {\n"
|
||
" let b: myb = true;\n"
|
||
" assert(b);\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_BUILDERR, "assert: cond must be bool" },
|
||
{ "dot_2level",
|
||
"package main;\n"
|
||
"type a3 = b3;\n"
|
||
"type b3 = c3;\n"
|
||
"type c3 = struct { x: size, y: size, z: size };\n"
|
||
"export fn main() i32 = {\n"
|
||
" if (size(a3) != 24) { return 1; };\n"
|
||
" if (size((void | a3)) != 32) { return 2; };\n"
|
||
" let v: a3;\n"
|
||
" v.x = 1; v.y = 2; v.z = 3;\n"
|
||
" if (v.x + v.y + v.z != 6) { return 3; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
{ "deref_alias_ptr",
|
||
"package main;\n"
|
||
"type pi = *int;\n"
|
||
"type pi2 = pi;\n"
|
||
"export fn main() i32 = {\n"
|
||
" let v: int = 41;\n"
|
||
" let p: pi2 = &v;\n"
|
||
" if (*p != 41) { return 1; };\n"
|
||
" *p = 7;\n"
|
||
" if (v != 7) { return 2; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
/* ---- reviewer-F1 find: 2-level alias of slice/str as a STRUCT
|
||
* FIELD type. The acceptance above admits every construction; the
|
||
* cgen FIELD-TYPE gates single-peeled, so the slice/str 3-word
|
||
* arms fell to word0-only scalar tails — SILENT wrong (ww correct,
|
||
* every shape LOUD at pristine 738d7f4 = opened by this commit).
|
||
* Chased gates: single-dot store (+via-ptr), struct-lit fill,
|
||
* chained store-walk leaf, chained-ptr-field store, single-dot /
|
||
* via-ptr / chained-walk reads. Each row pins one gate; the
|
||
* noise() call clobbers BX/CX so stale-register luck can't pass a
|
||
* word0-only header. Unprobed sibling gates are LOUD-tripwired,
|
||
* pinned by the #73 row at the end of this block. Rows whose
|
||
* `.len` readback rides the chained-dot READ walk entered as
|
||
* K_RUN_CS (runtime-correct both stages; cs took the generic
|
||
* spine) and graduated to K_RUN with the #71 walk chase. */
|
||
{ "slicefield_store_2lvl",
|
||
"package main;\n"
|
||
"type sl = []int;\n"
|
||
"type sl2 = sl;\n"
|
||
"type box = struct { s: sl2, n: int };\n"
|
||
"export fn main() i32 = {\n"
|
||
" let a: [3]int = [700: int, 800: int, 900: int];\n"
|
||
" let b: box;\n"
|
||
" b.n = 5;\n"
|
||
" b.s = a[0:3];\n"
|
||
" if (b.n != 5) { return 9; };\n"
|
||
" if (b.s[0] != 700) { return 1; };\n"
|
||
" if (b.s[2] != 900) { return 2; };\n"
|
||
" if (b.s.len != 3) { return 3; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
{ "slicefield_range_2lvl",
|
||
"package main;\n"
|
||
"type sl = []int;\n"
|
||
"type sl2 = sl;\n"
|
||
"type box = struct { s: sl2, n: int };\n"
|
||
"export fn main() i32 = {\n"
|
||
" let a: [3]int = [700: int, 800: int, 900: int];\n"
|
||
" let b: box;\n"
|
||
" b.s = a[0:3];\n"
|
||
" b.n = 5;\n"
|
||
" if (b.s.len != 3) { return 1; };\n"
|
||
" if (b.s[2] != 900) { return 2; };\n"
|
||
" for (let x .. b.s) {\n"
|
||
" if (x < 700) { return 3; };\n"
|
||
" };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
{ "strfield_store_2lvl",
|
||
"package main;\n"
|
||
"type s1t = str;\n"
|
||
"type s2t = s1t;\n"
|
||
"type box = struct { s: s2t, n: int };\n"
|
||
"export fn main() i32 = {\n"
|
||
" let b: box;\n"
|
||
" b.s = \"hello\";\n"
|
||
" b.n = 5;\n"
|
||
" if (b.s.len != 5) { return 1; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
{ "slicefield_structlit_2lvl",
|
||
"package main;\n"
|
||
"type sl = []int;\n"
|
||
"type sl2 = sl;\n"
|
||
"type box = struct { s: sl2, n: int };\n"
|
||
"export fn main() i32 = {\n"
|
||
" let a: [3]int = [700: int, 800: int, 900: int];\n"
|
||
" let b: box = box { s = a[0:3], n = 5: int };\n"
|
||
" if (b.n != 5) { return 1; };\n"
|
||
" if (b.s.len != 3) { return 2; };\n"
|
||
" if (b.s[2] != 900) { return 3; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
{ "slicefield_viaptr_2lvl",
|
||
"package main;\n"
|
||
"type sl = []int;\n"
|
||
"type sl2 = sl;\n"
|
||
"type box = struct { s: sl2, n: int };\n"
|
||
"export fn main() i32 = {\n"
|
||
" let a: [3]int = [700: int, 800: int, 900: int];\n"
|
||
" let b: box;\n"
|
||
" let p = &b;\n"
|
||
" p.s = a[0:3];\n"
|
||
" if (p.s.len != 3) { return 1; };\n"
|
||
" if (p.s[2] != 900) { return 2; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
{ "slicefield_chainstore_2lvl",
|
||
"package main;\n"
|
||
"type sl = []int;\n"
|
||
"type sl2 = sl;\n"
|
||
"type inner = struct { s: sl2 };\n"
|
||
"type outer = struct { i: inner };\n"
|
||
"export fn main() i32 = {\n"
|
||
" let a: [3]int = [700: int, 800: int, 900: int];\n"
|
||
" let v: outer;\n"
|
||
" v.i.s = a[0:3];\n"
|
||
" if (v.i.s.len != 3) { return 1; };\n"
|
||
" if (v.i.s[2] != 900) { return 2; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
{ "slicefield_ptrchain_2lvl",
|
||
"package main;\n"
|
||
"type sl = []int;\n"
|
||
"type sl2 = sl;\n"
|
||
"type inner = struct { s: sl2, n: int };\n"
|
||
"type outer = struct { pi: *inner };\n"
|
||
"export fn main() i32 = {\n"
|
||
" let a: [3]int = [700: int, 800: int, 900: int];\n"
|
||
" let i: inner;\n"
|
||
" i.n = 1;\n"
|
||
" let v: outer;\n"
|
||
" v.pi = &i;\n"
|
||
" v.pi.s = a[0:3];\n"
|
||
" if (i.s.len != 3) { return 1; };\n"
|
||
" if (i.s[2] != 900) { return 2; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
{ "slicefield_chainread_2lvl",
|
||
"package main;\n"
|
||
"type sl = []int;\n"
|
||
"type sl2 = sl;\n"
|
||
"type inner = struct { s: sl2 };\n"
|
||
"type outer = struct { i: inner };\n"
|
||
"fn noise(x: int) int = {\n"
|
||
" return x * 7 + 3;\n"
|
||
"};\n"
|
||
"export fn main() i32 = {\n"
|
||
" let a: [3]int = [700: int, 800: int, 900: int];\n"
|
||
" let v: outer;\n"
|
||
" v.i.s = a[0:3];\n"
|
||
" let k = noise(9);\n"
|
||
" if (k != 66) { return 9; };\n"
|
||
" let w = v.i.s;\n"
|
||
" if (w.len != 3) { return 1; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
{ "slicefield_ptrread_2lvl",
|
||
"package main;\n"
|
||
"type sl = []int;\n"
|
||
"type sl2 = sl;\n"
|
||
"type box = struct { s: sl2, n: int };\n"
|
||
"fn noise(x: int) int = {\n"
|
||
" return x * 7 + 3;\n"
|
||
"};\n"
|
||
"export fn main() i32 = {\n"
|
||
" let a: [3]int = [700: int, 800: int, 900: int];\n"
|
||
" let b: box;\n"
|
||
" b.s = a[0:3];\n"
|
||
" let p = &b;\n"
|
||
" let k = noise(9);\n"
|
||
" if (k != 66) { return 9; };\n"
|
||
" let w = p.s;\n"
|
||
" if (w.len != 3) { return 1; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
/* whole-field read into a local: cs runtime-correct post-chase
|
||
* (the clobbered-register r1b probe). The `let w = b.s` receive
|
||
* spine divergence noted at pristine 738d7f4 no longer
|
||
* reproduces at the F1-merged base, and ww's `w[i]` read (the
|
||
* task-#60 esz half) landed in F2a batch 1 — byte-id + 0/0
|
||
* verified, graduated K_RUN. */
|
||
{ "slicefield_wholeread_2lvl",
|
||
"package main;\n"
|
||
"type sl = []int;\n"
|
||
"type sl2 = sl;\n"
|
||
"type box = struct { s: sl2, n: int };\n"
|
||
"fn noise(x: int) int = {\n"
|
||
" return x * 7 + 3;\n"
|
||
"};\n"
|
||
"export fn main() i32 = {\n"
|
||
" let a: [3]int = [700: int, 800: int, 900: int];\n"
|
||
" let b: box;\n"
|
||
" b.s = a[0:3];\n"
|
||
" let k = noise(9);\n"
|
||
" if (k != 66) { return 9; };\n"
|
||
" let w = b.s;\n"
|
||
" if (w.len != 3) { return 1; };\n"
|
||
" if (w[2] != 900) { return 2; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL }, /* graduated: #60 (F2a batch 1) */
|
||
/* #73 tripwire pin: the UNPROBED single-peel field gates
|
||
* (indexed-elem store/read, ptr-chain read, heap fill, tuple-elem
|
||
* read, static emit) hard-error on a 2+-level alias over an
|
||
* aggregate base instead of emitting a word0 tail. ww accepts and
|
||
* runs these — cs-only loud until #73's chase. 1-level controls
|
||
* verified per gate (/tmp/revF1 t*c probes). */
|
||
{ "slicefield_idx_tripwire_73",
|
||
"package main;\n"
|
||
"type sl = []int;\n"
|
||
"type sl2 = sl;\n"
|
||
"type box = struct { s: sl2, n: int };\n"
|
||
"export fn main() i32 = {\n"
|
||
" let a: [3]int = [700: int, 800: int, 900: int];\n"
|
||
" let xs: [2]box;\n"
|
||
" xs[0].s = a[0:3];\n"
|
||
" if (xs[0].s.len != 3) { return 1; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_BUILDERR_CS,
|
||
"unswept single-peel gate (#73)" },
|
||
/* Values >255 break the esz=1 prefix-luck; the write-then-read
|
||
* pins the IMULQ stride on both the read and write spines. */
|
||
{ "idx_2level",
|
||
"package main;\n"
|
||
"type arr = [4]int;\n"
|
||
"type arr2 = arr;\n"
|
||
"export fn main() i32 = {\n"
|
||
" let a: arr2 = [1000: int, 2000: int, 3000: int, 4000: int];\n"
|
||
" if (a[2] != 3000) { return 1; };\n"
|
||
" a[1] = 9999;\n"
|
||
" if (a[1] != 9999) { return 2; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL }, /* graduated: #60 (F2a batch 1) */
|
||
{ "slice_2level",
|
||
"package main;\n"
|
||
"type sl = []int;\n"
|
||
"type sl2 = sl;\n"
|
||
"export fn main() i32 = {\n"
|
||
" let a: [4]int = [1000: int, 2000: int, 3000: int, 4000: int];\n"
|
||
" let s: sl2 = a[1:3];\n"
|
||
" if (s.len != 2) { return 1; };\n"
|
||
" if (s[0] != 2000) { return 2; };\n"
|
||
" s[1] = 7777;\n"
|
||
" if (a[2] != 7777) { return 3; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL }, /* graduated: #60 (F2a batch 1) */
|
||
{ "range_2level",
|
||
"package main;\n"
|
||
"type arr = [4]int;\n"
|
||
"type arr2 = arr;\n"
|
||
"export fn main() i32 = {\n"
|
||
" let a: arr2 = [1: int, 2: int, 3: int, 4: int];\n"
|
||
" let sum: int = 0;\n"
|
||
" for (let x .. a) {\n"
|
||
" sum = sum + x;\n"
|
||
" };\n"
|
||
" if (sum != 10) { return 1; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL }, /* graduated: #60 (F2a batch 1) */
|
||
{ "slice_of_alias_arg",
|
||
"package main;\n"
|
||
"type arr = [4]int;\n"
|
||
"type arr2 = arr;\n"
|
||
"fn sum(s: []int) int = {\n"
|
||
" let t: int = 0;\n"
|
||
" for (let x .. s) { t = t + x; };\n"
|
||
" return t;\n"
|
||
"};\n"
|
||
"export fn main() i32 = {\n"
|
||
" let a: arr2 = [1000: int, 2000: int, 3000: int, 4000: int];\n"
|
||
" let s = a[1:3];\n"
|
||
" if (s.len != 2) { return 1; };\n"
|
||
" if (s[1] != 3000) { return 2; };\n"
|
||
" if (sum(a[0:4]) != 10000) { return 3; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL }, /* graduated: #60 (F2a batch 1) */
|
||
/* ---- ken-v3 leg: the acceptance align above opens 2-level
|
||
* float/str/slice aliases to the cgen KIND classifiers
|
||
* (cg_isfloat/type_isf32/fld_isfloat/type_isstr/type_isslice),
|
||
* whose single peel classed them scalar/INT — the f64-alias param
|
||
* would read the wrong register class (cs exit 1 SILENT, ww
|
||
* correct). The classifiers chase IN THIS SAME COMMIT so the
|
||
* widening never ships a loud->silent flip (rule 7; ken root-
|
||
* verify /tmp/ken_f1, his v3 row below). */
|
||
{ "float_alias_param_kenv3",
|
||
"package main;\n"
|
||
"type fa = fb;\n"
|
||
"type fb = f64;\n"
|
||
"fn take(x: fa) f64 = {\n"
|
||
" return x * 2.0;\n"
|
||
"};\n"
|
||
"export fn main() i32 = {\n"
|
||
" if (take(1.5) != 3.0) { return 1; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
{ "float_alias_param",
|
||
"package main;\n"
|
||
"type f1t = f64;\n"
|
||
"type f2t = f1t;\n"
|
||
"fn half(x: f2t) f64 = {\n"
|
||
" return x / 2.0;\n"
|
||
"};\n"
|
||
"export fn main() i32 = {\n"
|
||
" let v: f2t = 5.0;\n"
|
||
" if (half(v) != 2.5) { return 1; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
{ "str_alias_2level",
|
||
"package main;\n"
|
||
"type s1t = str;\n"
|
||
"type s2t = s1t;\n"
|
||
"fn taillen(s: s2t) int = {\n"
|
||
" return (s.len: int);\n"
|
||
"};\n"
|
||
"export fn main() i32 = {\n"
|
||
" let v: s2t = \"hello\";\n"
|
||
" if (v.len != 5) { return 1; };\n"
|
||
" if (taillen(v) != 5) { return 2; };\n"
|
||
" let w: s2t = v;\n"
|
||
" if (w.len != 5) { return 3; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
/* slice leg: cs classify fixed; the ww half of the indexed read
|
||
* (task-#60 esz family) landed in F2a batch 1. Values >255
|
||
* break the esz=1 prefix-luck. */
|
||
{ "slice_alias_param",
|
||
"package main;\n"
|
||
"type b1 = []int;\n"
|
||
"type b2 = b1;\n"
|
||
"fn first(s: b2) int = {\n"
|
||
" return s[0];\n"
|
||
"};\n"
|
||
"export fn main() i32 = {\n"
|
||
" let a: [3]int = [1000: int, 2000: int, 3000: int];\n"
|
||
" let s: b2 = a[0:3];\n"
|
||
" if (first(s) != 1000) { return 1; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL }, /* graduated: #60 (F2a batch 1) */
|
||
/* ---- task #61: cstage alias-NAMED struct PARAM classify.
|
||
* The single peel classified a 2-level-alias param SCALAR: caller
|
||
* pushed and callee spilled ONE eightbyte, fields read saved-BP/
|
||
* return-address garbage (F0 m5_arg/m8b_arg1lit, cs exit 1 SILENT,
|
||
* ww correct). Fix = struct_arg_size/aggarg_size/struct_float_
|
||
* class + the prologue classify chase. Values are distinct and the
|
||
* LAST field is always checked (multi-eightbyte exit-checked). */
|
||
{ "arg_2level_fwdref",
|
||
"package main;\n"
|
||
"type ali = base;\n"
|
||
"type base = struct { a: size, b: size, c: size };\n"
|
||
"fn take(s: ali) size = {\n"
|
||
" return s.a + s.b + s.c;\n"
|
||
"};\n"
|
||
"export fn main() i32 = {\n"
|
||
" let x: ali;\n"
|
||
" x.a = 4; x.b = 9; x.c = 13;\n"
|
||
" if (take(x) != 26) { return 1; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
{ "arg_2level_litinit",
|
||
"package main;\n"
|
||
"type st = struct { a: size, b: size, c: size };\n"
|
||
"type row = st;\n"
|
||
"fn take(s: row) size = {\n"
|
||
" return s.a + s.b + s.c;\n"
|
||
"};\n"
|
||
"export fn main() i32 = {\n"
|
||
" let x: st = st { a = 4: size, b = 9: size, c = 13: size };\n"
|
||
" if (take(x) != 26) { return 1; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
/* 40B struct: 5 GP eightbytes through the aggarg (>16B) leg. */
|
||
{ "arg_2level_5word",
|
||
"package main;\n"
|
||
"type big = struct { a: size, b: size, c: size, d: size, e: size };\n"
|
||
"type big2 = big;\n"
|
||
"fn take(s: big2) size = {\n"
|
||
" return s.a + s.e;\n"
|
||
"};\n"
|
||
"export fn main() i32 = {\n"
|
||
" let v: big2;\n"
|
||
" v.a = 1000; v.b = 2; v.c = 3; v.d = 4; v.e = 5000;\n"
|
||
" if (take(v) != 6000) { return 1; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
/* f64-bearing 16B struct: the struct_float_class SSE leg. */
|
||
{ "arg_2level_floatclass",
|
||
"package main;\n"
|
||
"type fs = struct { x: f64, n: size };\n"
|
||
"type fs2 = fs;\n"
|
||
"fn take(s: fs2) size = {\n"
|
||
" if (s.x != 2.5) { return 99; };\n"
|
||
" return s.n;\n"
|
||
"};\n"
|
||
"export fn main() i32 = {\n"
|
||
" let v: fs2;\n"
|
||
" v.x = 2.5; v.n = 7;\n"
|
||
" if (take(v) != 7) { return 1; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
/* control: base-named param spelling stays green + byte-id. */
|
||
{ "arg_base_control",
|
||
"package main;\n"
|
||
"type base = struct { a: size, b: size, c: size };\n"
|
||
"fn take(s: base) size = {\n"
|
||
" return s.a + s.b + s.c;\n"
|
||
"};\n"
|
||
"export fn main() i32 = {\n"
|
||
" let x: base;\n"
|
||
" x.a = 4; x.b = 9; x.c = 13;\n"
|
||
" if (take(x) != 26) { return 1; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
/* ---- task #62 Layer-2: alias-NAMED struct as a UNION MEMBER.
|
||
* The widen store/push source classify fell past the struct arm
|
||
* to the scalar arm — word0-only payload (the banked rows
|
||
* /tmp/impl62r_layer2_rows.md; both-wrong-identical at normal
|
||
* decl order = gate-blind byte-id). cs half c138605
|
||
* (cg_widen_tagged_store/push su chase); ww half F2a batch-2 c2
|
||
* (rhsstructpayload -> structlookupchain) — K_RUN, byte-id.
|
||
* Values distinct per word; the LAST payload word is always
|
||
* checked. The RETURN-position leg stays both-stage divergent —
|
||
* cs cgreturn residual, task #89 (ww runtime-correct since c2;
|
||
* not pinned here until the cs half lands). */
|
||
{ "union_store_norm", /* banked row L2-1 (= F0 m5b_match1) */
|
||
"package main;\n"
|
||
"type base = struct { a: size, b: size };\n"
|
||
"type ali = base;\n"
|
||
"export fn main() i32 = {\n"
|
||
" let x: ali;\n"
|
||
" x.a = 4; x.b = 9;\n"
|
||
" let v: (void | ali) = x;\n"
|
||
" match (v) {\n"
|
||
" case let s: ali => {\n"
|
||
" if (s.a != 4) { return 1; };\n"
|
||
" if (s.b != 9) { return 2; };\n"
|
||
" };\n"
|
||
" case void => { return 3; };\n"
|
||
" };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
{ "union_store_fwd", /* banked row L2-2 (= F0 m5_match) */
|
||
"package main;\n"
|
||
"type ali = base;\n"
|
||
"type base = struct { a: size, b: size };\n"
|
||
"export fn main() i32 = {\n"
|
||
" let x: ali;\n"
|
||
" x.a = 4; x.b = 9;\n"
|
||
" let v: (void | ali) = x;\n"
|
||
" match (v) {\n"
|
||
" case let s: ali => {\n"
|
||
" if (s.a != 4) { return 1; };\n"
|
||
" if (s.b != 9) { return 2; };\n"
|
||
" };\n"
|
||
" case void => { return 3; };\n"
|
||
" };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
{ "union_store_3word", /* banked row L2-4: pins the width LOOP */
|
||
"package main;\n"
|
||
"type base = struct { a: size, b: size, c: size };\n"
|
||
"type ali = base;\n"
|
||
"export fn main() i32 = {\n"
|
||
" let x: ali;\n"
|
||
" x.a = 4; x.b = 9; x.c = 3;\n"
|
||
" let v: (void | ali) = x;\n"
|
||
" match (v) {\n"
|
||
" case let s: ali => {\n"
|
||
" if (s.a != 4) { return 1; };\n"
|
||
" if (s.c != 3) { return 2; };\n"
|
||
" };\n"
|
||
" case void => { return 3; };\n"
|
||
" };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
{ "union_push_arg", /* the cg_widen_tagged_push twin (F1 find) */
|
||
"package main;\n"
|
||
"type base = struct { a: size, b: size };\n"
|
||
"type ali = base;\n"
|
||
"fn peek(v: (void | ali)) size = {\n"
|
||
" match (v) {\n"
|
||
" case let s: ali => { return s.b; };\n"
|
||
" case void => { return 0; };\n"
|
||
" };\n"
|
||
"};\n"
|
||
"export fn main() i32 = {\n"
|
||
" let x: ali;\n"
|
||
" x.a = 4; x.b = 9;\n"
|
||
" if (peek(x) != 9) { return 1; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
/* banked row L2-5: the m5b_match0 gold invariant — base spelling
|
||
* indistinguishable (ken oracle PART 1.7). */
|
||
{ "union_store_base_ctl",
|
||
"package main;\n"
|
||
"type base = struct { a: size, b: size, c: size };\n"
|
||
"export fn main() i32 = {\n"
|
||
" let x: base;\n"
|
||
" x.a = 4; x.b = 9; x.c = 3;\n"
|
||
" let v: (void | base) = x;\n"
|
||
" match (v) {\n"
|
||
" case let s: base => {\n"
|
||
" if (s.a != 4) { return 1; };\n"
|
||
" if (s.c != 3) { return 2; };\n"
|
||
" };\n"
|
||
" case void => { return 3; };\n"
|
||
" };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
/* ---- F2a batch-3 c3 (task #92, reviewer-B2 find): the same
|
||
* rhsstructpayload widen, sourced from a struct LITERAL instead
|
||
* of a local ident — the N_STRUCTLIT arm still did bare
|
||
* structlookup, so `ali{...}` into a union fell to the scalar
|
||
* widen arm (cs 0 / ww EXIT 1, byte-id NO, pre-existing on
|
||
* master at 486f7f8). Graduated by routing the arm through
|
||
* structlookupchain (entry gate widened to the literal's N_IDENT
|
||
* type-ref leaf — consumer census in the commit body). Values
|
||
* distinct per word, LAST word checked. The alias struct-LIT
|
||
* LET-INIT zero-fill (task #63) does NOT green at this site —
|
||
* probed post-c3, documented there, deliberately no row here. */
|
||
{ "union_slit_base_ctl",
|
||
"package main;\n"
|
||
"type base = struct { a: size, b: size };\n"
|
||
"export fn main() i32 = {\n"
|
||
" let v: (void | base) = base{a=4000, b=9000};\n"
|
||
" match (v) {\n"
|
||
" case let s: base => {\n"
|
||
" if (s.a != 4000) { return 1; };\n"
|
||
" if (s.b != 9000) { return 2; };\n"
|
||
" };\n"
|
||
" case void => { return 3; };\n"
|
||
" };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
{ "union_slit_alias",
|
||
"package main;\n"
|
||
"type base = struct { a: size, b: size };\n"
|
||
"type ali = base;\n"
|
||
"export fn main() i32 = {\n"
|
||
" let v: (void | ali) = ali{a=4000, b=9000};\n"
|
||
" match (v) {\n"
|
||
" case let s: ali => {\n"
|
||
" if (s.a != 4000) { return 1; };\n"
|
||
" if (s.b != 9000) { return 2; };\n"
|
||
" };\n"
|
||
" case void => { return 3; };\n"
|
||
" };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
/* 2-level: the chain walk (structlookupchain's alias loop). */
|
||
{ "union_slit_alias2",
|
||
"package main;\n"
|
||
"type base = struct { a: size, b: size };\n"
|
||
"type ali = base;\n"
|
||
"type ali2 = ali;\n"
|
||
"export fn main() i32 = {\n"
|
||
" let v: (void | ali2) = ali2{a=4000, b=9000};\n"
|
||
" match (v) {\n"
|
||
" case let s: ali2 => {\n"
|
||
" if (s.a != 4000) { return 1; };\n"
|
||
" if (s.b != 9000) { return 2; };\n"
|
||
" };\n"
|
||
" case void => { return 3; };\n"
|
||
" };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
{ "union_slit_order",
|
||
"package main;\n"
|
||
"export fn main() i32 = {\n"
|
||
" let v: (void | ali) = ali{a=4000, b=9000};\n"
|
||
" match (v) {\n"
|
||
" case let s: ali => {\n"
|
||
" if (s.a != 4000) { return 1; };\n"
|
||
" if (s.b != 9000) { return 2; };\n"
|
||
" };\n"
|
||
" case void => { return 3; };\n"
|
||
" };\n"
|
||
" return 0;\n"
|
||
"};\n"
|
||
"type ali = base;\n"
|
||
"type base = struct { a: size, b: size };\n", 0, K_RUN, NULL },
|
||
/* ---- F2a batch-2 c3/B1: exprprimresolved's N_DOT base walk was
|
||
* a hand-rolled 2-peel — a 3-level alias base (or ptr-to-2-level)
|
||
* left the cast-source width unknowable on wwstage only, so the
|
||
* #33 identity clamp stayed emitted where cstage (castsrcprim,
|
||
* F1-chased) skipped it: runtime-correct both, byte-id NO.
|
||
* Graduated by the tichase walk; 1/2-level controls held all
|
||
* along (the 2-peel covered them by accident). */
|
||
{ "castprim_3lvl_base",
|
||
"package main;\n"
|
||
"type s1 = struct { f: u32 };\n"
|
||
"type s2 = s1;\n"
|
||
"type s3 = s2;\n"
|
||
"export fn main() i32 = {\n"
|
||
" let x: s3;\n"
|
||
" x.f = 70000;\n"
|
||
" let y: u64 = (x.f: u32): u64;\n"
|
||
" if (y != 70000) { return 1; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
{ "castprim_ptr2lvl_base",
|
||
"package main;\n"
|
||
"type s1 = struct { f: u32 };\n"
|
||
"type s2 = s1;\n"
|
||
"export fn main() i32 = {\n"
|
||
" let x: s2;\n"
|
||
" x.f = 70000;\n"
|
||
" let p: *s2 = &x;\n"
|
||
" let y: u64 = (p.f: u32): u64;\n"
|
||
" if (y != 70000) { return 1; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
/* 2-level control (was already byte-id pre-c3; pins the accident
|
||
* out of existence). */
|
||
{ "castprim_2lvl_base_ctl",
|
||
"package main;\n"
|
||
"type s1 = struct { f: u32 };\n"
|
||
"type s2 = s1;\n"
|
||
"export fn main() i32 = {\n"
|
||
" let x: s2;\n"
|
||
" x.f = 70000;\n"
|
||
" let y: u64 = (x.f: u32): u64;\n"
|
||
" if (y != 70000) { return 1; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
/* ---- F2a batch-2 c4 (rob FINAL RULING (i)): tyassignableuntyped
|
||
* full-chase — STRUCTURAL alignment to cs type.c:369-385 / harec
|
||
* type_is_assignable; ZERO acceptance graduations in this commit
|
||
* (graduations ride task #90). Holds + controls pin the chase as
|
||
* behavior-neutral on every reachable shape; the tagged-dst rows
|
||
* are the #33 pins (drill semantics unchanged). */
|
||
{ "untyped_hold33_pin", /* (void|T) untyped-int init — #33 fixed
|
||
* behavior, tagged-dst drill HOLD */
|
||
"package main;\n"
|
||
"export fn main() i32 = {\n"
|
||
" let mn: (void | size) = 5;\n"
|
||
" if (!(mn is size)) { return 1; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
{ "untyped_tagdst_2lvl_hold", /* 2-level alias TAGGED dst holds */
|
||
"package main;\n"
|
||
"type r1 = (void | size);\n"
|
||
"type r2 = r1;\n"
|
||
"export fn main() i32 = {\n"
|
||
" let v: r2 = 5;\n"
|
||
" if (!(v is size)) { return 1; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
{ "untyped_str2lvl_ctl", /* masked twin: ww stamps the str
|
||
* literal CONCRETE (#14 cluster), the
|
||
* shape fallback rescues the tag — 0/0
|
||
* all along; documents the rescue */
|
||
"package main;\n"
|
||
"type sa1 = str;\n"
|
||
"type sa2 = sa1;\n"
|
||
"export fn main() i32 = {\n"
|
||
" let v: (void | sa2) = \"hi\";\n"
|
||
" if (!(v is sa2)) { return 1; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
{ "untyped_int2lvl_ctl", /* typeisnum NAMED-recursion control */
|
||
"package main;\n"
|
||
"type ia1 = i64;\n"
|
||
"type ia2 = ia1;\n"
|
||
"export fn main() i32 = {\n"
|
||
" let v: (void | ia2) = 7;\n"
|
||
" if (!(v is ia2)) { return 1; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
{ "untyped_bool1lvl_ctl", /* 1 level: ww passes via the
|
||
* fallback's one peel — 0/0 observed */
|
||
"package main;\n"
|
||
"type ba1 = bool;\n"
|
||
"export fn main() i32 = {\n"
|
||
" let v: (void | ba1) = true;\n"
|
||
" if (!(v is ba1)) { return 1; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
/* BOUND row (task #90): ww stamps N_TRUE CONCRETE bool
|
||
* (check.ww:2440) vs cs untyped_bool (check.c:1234), so the bool
|
||
* literal never reaches the c4-chased untyped funnel on ww — it
|
||
* dies at flatvariantidxt pass-2's one-level pu.under guard
|
||
* (cgenutil.ww:2868, the #17 site): SILENT tag 0, ww runs exit 1
|
||
* where cs runs 0. Flip to K_RUN when #90 clears BOTH layers
|
||
* (stamp + fallback peel). */
|
||
{ "untyped_bool2lvl_bound90",
|
||
"package main;\n"
|
||
"type bb1 = bool;\n"
|
||
"type bb2 = bb1;\n"
|
||
"export fn main() i32 = {\n"
|
||
" let v: (void | bb2) = true;\n"
|
||
" if (!(v is bb2)) { return 1; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN_CS, NULL }, /* ww: task #90 */
|
||
/* BOUND expected-state row (#199α + #90): untyped literal into a
|
||
* NESTED-tagged alias-wrapped variant. cs CHECKER loud-rejects —
|
||
* the #199α ww-stricter no-transitive-drill rule (type.c:316-324);
|
||
* ww's node-keyed checker ACCEPTS and the binary runs exit 0
|
||
* (observed post-c4; the harness has no cs-reject+ww-runs mode,
|
||
* so the ww half is pinned via #90's metadata, not here). The c4
|
||
* pu-chase aligned the CGEN drill structure to cs; the acceptance
|
||
* gate is check.ww — batch-4 aligns ww down, then this row flips
|
||
* to K_BUILDERR (loud BOTH). */
|
||
{ "untyped_nestvar_bound",
|
||
"package main;\n"
|
||
"type inner = (i64 | str);\n"
|
||
"type inner2 = inner;\n"
|
||
"export fn main() i32 = {\n"
|
||
" let v: (void | inner2) = 7;\n"
|
||
" if (v is void) { return 1; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_BUILDERR_CS, "not assignable" },
|
||
/* ---- task #71 (rob probe-ruled F1 enrollment): nested fields
|
||
* whose TYPES are aliases. The chained-dot store/read/addr-of
|
||
* walks single-peeled each hop, aborted on the alias, and fell
|
||
* to the generic PUSHQ/LEAQ/ADDQ/POPQ address spine — runtime-
|
||
* correct but byte-id NO vs wwstage's folded direct offsets.
|
||
* Chasing the walks converges cs onto the direct arm = ww's asm.
|
||
* Distinct values; the LAST field of the SECOND member checked. */
|
||
{ "nested_alias_field_norm",
|
||
"package main;\n"
|
||
"type fa = inner;\n"
|
||
"type inner = struct { a: size, b: size };\n"
|
||
"type outer = struct { x: fa, y: fa };\n"
|
||
"export fn main() i32 = {\n"
|
||
" let v: outer;\n"
|
||
" v.x.a = 4; v.x.b = 9;\n"
|
||
" v.y.a = 7; v.y.b = 3;\n"
|
||
" if (v.x.b != 9) { return 1; };\n"
|
||
" if (v.y.b != 3) { return 2; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
{ "nested_alias_field_fwd",
|
||
"package main;\n"
|
||
"type outer = struct { x: fa, y: fa };\n"
|
||
"type fa = inner;\n"
|
||
"type inner = struct { a: size, b: size };\n"
|
||
"export fn main() i32 = {\n"
|
||
" let v: outer;\n"
|
||
" v.x.a = 4; v.x.b = 9;\n"
|
||
" v.y.a = 7; v.y.b = 3;\n"
|
||
" if (v.x.b != 9) { return 1; };\n"
|
||
" if (v.y.b != 3) { return 2; };\n"
|
||
" let pa = &v.y.b;\n"
|
||
" *pa = 11;\n"
|
||
" if (v.y.b != 11) { return 3; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_RUN, NULL },
|
||
/* banked row L2-3 (`v as ali` readback) trips task #54's as-binding
|
||
* aggregate-init bound — LOUD both stages today; fold the row into
|
||
* #54's pin set on its fold (do not drop). Pinned here as the
|
||
* loud-both bound so a silent regression can't hide. */
|
||
{ "union_as_bound_54",
|
||
"package main;\n"
|
||
"type base = struct { a: size, b: size };\n"
|
||
"type ali = base;\n"
|
||
"export fn main() i32 = {\n"
|
||
" let x: ali;\n"
|
||
" x.a = 4; x.b = 9;\n"
|
||
" let v: (void | ali) = x;\n"
|
||
" if (!(v is ali)) { return 1; };\n"
|
||
" let w = v as ali;\n"
|
||
" if (w.b != 9) { return 2; };\n"
|
||
" return 0;\n"
|
||
"};\n", 0, K_BUILDERR,
|
||
"aggregate init from unhandled rhs shape" },
|
||
};
|
||
|
||
static int
|
||
run_driver(const char *driver, const struct row *r, int i)
|
||
{
|
||
char src[96], tmpdir[96], errf[96], cmd[1024];
|
||
snprintf(src, sizeof src, "/tmp/aac_%d_%d.ww", getpid(), i);
|
||
snprintf(tmpdir, sizeof tmpdir, "/tmp/aac_%d_d_%d", getpid(), i);
|
||
snprintf(errf, sizeof errf, "/tmp/aac_%d_e_%d", getpid(), i);
|
||
|
||
FILE *f = fopen(src, "wb");
|
||
if (!f) return -1;
|
||
fputs(r->src, f);
|
||
fclose(f);
|
||
|
||
mkdir(tmpdir, 0755);
|
||
snprintf(cmd, sizeof cmd,
|
||
"cd %s && timeout 20 %s build %s >/dev/null 2>%s",
|
||
tmpdir, driver, src, errf);
|
||
int brc = runwait(cmd);
|
||
if (r->kind == K_BUILDERR || r->kind == K_BUILDERR_CS) {
|
||
int ok = (brc != 0)
|
||
&& (r->experr == NULL || errlog_has(errf, r->experr));
|
||
if (!ok)
|
||
fprintf(stderr, "row[%s]: %s expected loud builderr "
|
||
"\"%s\" (brc=%d)\n", r->label, driver,
|
||
r->experr ? r->experr : "", brc);
|
||
unlink(src); unlink(errf); rmdir(tmpdir);
|
||
return ok ? 0 : 1;
|
||
}
|
||
if (brc != 0) {
|
||
fprintf(stderr, "row[%s]: build via %s failed\n",
|
||
r->label, driver);
|
||
unlink(src); unlink(errf); rmdir(tmpdir);
|
||
return -1;
|
||
}
|
||
|
||
const char *base = strrchr(src, '/');
|
||
base = base ? base + 1 : src;
|
||
char outbin[256];
|
||
snprintf(outbin, sizeof outbin, "%s/%s", tmpdir, base);
|
||
char *dot = strrchr(outbin, '.');
|
||
if (dot && strcmp(dot, ".ww") == 0) *dot = '\0';
|
||
int got = runwait(outbin);
|
||
|
||
unlink(src); unlink(outbin); unlink(errf); rmdir(tmpdir);
|
||
if (got != r->want) {
|
||
fprintf(stderr, "row[%s]: %s exit %d, want %d\n",
|
||
r->label, driver, got, r->want);
|
||
return 1;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
static int
|
||
asm_byte_identical(const char *bin, const struct row *r, int i)
|
||
{
|
||
char src[96], cs[96], ws[96], cmd[1024];
|
||
snprintf(src, sizeof src, "/tmp/aac_asm_%d_%d.ww", getpid(), i);
|
||
snprintf(cs, sizeof cs, "/tmp/aac_asm_%d_%d_c.s", getpid(), i);
|
||
snprintf(ws, sizeof ws, "/tmp/aac_asm_%d_%d_w.s", getpid(), i);
|
||
|
||
FILE *f = fopen(src, "wb");
|
||
if (!f) return -1;
|
||
fputs(r->src, f);
|
||
fclose(f);
|
||
|
||
snprintf(cmd, sizeof cmd, "%s/w6c -o %s %s 2>/dev/null", bin, cs, src);
|
||
if (runwait(cmd) != 0) {
|
||
fprintf(stderr, "row[%s]: w6c errored\n", r->label);
|
||
unlink(src);
|
||
return -1;
|
||
}
|
||
snprintf(cmd, sizeof cmd, "%s/w6c_ww -o %s %s 2>/dev/null",
|
||
bin, ws, src);
|
||
if (runwait(cmd) != 0) {
|
||
fprintf(stderr, "row[%s]: w6c_ww errored\n", r->label);
|
||
unlink(src); unlink(cs);
|
||
return -1;
|
||
}
|
||
int rc = slurp_eq(cs, ws);
|
||
if (rc != 0)
|
||
fprintf(stderr, "row[%s]: cstage vs wwstage asm differs\n",
|
||
r->label);
|
||
unlink(src); unlink(cs); unlink(ws);
|
||
return rc;
|
||
}
|
||
|
||
int
|
||
main(void)
|
||
{
|
||
const char *bin = getenv("BIN");
|
||
if (!bin) bin = "out/bin";
|
||
char absbin[2080];
|
||
if (bin[0] != '/') {
|
||
char cwd[1024];
|
||
if (getcwd(cwd, sizeof cwd) == NULL) return 1;
|
||
snprintf(absbin, sizeof absbin, "%s/%s", cwd, bin);
|
||
bin = absbin;
|
||
}
|
||
|
||
char cdrv[2120], wdrv[2120];
|
||
snprintf(cdrv, sizeof cdrv, "%s/ww", bin);
|
||
snprintf(wdrv, sizeof wdrv, "%s/ww_ww", bin);
|
||
|
||
int n = (int)(sizeof rows / sizeof rows[0]);
|
||
int total = 0, fail = 0;
|
||
|
||
for (int i = 0; i < n; i++) {
|
||
total++;
|
||
if (run_driver(cdrv, &rows[i], i) != 0) fail++;
|
||
}
|
||
if (access(wdrv, X_OK) == 0) {
|
||
for (int i = 0; i < n; i++) {
|
||
if (rows[i].kind == K_RUN_CS
|
||
|| rows[i].kind == K_BUILDERR_CS)
|
||
continue;
|
||
total++;
|
||
if (run_driver(wdrv, &rows[i], i) != 0) fail++;
|
||
}
|
||
for (int i = 0; i < n; i++) {
|
||
if (rows[i].kind != K_RUN)
|
||
continue;
|
||
total++;
|
||
if (asm_byte_identical(bin, &rows[i], i) != 0) fail++;
|
||
}
|
||
}
|
||
|
||
if (fail) {
|
||
fprintf(stderr, "alias_accept: %d/%d checks failed\n",
|
||
fail, total);
|
||
return 1;
|
||
}
|
||
printf("alias_accept: %d/%d ok\n", total, total);
|
||
return 0;
|
||
}
|