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

View File

@@ -370,14 +370,10 @@ TESTS = $(BIN)/test_smoke $(BIN)/test_lex $(BIN)/test_parse $(BIN)/test_check \
$(BIN)/test_sret_narrow_field \
$(BIN)/test_match_slice_variant \
$(BIN)/test_match_slice_variant_run \
$(BIN)/test_alias_decl_order_size_run \
$(BIN)/test_alias_structlit_init_run \
$(BIN)/test_array_zeroinit_run \
$(BIN)/test_alias_accept_run \
$(BIN)/test_alias_idx_family_run \
$(BIN)/test_idx_tagged_field_run \
$(BIN)/test_tagged_widen_arg_run \
$(BIN)/test_alias_global_decl_run \
$(BIN)/test_alias_cgen_b5_run \
$(BIN)/test_alias_cgen_b6_run \
$(BIN)/test_alias_emit_b7_run \
@@ -2188,18 +2184,6 @@ $(BIN)/test_str_forrange_loopvar_run: test/wcc/940_str_forrange_loopvar_run.c \
$(LIB)/libwwrt.a | $(BIN)
$(CC) $(CFLAGS) -o $@ $<
$(BIN)/test_alias_decl_order_size_run: test/wcc/944_alias_decl_order_size_run.c \
$(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \
$(BIN)/ww_ww $(BIN)/w6c_ww $(BIN)/w6a_ww $(BIN)/w6l_ww \
$(LIB)/libwwrt.a | $(BIN)
$(CC) $(CFLAGS) -o $@ $<
$(BIN)/test_alias_structlit_init_run: test/wcc/944_alias_structlit_init_run.c \
$(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \
$(BIN)/ww_ww $(BIN)/w6c_ww $(BIN)/w6a_ww $(BIN)/w6l_ww \
$(LIB)/libwwrt.a | $(BIN)
$(CC) $(CFLAGS) -o $@ $<
$(BIN)/test_array_zeroinit_run: test/wcc/944_array_zeroinit_run.c \
$(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \
$(BIN)/ww_ww $(BIN)/w6c_ww $(BIN)/w6a_ww $(BIN)/w6l_ww \
@@ -2212,12 +2196,6 @@ $(BIN)/test_alias_accept_run: test/wcc/944_alias_accept_run.c \
$(LIB)/libwwrt.a | $(BIN)
$(CC) $(CFLAGS) -o $@ $<
$(BIN)/test_alias_idx_family_run: test/wcc/944_alias_idx_family_run.c \
$(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \
$(BIN)/ww_ww $(BIN)/w6c_ww $(BIN)/w6a_ww $(BIN)/w6l_ww \
$(LIB)/libwwrt.a | $(BIN)
$(CC) $(CFLAGS) -o $@ $<
$(BIN)/test_idx_tagged_field_run: test/wcc/944_idx_tagged_field_run.c \
$(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \
$(BIN)/ww_ww $(BIN)/w6c_ww $(BIN)/w6a_ww $(BIN)/w6l_ww \
@@ -2230,12 +2208,6 @@ $(BIN)/test_tagged_widen_arg_run: test/wcc/944_tagged_widen_arg_run.c \
$(LIB)/libwwrt.a | $(BIN)
$(CC) $(CFLAGS) -o $@ $<
$(BIN)/test_alias_global_decl_run: test/wcc/944_alias_global_decl_run.c \
$(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \
$(BIN)/ww_ww $(BIN)/w6c_ww $(BIN)/w6a_ww $(BIN)/w6l_ww \
$(LIB)/libwwrt.a | $(BIN)
$(CC) $(CFLAGS) -o $@ $<
$(BIN)/test_alias_cgen_b5_run: test/wcc/944_alias_cgen_b5_run.c \
$(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \
$(BIN)/ww_ww $(BIN)/w6c_ww $(BIN)/w6a_ww $(BIN)/w6l_ww \
@@ -3190,7 +3162,7 @@ test-lang: all
LANGBYTEID_DIR = $(OUT)/langbyteid
LANGBYTEID_FILES = $(filter-out %_runonly_test.ww,$(wildcard test/lang/*_test.ww))
LANGBYTEID_VERB = test -c
LANGBYTEID_EXPECTED_MIN = 74
LANGBYTEID_EXPECTED_MIN = 82
$(if $(LANGBYTEID_FILES),,$(error test-lang-byteid: empty corpus))
test-lang-byteid: all
@set -e; \

View File

@@ -0,0 +1,20 @@
// alias_accept_runonly_test — the cs≠ww .s carve-out split from
// alias_accept_test (#5-C3, #7f/#254 value-only runonly home). A bare
// (anonymous-let) struct widened into a 2-level alias variant: the asm
// diverges on 3 pre-existing cglet zero-fill lines (cs XORQ+2 stores, ww none
// — task #81 class), runtime-correct on BOTH stages, ORTHOGONAL to the variant
// tag under test. The acceptance + correct-tag behavior stays pinned on the
// cstage run (T1); the file is *_runonly so the test-lang-byteid (T2) corpus
// excludes it. Flip back into alias_accept_test when the #81 zero-fill
// divergence closes. Migrated from test/wcc/944_alias_accept_run.c.
package alias_accept_runonly_test;
type sa = struct { a: i64, };
type sb = sa;
@test fn v2_struct2() void = {
let s: struct { a: i64, } = sa{a=7};
let v: (void | sb) = s;
assert(v is sb);
};

View File

@@ -0,0 +1,812 @@
// alias_accept_test — #5 alias arc F1: the transitive TY_NAMED chase. cstage
// single-peeled the alias at promotion/cond/assign/index/field/arg/union/cast
// consumers, so a 2+-level alias (or one alias over a named aggregate) left the
// type TY_NAMED and fell to a scalar/word0-only/pointer tail — runtime-wrong or
// byte-diverging vs wwstage (which already chased). Each @test pins one consumer
// shape, asserting the value the C row checked so a re-narrowing can't hide.
// Migrated from test/wcc/944_alias_accept_run.c (#5-C3).
package alias_accept_test;
// binop_alias_base
type bab_myint = int;
// binop_2level
type b2_myint = int;
type b2_myint2 = b2_myint;
type b2_myu = u32;
// ret_through_2level
type rt_myint = int;
type rt_myint2 = rt_myint;
// assign_alias_alias
type aa_k1 = int;
type aa_k2 = int;
// cond_* family (alias-of-bool)
type cond_myb = bool;
// dot_2level (alias declared before base — forward ref under test)
type dot_a3 = dot_b3;
type dot_b3 = dot_c3;
type dot_c3 = struct { x: size, y: size, z: size };
// deref_alias_ptr
type dp_pi = *int;
type dp_pi2 = dp_pi;
// slicefield_store_2lvl
type sfs_sl = []int;
type sfs_sl2 = sfs_sl;
type sfs_box = struct { s: sfs_sl2, n: int };
// slicefield_range_2lvl
type sfr_sl = []int;
type sfr_sl2 = sfr_sl;
type sfr_box = struct { s: sfr_sl2, n: int };
// strfield_store_2lvl
type sfst_s1t = str;
type sfst_s2t = sfst_s1t;
type sfst_box = struct { s: sfst_s2t, n: int };
// slicefield_structlit_2lvl
type sfsl_sl = []int;
type sfsl_sl2 = sfsl_sl;
type sfsl_box = struct { s: sfsl_sl2, n: int };
// slicefield_viaptr_2lvl
type sfv_sl = []int;
type sfv_sl2 = sfv_sl;
type sfv_box = struct { s: sfv_sl2, n: int };
// slicefield_chainstore_2lvl
type sfc_sl = []int;
type sfc_sl2 = sfc_sl;
type sfc_inner = struct { s: sfc_sl2 };
type sfc_outer = struct { i: sfc_inner };
// slicefield_ptrchain_2lvl
type sfp_sl = []int;
type sfp_sl2 = sfp_sl;
type sfp_inner = struct { s: sfp_sl2, n: int };
type sfp_outer = struct { pi: *sfp_inner };
// slicefield_chainread_2lvl
type sfcr_sl = []int;
type sfcr_sl2 = sfcr_sl;
type sfcr_inner = struct { s: sfcr_sl2 };
type sfcr_outer = struct { i: sfcr_inner };
// slicefield_ptrread_2lvl
type sfpr_sl = []int;
type sfpr_sl2 = sfpr_sl;
type sfpr_box = struct { s: sfpr_sl2, n: int };
// slicefield_wholeread_2lvl
type sfw_sl = []int;
type sfw_sl2 = sfw_sl;
type sfw_box = struct { s: sfw_sl2, n: int };
// slicefield_idx_tripwire_73
type sfi_sl = []int;
type sfi_sl2 = sfi_sl;
type sfi_box = struct { s: sfi_sl2, n: int };
// idx_2level
type idx_arr = [4]int;
type idx_arr2 = idx_arr;
// slice_2level
type sl2_sl = []int;
type sl2_sl2 = sl2_sl;
// range_2level
type rng_arr = [4]int;
type rng_arr2 = rng_arr;
// slice_of_alias_arg
type soa_arr = [4]int;
type soa_arr2 = soa_arr;
// float_alias_param_kenv3 (alias before base — forward ref)
type fak_fa = fak_fb;
type fak_fb = f64;
// float_alias_param
type fap_f1t = f64;
type fap_f2t = fap_f1t;
// str_alias_2level
type sa2_s1t = str;
type sa2_s2t = sa2_s1t;
// slice_alias_param
type slp_b1 = []int;
type slp_b2 = slp_b1;
// arg_2level_fwdref (alias before base — forward ref)
type afr_ali = afr_base;
type afr_base = struct { a: size, b: size, c: size };
// arg_2level_litinit
type ali_st = struct { a: size, b: size, c: size };
type ali_row = ali_st;
// arg_2level_5word
type a5_big = struct { a: size, b: size, c: size, d: size, e: size };
type a5_big2 = a5_big;
// arg_2level_floatclass
type afc_fs = struct { x: f64, n: size };
type afc_fs2 = afc_fs;
// arg_base_control
type abc_base = struct { a: size, b: size, c: size };
// union_store_norm
type usn_base = struct { a: size, b: size };
type usn_ali = usn_base;
// union_store_fwd (alias before base — forward ref)
type usf_ali = usf_base;
type usf_base = struct { a: size, b: size };
// union_store_3word
type us3_base = struct { a: size, b: size, c: size };
type us3_ali = us3_base;
// union_push_arg
type upa_base = struct { a: size, b: size };
type upa_ali = upa_base;
// union_store_base_ctl
type usbc_base = struct { a: size, b: size, c: size };
// union_slit_base_ctl
type uslbc_base = struct { a: size, b: size };
// union_slit_alias
type usla_base = struct { a: size, b: size };
type usla_ali = usla_base;
// union_slit_alias2
type usl2_base = struct { a: size, b: size };
type usl2_ali = usl2_base;
type usl2_ali2 = usl2_ali;
// union_slit_order (alias before base — forward ref)
type uslo_ali = uslo_base;
type uslo_base = struct { a: size, b: size };
// castprim_3lvl_base
type cp3_s1 = struct { f: u32 };
type cp3_s2 = cp3_s1;
type cp3_s3 = cp3_s2;
// castprim_ptr2lvl_base
type cpp_s1 = struct { f: u32 };
type cpp_s2 = cpp_s1;
// castprim_2lvl_base_ctl
type cp2_s1 = struct { f: u32 };
type cp2_s2 = cp2_s1;
// untyped_tagdst_2lvl_hold
type utd_r1 = (void | size);
type utd_r2 = utd_r1;
// untyped_str2lvl_ctl
type usc_sa1 = str;
type usc_sa2 = usc_sa1;
// untyped_int2lvl_ctl
type uic_ia1 = i64;
type uic_ia2 = uic_ia1;
// untyped_bool1lvl_ctl
type ub1_ba1 = bool;
// untyped_bool2lvl_bound90
type ub2_bb1 = bool;
type ub2_bb2 = ub2_bb1;
// v2_ctrl
type v2c_pc = *i64;
// v2_alias2
type v2a_pa = *i64;
type v2a_pb = v2a_pa;
// sp_alias1
type sp1_inner = (i64 | str);
type sp1_outer = (...sp1_inner | void);
// sp_alias2
type sp2_inner = (i64 | str);
type sp2_inner2 = sp2_inner;
type sp2_outer = (...sp2_inner2 | void);
// rangevar_alias2
type rva_slk = []int;
// nested_alias_field_norm
type nfn_fa = nfn_inner;
type nfn_inner = struct { a: size, b: size };
type nfn_outer = struct { x: nfn_fa, y: nfn_fa };
// nested_alias_field_fwd (outer before fa before inner — forward ref)
type nff_outer = struct { x: nff_fa, y: nff_fa };
type nff_fa = nff_inner;
type nff_inner = struct { a: size, b: size };
fn rt_dbl(x: rt_myint2) int = {
return x * 2;
};
fn cond_pick(b: cond_myb) i32 = {
if (b) { return 0; };
return 1;
};
fn sfcr_noise(x: int) int = {
return x * 7 + 3;
};
fn sfpr_noise(x: int) int = {
return x * 7 + 3;
};
fn sfw_noise(x: int) int = {
return x * 7 + 3;
};
fn soa_sum(s: []int) int = {
let t: int = 0;
for (let x .. s) { t = t + x; };
return t;
};
fn fak_take(x: fak_fa) f64 = {
return x * 2.0;
};
fn fap_half(x: fap_f2t) f64 = {
return x / 2.0;
};
fn sa2_taillen(s: sa2_s2t) int = {
return (s.len: int);
};
fn slp_first(s: slp_b2) int = {
return s[0];
};
fn afr_take(s: afr_ali) size = {
return s.a + s.b + s.c;
};
fn ali_take(s: ali_row) size = {
return s.a + s.b + s.c;
};
fn a5_take(s: a5_big2) size = {
return s.a + s.e;
};
fn afc_take(s: afc_fs2) size = {
if (s.x != 2.5) { return 99; };
return s.n;
};
fn abc_take(s: abc_base) size = {
return s.a + s.b + s.c;
};
fn upa_peek(v: (void | upa_ali)) size = {
match (v) {
case let s: upa_ali => { return s.b; };
case void => { return 0; };
};
};
@test fn binop_alias_base() void = {
let a: bab_myint = 5;
let b: int = 3;
let c = a + b;
assert(c == 8);
let d: bab_myint = 2;
assert(a * d == 10);
assert(!(a < b));
assert(a - b == 2);
};
@test fn binop_2level() void = {
let a: b2_myint2 = 7;
let b: int = 2;
assert(a % b == 1);
let u: b2_myu = 10: u32;
let v: u32 = 3: u32;
assert(u / v == 3: u32);
assert(u + v == 13: u32);
};
@test fn ret_through_2level() void = {
let a: rt_myint2 = 21;
assert(rt_dbl(a) == 42);
};
@test fn assign_alias_alias() void = {
let x: aa_k1 = 5;
let y: aa_k2 = x;
assert(y == 5);
};
// alias-bool at the IF consumer (assert itself rejects alias-bool — that loud
// case is assert_stays_loud, not migrated here).
@test fn cond_if() void = {
let b: cond_myb = true;
let r: int = 1;
if (b) { r = 0; };
assert(r == 0);
};
@test fn cond_for() void = {
let b: cond_myb = true;
let i: int = 0;
for (b) {
i = i + 1;
if (i >= 3) { b = false; };
};
assert(i == 3);
};
@test fn cond_bang() void = {
let b: cond_myb = false;
let n = !b;
let r: int = 0;
if (!n) { r = 1; };
assert(r == 0);
};
@test fn cond_andor() void = {
let b: cond_myb = true;
let c: cond_myb = false;
let r: int = 0;
if (b && !c) { } else { r = 1; };
assert(r == 0);
if (c || b) { } else { r = 2; };
assert(r == 0);
};
@test fn cond_fnparam() void = {
let b: cond_myb = true;
assert(cond_pick(b) == 0);
};
@test fn dot_2level() void = {
assert(size(dot_a3) == 24);
assert(size((void | dot_a3)) == 32);
let v: dot_a3;
v.x = 1; v.y = 2; v.z = 3;
assert(v.x + v.y + v.z == 6);
};
@test fn deref_alias_ptr() void = {
let v: int = 41;
let p: dp_pi2 = &v;
assert(*p == 41);
*p = 7;
assert(v == 7);
};
@test fn slicefield_store_2lvl() void = {
let a: [3]int = [700: int, 800: int, 900: int];
let b: sfs_box;
b.n = 5;
b.s = a[0:3];
assert(b.n == 5);
assert(b.s[0] == 700);
assert(b.s[2] == 900);
assert(b.s.len == 3);
};
@test fn slicefield_range_2lvl() void = {
let a: [3]int = [700: int, 800: int, 900: int];
let b: sfr_box;
b.s = a[0:3];
b.n = 5;
assert(b.s.len == 3);
assert(b.s[2] == 900);
for (let x .. b.s) {
assert(!(x < 700));
};
};
@test fn strfield_store_2lvl() void = {
let b: sfst_box;
b.s = "hello";
b.n = 5;
assert(b.s.len == 5);
};
@test fn slicefield_structlit_2lvl() void = {
let a: [3]int = [700: int, 800: int, 900: int];
let b: sfsl_box = sfsl_box { s = a[0:3], n = 5: int };
assert(b.n == 5);
assert(b.s.len == 3);
assert(b.s[2] == 900);
};
@test fn slicefield_viaptr_2lvl() void = {
let a: [3]int = [700: int, 800: int, 900: int];
let b: sfv_box;
let p = &b;
p.s = a[0:3];
assert(p.s.len == 3);
assert(p.s[2] == 900);
};
@test fn slicefield_chainstore_2lvl() void = {
let a: [3]int = [700: int, 800: int, 900: int];
let v: sfc_outer;
v.i.s = a[0:3];
assert(v.i.s.len == 3);
assert(v.i.s[2] == 900);
};
@test fn slicefield_ptrchain_2lvl() void = {
let a: [3]int = [700: int, 800: int, 900: int];
let i: sfp_inner;
i.n = 1;
let v: sfp_outer;
v.pi = &i;
v.pi.s = a[0:3];
assert(i.s.len == 3);
assert(i.s[2] == 900);
};
@test fn slicefield_chainread_2lvl() void = {
let a: [3]int = [700: int, 800: int, 900: int];
let v: sfcr_outer;
v.i.s = a[0:3];
let k = sfcr_noise(9);
assert(k == 66);
let w = v.i.s;
assert(w.len == 3);
};
@test fn slicefield_ptrread_2lvl() void = {
let a: [3]int = [700: int, 800: int, 900: int];
let b: sfpr_box;
b.s = a[0:3];
let p = &b;
let k = sfpr_noise(9);
assert(k == 66);
let w = p.s;
assert(w.len == 3);
};
@test fn slicefield_wholeread_2lvl() void = {
let a: [3]int = [700: int, 800: int, 900: int];
let b: sfw_box;
b.s = a[0:3];
let k = sfw_noise(9);
assert(k == 66);
let w = b.s;
assert(w.len == 3);
assert(w[2] == 900);
};
@test fn slicefield_idx_tripwire_73() void = {
let a: [3]int = [700: int, 800: int, 900: int];
let xs: [2]sfi_box;
xs[0].s = a[0:3];
assert(xs[0].s.len == 3);
};
@test fn idx_2level() void = {
let a: idx_arr2 = [1000: int, 2000: int, 3000: int, 4000: int];
assert(a[2] == 3000);
a[1] = 9999;
assert(a[1] == 9999);
};
@test fn slice_2level() void = {
let a: [4]int = [1000: int, 2000: int, 3000: int, 4000: int];
let s: sl2_sl2 = a[1:3];
assert(s.len == 2);
assert(s[0] == 2000);
s[1] = 7777;
assert(a[2] == 7777);
};
@test fn range_2level() void = {
let a: rng_arr2 = [1: int, 2: int, 3: int, 4: int];
let sum: int = 0;
for (let x .. a) {
sum = sum + x;
};
assert(sum == 10);
};
@test fn slice_of_alias_arg() void = {
let a: soa_arr2 = [1000: int, 2000: int, 3000: int, 4000: int];
let s = a[1:3];
assert(s.len == 2);
assert(s[1] == 3000);
assert(soa_sum(a[0:4]) == 10000);
};
@test fn float_alias_param_kenv3() void = {
assert(fak_take(1.5) == 3.0);
};
@test fn float_alias_param() void = {
let v: fap_f2t = 5.0;
assert(fap_half(v) == 2.5);
};
@test fn str_alias_2level() void = {
let v: sa2_s2t = "hello";
assert(v.len == 5);
assert(sa2_taillen(v) == 5);
let w: sa2_s2t = v;
assert(w.len == 5);
};
@test fn slice_alias_param() void = {
let a: [3]int = [1000: int, 2000: int, 3000: int];
let s: slp_b2 = a[0:3];
assert(slp_first(s) == 1000);
};
@test fn arg_2level_fwdref() void = {
let x: afr_ali;
x.a = 4; x.b = 9; x.c = 13;
assert(afr_take(x) == 26);
};
@test fn arg_2level_litinit() void = {
let x: ali_st = ali_st { a = 4: size, b = 9: size, c = 13: size };
assert(ali_take(x) == 26);
};
@test fn arg_2level_5word() void = {
let v: a5_big2;
v.a = 1000; v.b = 2; v.c = 3; v.d = 4; v.e = 5000;
assert(a5_take(v) == 6000);
};
@test fn arg_2level_floatclass() void = {
let v: afc_fs2;
v.x = 2.5; v.n = 7;
assert(afc_take(v) == 7);
};
@test fn arg_base_control() void = {
let x: abc_base;
x.a = 4; x.b = 9; x.c = 13;
assert(abc_take(x) == 26);
};
@test fn union_store_norm() void = {
let x: usn_ali;
x.a = 4; x.b = 9;
let v: (void | usn_ali) = x;
match (v) {
case let s: usn_ali => {
assert(s.a == 4);
assert(s.b == 9);
};
case void => { assert(false); };
};
};
@test fn union_store_fwd() void = {
let x: usf_ali;
x.a = 4; x.b = 9;
let v: (void | usf_ali) = x;
match (v) {
case let s: usf_ali => {
assert(s.a == 4);
assert(s.b == 9);
};
case void => { assert(false); };
};
};
@test fn union_store_3word() void = {
let x: us3_ali;
x.a = 4; x.b = 9; x.c = 3;
let v: (void | us3_ali) = x;
match (v) {
case let s: us3_ali => {
assert(s.a == 4);
assert(s.c == 3);
};
case void => { assert(false); };
};
};
@test fn union_push_arg() void = {
let x: upa_ali;
x.a = 4; x.b = 9;
assert(upa_peek(x) == 9);
};
@test fn union_store_base_ctl() void = {
let x: usbc_base;
x.a = 4; x.b = 9; x.c = 3;
let v: (void | usbc_base) = x;
match (v) {
case let s: usbc_base => {
assert(s.a == 4);
assert(s.c == 3);
};
case void => { assert(false); };
};
};
@test fn union_slit_base_ctl() void = {
let v: (void | uslbc_base) = uslbc_base{a=4000, b=9000};
match (v) {
case let s: uslbc_base => {
assert(s.a == 4000);
assert(s.b == 9000);
};
case void => { assert(false); };
};
};
@test fn union_slit_alias() void = {
let v: (void | usla_ali) = usla_ali{a=4000, b=9000};
match (v) {
case let s: usla_ali => {
assert(s.a == 4000);
assert(s.b == 9000);
};
case void => { assert(false); };
};
};
@test fn union_slit_alias2() void = {
let v: (void | usl2_ali2) = usl2_ali2{a=4000, b=9000};
match (v) {
case let s: usl2_ali2 => {
assert(s.a == 4000);
assert(s.b == 9000);
};
case void => { assert(false); };
};
};
@test fn union_slit_order() void = {
let v: (void | uslo_ali) = uslo_ali{a=4000, b=9000};
match (v) {
case let s: uslo_ali => {
assert(s.a == 4000);
assert(s.b == 9000);
};
case void => { assert(false); };
};
};
@test fn castprim_3lvl_base() void = {
let x: cp3_s3;
x.f = 70000;
let y: u64 = (x.f: u32): u64;
assert(y == 70000);
};
@test fn castprim_ptr2lvl_base() void = {
let x: cpp_s2;
x.f = 70000;
let p: *cpp_s2 = &x;
let y: u64 = (p.f: u32): u64;
assert(y == 70000);
};
@test fn castprim_2lvl_base_ctl() void = {
let x: cp2_s2;
x.f = 70000;
let y: u64 = (x.f: u32): u64;
assert(y == 70000);
};
@test fn untyped_hold33_pin() void = {
let mn: (void | size) = 5;
assert(mn is size);
};
@test fn untyped_tagdst_2lvl_hold() void = {
let v: utd_r2 = 5;
assert(v is size);
};
@test fn untyped_str2lvl_ctl() void = {
let v: (void | usc_sa2) = "hi";
assert(v is usc_sa2);
};
@test fn untyped_int2lvl_ctl() void = {
let v: (void | uic_ia2) = 7;
assert(v is uic_ia2);
};
@test fn untyped_bool1lvl_ctl() void = {
let v: (void | ub1_ba1) = true;
assert(v is ub1_ba1);
};
@test fn untyped_bool2lvl_bound90() void = {
let v: (void | ub2_bb2) = true;
assert(v is ub2_bb2);
};
@test fn v2_ctrl() void = {
let x: i64 = 7;
let v: (void | v2c_pc) = &x;
assert(v is v2c_pc);
};
@test fn v2_alias2() void = {
let x: i64 = 7;
let v: (void | v2a_pb) = &x;
assert(v is v2a_pb);
};
@test fn sp_alias1() void = {
let v: sp1_outer = 5: i64;
assert(v is i64);
};
@test fn sp_alias2() void = {
let v: sp2_outer = 5: i64;
assert(v is i64);
};
@test fn amplen_plain() void = {
let s: []i64 = [1, 2, 3];
let p: *i64 = &s.len;
assert(*p == 3);
};
@test fn rangevar_alias2() void = {
let a: [4]int = [10: int, 20: int, 30: int, 40: int];
let t: rva_slk = a[2:];
assert(t.len == 2);
assert(t.cap == 2);
let sum: int = 0;
for (let x .. t) { sum = sum + 0 * x + 1; };
assert(sum == 2);
};
@test fn rangevar_plain_ctl() void = {
let a: [4]int = [10: int, 20: int, 30: int, 40: int];
let t: []int = a[2:];
let sum: int = 0;
for (let x .. t) { sum = sum + 0 * x + 1; };
assert(sum == 2);
};
@test fn nested_alias_field_norm() void = {
let v: nfn_outer;
v.x.a = 4; v.x.b = 9;
v.y.a = 7; v.y.b = 3;
assert(v.x.b == 9);
assert(v.y.b == 3);
};
@test fn nested_alias_field_fwd() void = {
let v: nff_outer;
v.x.a = 4; v.x.b = 9;
v.y.a = 7; v.y.b = 3;
assert(v.x.b == 9);
assert(v.y.b == 3);
let pa = &v.y.b;
*pa = 11;
assert(v.y.b == 11);
};

View File

@@ -0,0 +1,378 @@
// alias_cgen_b5_test — #5 alias arc F2b (B5 train): the 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). Each was a 2-level (alias-over-alias) or
// 1-level-over-named type whose cgen site single-peeled the TY_NAMED layer:
// tagged_arg_size sized a union param to 0, the #73 tripwire fataled at indexed
// struct-field store/read, cgreturn dropped the un-widened payload (silent exit
// 1), and the N_UN(STAR) pointee classify missed the array skip on a 2-level
// alias array (one spurious MOVQ (AX),AX → SEGV). All graduated to 0/0 byte-id
// by chasing the alias at the cgen site; ww was the runtime-correct reference
// for the #263-polarity rows. Migrated from test/wcc/944_alias_cgen_b5_run.c
// (#5-C3); the C driver ran each row both stages + asserted cs==ww exit, here
// the cstage run is test-lang (T1) and byte-id is test-lang-byteid (T2). The
// fill0/fill2 loud-pair, g73_static_str (#129 loud) and g73_heapfill
// (compile-only) rows live elsewhere (separate kinds).
package alias_cgen_b5_test;
// --- c1: signed_ctl
type signed_s0 = i8;
type signed_s1 = signed_s0;
type signed_st = struct { f: signed_s1, g: signed_s1 };
// --- c1: targ_2lvl / wpush_2lvl share the (void|i64) 2-lvl alias + matcher.
type targ_u0 = (void | i64);
type targ_u = targ_u0;
fn targ_h(v: targ_u) i32 = {
match (v) {
case let n: i64 => { if (n != 42) { return 1; }; return 0; };
case void => { return 2; };
};
};
// --- c1: tmem_2lvl (>48B MEMORY-class twin)
type tmem_big = struct { a: i64, b: i64, c: i64, d: i64, e: i64, f: i64, g: i64 };
type tmem_m0 = (void | tmem_big);
type tmem_m = tmem_m0;
fn tmem_h(v: tmem_m) i32 = {
match (v) {
case let s: tmem_big => { if (s.g != 77) { return 1; }; return 0; };
case void => { return 2; };
};
};
// --- c1: wstore_2lvl
type wstore_u0 = (void | i64);
type wstore_u = wstore_u0;
// --- c1: wstore_1lvl
type wstore1_u = (void | i64);
// --- c1: wstore_a_2lvl
type wstorea_u0 = (void | i64);
type wstorea_u = wstorea_u0;
// --- c1: succ_2lvl (`?`-success remap over 2-lvl alias result)
type succ_e0 = !i64;
type succ_r0 = (i64 | succ_e0);
type succ_r = succ_r0;
fn succ_w(bad: bool) succ_r = {
if (bad) { return 7: succ_e0; };
return 42;
};
fn succ_outer() succ_r = {
let v = succ_w(false)?;
return v + 1;
};
// --- c1: null_2lvl
type null_np0 = (*i64 | void);
type null_np = null_np0;
// --- c1: f32p_2lvl
type f32p_in0 = struct { a: f64 };
type f32p_in1 = f32p_in0;
type f32p_pt = struct { x: f32p_in1, y: f64 };
fn f32p_g(p: f32p_pt) f64 = { return p.x.a + p.y; };
// --- c1: tuparg_bound99 / tuparg_cast_bound99 (2-lvl alias tuple param)
type tparg_tp0 = (i64, i64);
type tparg_tp = tparg_tp0;
fn tparg_f(t: tparg_tp) i64 = { return t.0 + t.1; };
// --- c1: tuparg1_bound99 (1-level identical, not alias-depth)
type tparg1_tp = (i64, i64);
fn tparg1_f(t: tparg1_tp) i64 = { return t.0 + t.1; };
// --- c1: tupglobal_bound99 (alias-tuple module-global)
type tpglob_tp0 = (i64, i64);
type tpglob_tp = tpglob_tp0;
let tpglob_G: tpglob_tp = (4, 9);
// --- c2: g73_idxstore
type g73is_sl = []int;
type g73is_sl2 = g73is_sl;
type g73is_box = struct { s: g73is_sl2, n: int };
// --- c2: g73_strfield
type g73sf_s1t = str;
type g73sf_s2t = g73sf_s1t;
type g73sf_box = struct { s: g73sf_s2t, n: int };
fn g73sf_noise(x: int) int = { return x * 7 + 3; };
// --- c2: g73_tagfield
type g73tf_tu0 = (void | i64);
type g73tf_tu = g73tf_tu0;
type g73tf_box = struct { u: g73tf_tu, n: int };
// --- c2: g73_idxread
type g73ir_sl = []int;
type g73ir_sl2 = g73ir_sl;
type g73ir_box = struct { s: g73ir_sl2, n: int };
fn g73ir_noise(x: int) int = { return x * 7 + 3; };
// --- c2: g73_ptrread
type g73pr_sl = []int;
type g73pr_sl2 = g73pr_sl;
type g73pr_inner = struct { s: g73pr_sl2, n: int };
type g73pr_outer = struct { pi: *g73pr_inner };
fn g73pr_noise(x: int) int = { return x * 7 + 3; };
// --- c2: g73_tupread
type g73tr_sl = []int;
type g73tr_sl2 = g73tr_sl;
// --- c2: g73_static_struct (alias-tuple/struct module-global)
type g73ss_in0 = struct { a: i64, b: i64 };
type g73ss_in1 = g73ss_in0;
type g73ss_box = struct { i: g73ss_in1, n: i64 };
let g73ss_g: g73ss_box = g73ss_box { i = g73ss_in0 { a = 4, b = 9 }, n = 5 };
// --- c3: g89_ret_widen
type g89w_base = struct { a: size, b: size };
type g89w_ali = g89w_base;
fn g89w_mk() (void | g89w_ali) = {
let x: g89w_ali;
x.a = 4; x.b = 9;
return x;
};
// --- c3: g89_ret_errunion
type g89e_failure = struct { code: i32, aux: size };
type g89e_myerr = g89e_failure;
fn g89e_work(bad: bool) (i32 | g89e_myerr) = {
if (bad) {
let e: g89e_myerr;
e.code = 7; e.aux = 99;
return e;
};
return 42;
};
// --- c3: g89_ret_named_ctl (bare NAMED struct return control)
type g89c_base = struct { a: size, b: size };
fn g89c_make() (void | g89c_base) = {
let x: g89c_base;
x.a = 4; x.b = 9;
return x;
};
// --- c4: g93_l2_local
type g93l_arr = [3]int;
type g93l_arr2 = g93l_arr;
// --- c4: g93_def (def twin over a 2-lvl alias def array)
type g93d_arr0 = [3]i64;
type g93d_arr = g93d_arr0;
def g93d_D: g93d_arr = [18i64, 29i64, 40i64];
// --- c4: g93_1lvl_ctl (1-level pointee control)
type g93c_arr = [3]int;
// ===== c1: helper + funnel internalization =====
@test fn signed_ctl() void = {
let x: signed_st;
x.f = -5;
x.g = 3;
assert(x.f < 0);
let w: i64 = x.f: i64;
assert(w == -5);
};
@test fn targ_2lvl() void = {
let x: targ_u = 42i64;
assert(targ_h(x) == 0);
};
@test fn tmem_2lvl() void = {
let s: tmem_big;
s.a = 11; s.b = 22; s.c = 33; s.d = 44; s.e = 55; s.f = 66; s.g = 77;
let x: tmem_m = s;
assert(tmem_h(x) == 0);
};
@test fn wpush_2lvl() void = {
assert(targ_h(42i64) == 0);
};
@test fn wstore_2lvl() void = {
let v: wstore_u = 42i64;
match (v) {
case let n: i64 => { assert(n == 42); };
case void => { assert(false); };
};
};
@test fn wstore_1lvl() void = {
let v: wstore1_u = 42i64;
match (v) {
case let n: i64 => { assert(n == 42); };
case void => { assert(false); };
};
};
@test fn wstore_a_2lvl() void = {
let v: wstorea_u = void;
v = 42i64;
match (v) {
case let n: i64 => { assert(n == 42); };
case void => { assert(false); };
};
};
@test fn succ_2lvl() void = {
match (succ_outer()) {
case let n: i64 => { assert(n == 43); };
case succ_e0 => { assert(false); };
};
};
@test fn null_2lvl() void = {
let n: i64 = 31;
let p: null_np = &n;
match (p) {
case let q: *i64 => { assert(*q == 31); };
case void => { assert(false); };
};
};
@test fn f32p_2lvl() void = {
let p: f32p_pt;
p.x.a = 2.5;
p.y = 1.5;
assert(f32p_g(p) == 4.0);
};
@test fn tuparg_bound99() void = {
let t: tparg_tp = (4, 9);
assert(tparg_f(t) == 13);
};
@test fn tuparg1_bound99() void = {
let t: tparg1_tp = (4, 9);
assert(tparg1_f(t) == 13);
};
@test fn tuparg_cast_bound99() void = {
let t: tparg_tp = (4, 9): tparg_tp;
assert(tparg_f(t) == 13);
};
@test fn tupglobal_bound99() void = {
assert(tpglob_G.0 + tpglob_G.1 == 13);
};
// ===== c2: #73 graduation =====
@test fn g73_idxstore() void = {
let a: [3]int = [700: int, 800: int, 900: int];
let xs: [2]g73is_box;
xs[0].s = a[0:3];
assert(xs[0].s.len == 3);
};
@test fn g73_strfield() void = {
let xs: [2]g73sf_box;
xs[1].s = "hello";
xs[1].n = 4;
let k = g73sf_noise(9);
assert(k == 66);
let w = xs[1].s;
assert(w.len == 5);
};
@test fn g73_tagfield() void = {
let xs: [2]g73tf_box;
xs[0].n = 5;
xs[0].u = 42i64;
assert(xs[0].n == 5);
match (xs[0].u) {
case let v: i64 => { assert(v == 42); };
case void => { assert(false); };
};
};
@test fn g73_idxread() void = {
let a: [3]int = [700: int, 800: int, 900: int];
let xs: [2]g73ir_box;
let p = &xs[1];
p.s = a[0:3];
p.n = 4;
let k = g73ir_noise(9);
assert(k == 66);
let w = xs[1].s;
assert(w.len == 3);
assert(w[2] == 900);
};
@test fn g73_ptrread() void = {
let a: [3]int = [700: int, 800: int, 900: int];
let i: g73pr_inner;
i.s = a[0:3];
i.n = 1;
let v: g73pr_outer;
v.pi = &i;
let k = g73pr_noise(9);
assert(k == 66);
let w = v.pi.s;
assert(w.len == 3);
assert(w[2] == 900);
};
@test fn g73_tupread() void = {
let a: [3]int = [700: int, 800: int, 900: int];
let t: (g73tr_sl2, int) = (a[0:3], 5);
let s = t.0;
assert(s.len == 3);
assert(t.1 == 5);
};
@test fn g73_static_struct() void = {
assert(g73ss_g.n == 5);
assert(g73ss_g.i.b == 9);
};
// ===== c3: #89 cgreturn return-position widen =====
@test fn g89_ret_widen() void = {
match (g89w_mk()) {
case let s: g89w_ali => { assert(s.b == 9); };
case void => { assert(false); };
};
};
@test fn g89_ret_errunion() void = {
match (g89e_work(true)) {
case let e: g89e_myerr => { assert(e.aux == 99); };
case i32 => { assert(false); };
};
};
@test fn g89_ret_named_ctl() void = {
let v = g89c_make();
match (v) {
case let s: g89c_base => { assert(s.b == 9); };
case void => { assert(false); };
};
};
// ===== c4: #93 deref-index pointee chase =====
@test fn g93_l2_local() void = {
let a: g93l_arr2 = [1000: int, 2000: int, 3000: int];
let p: *g93l_arr2 = &a;
assert((*p)[2] == 3000);
};
@test fn g93_def() void = {
let p: *g93d_arr = &g93d_D;
assert((*p)[2] == 40i64);
};
@test fn g93_1lvl_ctl() void = {
let a: g93c_arr = [1000: int, 2000: int, 3000: int];
let p: *g93c_arr = &a;
assert((*p)[2] == 3000);
};

View File

@@ -0,0 +1,271 @@
// alias_cgen_b6_test — #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, c2 call-arg, c3 addr-of/field-walk/index spine,
// c4 cast/is/try, c5 reads/len/globals. Every K_RUN row was a cs-side
// single-peel that left a 2-level alias TY_NAMED (or ww the alias-blind side
// at the c3 index/field gates, graduated by W2 #102): silent-wrong store
// width, wrong stride, alias-blind field offset. Migrated from
// test/wcc/944_alias_cgen_b6_run.c (#5-C3).
//
// The 3 K_BUILDERR/loud rows (fsarg0_loud_ctl, fsarg2_bound, try_loud_38b)
// live elsewhere — value rows only here. Per-row type/global/fn families are
// prefixed to dedup the source's reused {ms,st,fs,u,big,S,my32,...} spellings
// at module scope (ww forbids local `type`); forward-ref decl order is
// irrelevant to value semantics here so families are declared base-first.
package alias_cgen_b6_test;
// ---- c1: assign/reassign family
type c1sr_ms0 = str;
type c1sr_ms = c1sr_ms0;
@test fn streassign_2lvl() void = {
let a: c1sr_ms = "hello";
let b: c1sr_ms = "x";
b = a;
assert(len(b) == 5);
};
type c1ra_st0 = struct { a: i64, b: i64, c: i64 };
type c1ra_st = c1ra_st0;
@test fn sreassign_2lvl() void = {
let x: c1ra_st; x.a = 1; x.b = 2; x.c = 3;
let y: c1ra_st; y.a = 0; y.b = 0; y.c = 0;
y = x;
assert(y.c == 3 && y.b == 2);
};
type c1da_st0 = struct { a: i64, b: i64 };
type c1da_st = c1da_st0;
@test fn dassign_2lvl() void = {
let x: c1da_st; x.a = 1; x.b = 2;
let p: *c1da_st = &x;
(*p).b = 9;
assert(x.b == 9);
};
// ---- c2: call-arg family
type c2fi_fs0 = struct { x: f64 };
type c2fi_fs = c2fi_fs0;
fn c2fi_mk() c2fi_fs0 = {
let s: c2fi_fs0; s.x = 2.5;
return s;
};
fn c2fi_g(p: c2fi_fs) f64 = { return p.x; };
@test fn fsarg_ident_ctl() void = {
let v: c2fi_fs = c2fi_mk();
assert(c2fi_g(v) == 2.5);
};
type c2sa_big0 = struct { a: i64, b: i64, c: i64 };
type c2sa_big = c2sa_big0;
fn c2sa_g(p: c2sa_big) i64 = { return p.a + p.c; };
@test fn sarg_2lvl() void = {
let s: c2sa_big; s.a = 4; s.b = 5; s.c = 9;
assert(c2sa_g(s) == 13);
};
type c2st_ms0 = str;
type c2st_ms = c2st_ms0;
fn c2st_g(s: c2st_ms) i64 = { return len(s): i64; };
@test fn strarg_2lvl() void = {
let a: c2st_ms = "hello";
assert(c2st_g(a) == 5);
};
// ---- c3: addr-of/field-walk/index spine
type c3if_el0 = struct { a: i64, b: i64 };
type c3if_el = c3if_el0;
// graduated: #102 (W2)
@test fn idxf_2lvl() void = {
let xs: [2]c3if_el;
xs[0].a = 1; xs[0].b = 2;
xs[1].a = 3; xs[1].b = 4;
assert(xs[1].b == 4 && xs[0].b == 2);
};
type c3ifp_el0 = struct { a: i64, b: i64 };
@test fn idxf_plain_ctl() void = {
let xs: [2]c3ifp_el0;
xs[0].a = 1; xs[0].b = 2;
xs[1].a = 3; xs[1].b = 4;
assert(xs[1].b == 4 && xs[0].b == 2);
};
type c3af_st0 = struct { a: i64, b: i64 };
type c3af_st = c3af_st0;
// graduated: #102 (W2)
@test fn ampf_2lvl() void = {
let x: c3af_st; x.a = 1; x.b = 2;
let p: *c3af_st = &x;
let q: *i64 = &p.b;
*q = 9;
assert(x.b == 9);
};
type c3afp_st0 = struct { a: i64, b: i64 };
@test fn ampf_plain_ctl() void = {
let x: c3afp_st0; x.a = 1; x.b = 2;
let p: *c3afp_st0 = &x;
let q: *i64 = &p.b;
*q = 9;
assert(x.b == 9);
};
type c3av_st0 = struct { a: i64, b: i64 };
type c3av_st = c3av_st0;
// amendment: #102 (W2)
@test fn ampv_2lvl() void = {
let x: c3av_st; x.a = 1; x.b = 2;
let q: *i64 = &x.b;
*q = 9;
assert(x.b == 9);
};
type c3avp_st0 = struct { a: i64, b: i64 };
@test fn ampv_plain_ctl() void = {
let x: c3avp_st0; x.a = 1; x.b = 2;
let q: *i64 = &x.b;
*q = 9;
assert(x.b == 9);
};
type c3cd_in0 = struct { v: i64 };
type c3cd_in1 = c3cd_in0;
type c3cd_out0 = struct { inner: c3cd_in1, n: i64 };
type c3cd_out1 = c3cd_out0;
@test fn chdot_2lvl() void = {
let s: c3cd_out1; s.inner.v = 7; s.n = 3;
let p: *c3cd_out1 = &s;
assert(p.inner.v == 7);
};
type c3es_my32 = u32;
type c3es_my32b = c3es_my32;
@test fn esub_2lvl() void = {
let xs: [3]c3es_my32b;
xs[0] = 5; xs[1] = 6; xs[2] = 7;
assert(xs[0]: i64 + xs[1]: i64 + xs[2]: i64 == 18);
};
type c3kw_my32 = u32;
type c3kw_S = struct { arr: [3]c3kw_my32, n: int };
@test fn kw1_101() void = {
let s = c3kw_S { arr = [10u32, 20u32, 30u32], n = 4 };
assert(s.arr[0] + s.arr[1] + s.arr[2] == 60u32);
assert(s.n == 4);
};
type c3kc_my16 = u16;
type c3kc_S2 = struct { arr: [4]c3kc_my16, n: int };
@test fn kw1_ctl16() void = {
let s = c3kc_S2 { arr = [1u16, 2u16, 3u16, 4u16], n = 9 };
assert(s.arr[0] + s.arr[1] + s.arr[2] + s.arr[3] == 10u16);
assert(s.n == 9);
};
// ---- c4: cast/is/try family
type c4sc_ms0 = str;
type c4sc_ms = c4sc_ms0;
@test fn strcast_2lvl() void = {
let a: c4sc_ms = "hey";
let b: []u8 = a: []u8;
assert(len(b) == 3);
assert(b[0] == 'h');
};
type c4ic_u0 = (void | i64);
type c4ic_u = c4ic_u0;
@test fn idcast_2lvl() void = {
let v: c4ic_u = 42i64;
let w: c4ic_u = (v: c4ic_u);
match (w) {
case let n: i64 => { assert(n == 42); };
case void => { assert(false); };
};
};
type c4is_u0 = (void | i64);
type c4is_u = c4is_u0;
@test fn is_2lvl() void = {
let v: c4is_u = 42i64;
assert(v is i64);
assert(!(v is void));
};
// ---- c5: reads/len/globals family
type c5tf_u0 = (void | i64);
type c5tf_u = c5tf_u0;
type c5tf_st0 = struct { f: c5tf_u, n: i64 };
type c5tf_st = c5tf_st0;
@test fn tfread_2lvl() void = {
let s: c5tf_st;
s.f = 42i64;
s.n = 3;
assert(s.f is i64);
let p: *c5tf_st = &s;
assert(p.f is i64);
};
type c5ln_ms0 = str;
type c5ln_ms = c5ln_ms0;
type c5ln_ar0 = [4]i64;
type c5ln_ar = c5ln_ar0;
@test fn len_2lvl() void = {
let a: c5ln_ms = "hello";
assert(len(a) == 5);
let xs: c5ln_ar = [1, 2, 3, 4];
assert(len(xs) == 4);
};
type c5gr_my64 = i64;
type c5gr_my64b = c5gr_my64;
let c5gr_G: c5gr_my64b = 7;
@test fn gref_2lvl() void = {
assert(c5gr_G == 7);
};
type c5mr_big = struct { a: i64, b: i64, c: i64, d: i64, e: i64 };
type c5mr_m0 = (void | c5mr_big);
type c5mr_m = c5mr_m0;
@test fn memread_40b() void = {
let s: c5mr_big;
s.a = 1; s.b = 2; s.c = 3; s.d = 4; s.e = 55;
let v: c5mr_m = s;
assert(v is c5mr_big);
match (v) {
case let w: c5mr_big => { assert(w.e == 55); };
case void => { assert(false); };
};
};

View File

@@ -0,0 +1,37 @@
// alias_decl_order_size_runonly_test — the cs≠ww .s carve-out split from
// alias_decl_order_size_test (#5-C3, #7f/#254 value-only runonly home).
// 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 both stages (probe-verified cs≠ww .s at
// HEAD). The decl-order-independence + size assert + last-element readback
// stay pinned on the cstage run (T1); the file is *_runonly so the
// test-lang-byteid (T2) corpus excludes it. Flip back into the byte-id file
// when #60 lands. Migrated from test/wcc/944_alias_decl_order_size_run.c.
package alias_decl_order_size_runonly_test;
// arrelem_fwd: arr=[2]base declared BEFORE base (forward ref).
type aef_arr = [2]aef_base;
type aef_base = struct { a: size, b: size };
// arrelem_norm: base before arr.
type aen_base = struct { a: size, b: size };
type aen_arr = [2]aen_base;
@test fn arrelem_fwd() void = {
assert(size(aef_arr) == 32);
let a: aef_arr;
a[0].a = 4; a[0].b = 9; a[1].a = 7; a[1].b = 3;
assert(a[0].b == 9);
assert(a[1].a == 7);
assert(a[1].b == 3);
};
@test fn arrelem_norm() void = {
assert(size(aen_arr) == 32);
let a: aen_arr;
a[0].a = 4; a[0].b = 9; a[1].a = 7; a[1].b = 3;
assert(a[0].b == 9);
assert(a[1].a == 7);
assert(a[1].b == 3);
};

View File

@@ -0,0 +1,139 @@
// alias_decl_order_size_test — #62 rider (alias arc pre-F1): type-table layout
// must be DECL-ORDER-INDEPENDENT, migrated from
// test/wcc/944_alias_decl_order_size_run.c (#5-C3). cstage check_file resolved
// typedecl bodies in file order with an eager under->size copy, so a body
// referencing a LATER typedecl read its size-0 placeholder and baked it in
// (alias size 0, union maxsz 0, struct offsets collapsed, array stride 0).
// wwstage (demand-driven tinfofornode) was order-independent; cstage now
// mirrors via resolve-on-first-reference. Oracle: size((void|ali)) = 8B tag +
// roundup8(chased member size).
//
// FORWARD-REF FIDELITY: each row's decl-order is preserved at module scope by
// giving it its OWN type family — the *_f families declare an alias (or struct
// containing a field) BEFORE the type it references, which is exactly the
// forward reference the fix made sound. The C driver ran each row both stages
// + asserted cs==ww exit; here the cstage run is test-lang (T1) and byte-id is
// test-lang-byteid (T2). The arrelem index-over-alias rows (cs≠ww .s, #60) and
// the cycle BUILDERR rows live elsewhere (runonly_test + runww carriers).
package alias_decl_order_size_test;
// sizes_norm: base before alias.
type sn_base = struct { a: size, b: size };
type sn_ali = sn_base;
// sizes_fwd: alias BEFORE base (forward ref).
type sf_ali = sf_base;
type sf_base = struct { a: size, b: size };
// union_decl_norm: named u=(void|ali) declared LAST.
type udn_base = struct { a: size, b: size };
type udn_ali = udn_base;
type udn_u = (void | udn_ali);
// union_decl_fwd: named u declared FIRST, then ali, then base.
type udf_u = (void | udf_ali);
type udf_ali = udf_base;
type udf_base = struct { a: size, b: size };
// field_fwd: outer{i,j: inner} declared BEFORE inner.
type ff_outer = struct { i: ff_inner, j: ff_inner };
type ff_inner = struct { a: size, b: size };
// field_norm: inner before outer.
type fn_inner = struct { a: size, b: size };
type fn_outer = struct { i: fn_inner, j: fn_inner };
// chain2_fwd: a2=a1=base full forward chain.
type cf_a2 = cf_a1;
type cf_a1 = cf_base;
type cf_base = struct { a: size, b: size };
// chain2_norm: base, a1, a2 in order.
type cn_base = struct { a: size, b: size };
type cn_a1 = cn_base;
type cn_a2 = cn_a1;
// union_base_ctl: direct base member (m5b_match0 no-regress control).
type ubc_base = struct { a: size, b: size };
// ptr_selfref_ok: legal self-reference (pointer field never reads the
// target's size) must stay accepted — the io.stream / list-node shape.
type node = struct { v: size, next: *node };
@test fn sizes_norm() void = {
assert(size(sn_base) == 16);
assert(size(sn_ali) == 16);
assert(size((void | sn_ali)) == 24);
};
@test fn sizes_fwd() void = {
assert(size(sf_base) == 16);
assert(size(sf_ali) == 16);
assert(size((void | sf_ali)) == 24);
};
@test fn union_decl_norm() void = {
assert(size(udn_u) == 24);
};
@test fn union_decl_fwd() void = {
assert(size(udf_u) == 24);
};
// fwd field: a size-0 inner collapsed outer's offsets too — pin the LAST word
// of the SECOND field, values all distinct.
@test fn field_fwd() void = {
assert(size(ff_inner) == 16);
assert(size(ff_outer) == 32);
let o: ff_outer;
o.i.a = 4; o.i.b = 9; o.j.a = 7; o.j.b = 3;
assert(o.i.a == 4);
assert(o.i.b == 9);
assert(o.j.a == 7);
assert(o.j.b == 3);
};
@test fn field_norm() void = {
assert(size(fn_inner) == 16);
assert(size(fn_outer) == 32);
let o: fn_outer;
o.i.a = 4; o.i.b = 9; o.j.a = 7; o.j.b = 3;
assert(o.i.a == 4);
assert(o.i.b == 9);
assert(o.j.a == 7);
assert(o.j.b == 3);
};
@test fn chain2_fwd() void = {
assert(size(cf_a1) == 16);
assert(size(cf_a2) == 16);
};
@test fn chain2_norm() void = {
assert(size(cn_a1) == 16);
assert(size(cn_a2) == 16);
};
// m5b_match0 no-regress control: direct base member, full payload readback
// through the box, last word checked.
@test fn union_base_ctl() void = {
let x: ubc_base;
x.a = 4; x.b = 9;
let v: (void | ubc_base) = x;
match (v) {
case let s: ubc_base => {
assert(s.a == 4);
assert(s.b == 9);
};
case void => { assert(false); };
};
};
@test fn ptr_selfref_ok() void = {
let n: node;
n.v = 7;
n.next = &n;
assert(size(node) == 16);
assert(n.v == 7);
};

View File

@@ -0,0 +1,95 @@
// alias_emit_b7_test — #5 alias arc B7 (finale): the cgen static-DATA emitter
// ELEM-type alias chases, migrated from test/wcc/944_alias_emit_b7_run.c
// (#5-C3). The residual single peel was on the ELEMENT type (u->sub), so a
// 2-level-elem-alias global missed the TY_STRUCT / TY_STR kind tests and fell
// off the foldable-literal path: cs emitted NO DATA (link-loud, or latent
// silence when unreferenced) while ww always emitted. The fix chases the elem
// type at each emitter site; cs aligns UP onto ww's already-correct emit and
// the rows graduate to byte-id. `type el = el0` over a named struct is ALREADY
// two NAMED layers, so the "_1lvl" spelling graduates with the 2-level rows;
// only a direct alias of a primitive is a true single layer. The C driver ran
// each row both stages + asserted cs==ww exit; here the cstage run is
// test-lang (T1) and byte-id is test-lang-byteid (T2). The slice-of-{str,
// slice,tagged} BUILDERR rows and ww-checker-reject slice cells live elsewhere.
package alias_emit_b7_test;
// sarr_2lvl: [2]el 2-lvl alias struct — elem alias missed TY_STRUCT.
type sarr2_el0 = struct { a: i64, b: i64 };
type sarr2_el1 = sarr2_el0;
type sarr2_el = sarr2_el1;
let g_sarr2: [2]sarr2_el = [sarr2_el0 { a = 1, b = 2 }, sarr2_el0 { a = 3, b = 4 }];
// sarr_1lvl: [2]el, el = el0 — two NAMED layers by construction.
type sarr1_el0 = struct { a: i64, b: i64 };
type sarr1_el = sarr1_el0;
let g_sarr1: [2]sarr1_el = [sarr1_el0 { a = 1, b = 2 }, sarr1_el0 { a = 3, b = 4 }];
// sarr_plain_ctl: [2]el0 control.
type sarrc_el0 = struct { a: i64, b: i64 };
let g_sarrc: [2]sarrc_el0 = [sarrc_el0 { a = 1, b = 2 }, sarrc_el0 { a = 3, b = 4 }];
// sarr_unref_2lvl: NEVER-REFERENCED 2-lvl-elem global — pre-B7 cs silently
// lacked DATA (no reference → no link error → latent silence). The byte-id vs
// ww (which always emitted) is the closure pin.
type sarru_el0 = struct { a: i64, b: i64 };
type sarru_el1 = sarru_el0;
type sarru_el = sarru_el1;
let g_sarru: [2]sarru_el = [sarru_el0 { a = 1, b = 2 }, sarru_el0 { a = 3, b = 4 }];
// strarr_2lvl: [2]ms 2-lvl alias str — eu != TY_STR → generic path can't fold
// strlits → link-loud. Also pins letpreintern's intern-order coupling.
type strarr2_ms0 = str;
type strarr2_ms = strarr2_ms0;
let g_strarr2: [2]strarr2_ms = ["aa", "bbb"];
// strarr_1lvl_ctl: type ms = str — TRUE 1-level; worked pre-B7, byte-neutral.
type strarr1_ms = str;
let g_strarr1: [2]strarr1_ms = ["aa", "bbb"];
// strarr_plain_ctl: [2]str control.
let g_strarrc: [2]str = ["aa", "bbb"];
// scalararr_2lvl: [3]my64b raw-bytes path — scalar fold never consulted eu,
// worked pre-B7, byte-neutral regression net.
type scalararr_my64 = i64;
type scalararr_my64b = scalararr_my64;
let g_scalararr: [3]scalararr_my64b = [5, 6, 7];
@test fn sarr_2lvl() void = {
assert(g_sarr2[0].a + g_sarr2[0].b + g_sarr2[1].a + g_sarr2[1].b == 10);
};
@test fn sarr_1lvl() void = {
assert(g_sarr1[0].a + g_sarr1[0].b + g_sarr1[1].a + g_sarr1[1].b == 10);
};
@test fn sarr_plain_ctl() void = {
assert(g_sarrc[0].a + g_sarrc[0].b + g_sarrc[1].a + g_sarrc[1].b == 10);
};
// zero-consumer latent-silence pin: the global is never read in the C source's
// main, so its DATA emit is asserted only by the byte-id (T2) gate; the T1 run
// merely exercises the def's presence.
@test fn sarr_unref_2lvl() void = {
assert(g_sarru[0].a + g_sarru[0].b + g_sarru[1].a + g_sarru[1].b == 10);
};
@test fn strarr_2lvl() void = {
assert(len(g_strarr2[0]) == 2);
assert(len(g_strarr2[1]) == 3);
};
@test fn strarr_1lvl_ctl() void = {
assert(len(g_strarr1[0]) == 2);
assert(len(g_strarr1[1]) == 3);
};
@test fn strarr_plain_ctl() void = {
assert(len(g_strarrc[0]) == 2);
assert(len(g_strarrc[1]) == 3);
};
@test fn scalararr_2lvl() void = {
assert(g_scalararr[0] + g_scalararr[1] + g_scalararr[2] == 18);
};

View File

@@ -0,0 +1,179 @@
// alias_global_decl_test — g-fold (#77 + #78 fused): alias-typed GLOBAL
// declarations, migrated from test/wcc/944_alias_global_decl_run.c (#5-C3).
// The decl/emit dispatch was alias-blind on both sides: cs (#78) single-peeled
// the let_* helper family so a 2-level alias chain (or one user alias over a
// named struct) left the type TY_NAMED, emitted no DATA, and read frame-local
// at offset 0 (saved-BP reads / SEGV); ww (#77) keyed emitletdataw's array gate
// on the UNCHASED N_TARRAY tnode so an alias-typed global ARRAY got `undefined
// reference to main.g`. Both fixed by ONE tichase at the dispatch entry.
//
// This table is the PERMANENT GUARD: the global decl path is lint-invisible
// (ww side is a no-peel consumer; cs helpers spell the one chased accessor).
// Values exceed 255 (no little-endian prefix-luck) and readbacks assert the
// LAST element. The C driver ran each row both stages + asserted cs==ww exit;
// here the cstage run is test-lang (T1) and byte-id is test-lang-byteid (T2).
// The *_ord rows' decl-after-let dimension is subsumed by module-level
// resolution (already order-independent), kept for row-count fidelity.
package alias_global_decl_test;
type t_arr = [4]int;
type t_arr2 = t_arr;
type t_au = [4]u32;
type t_myint = int;
type t_myint2 = t_myint;
type t_ms = str;
type t_ms2 = t_ms;
type t_mf = f64;
type t_mf2 = t_mf;
type t_mg = f32;
type t_mg2 = t_mg;
type t_pt = struct { x: int, y: int };
type t_pt1 = t_pt;
type t_pt2 = t_pt1;
type t_sl = []int;
type t_sl2 = t_sl;
type t_sa = [2]str;
type t_sa2 = t_sa;
type t_row = [3]int;
let g_ctl: [4]int = [1001: int, 1002: int, 1003: int, 1004: int];
let g_a1r: t_arr = [1001: int, 1002: int, 1003: int, 1004: int];
let g_a1w: t_arr = [1001: int, 1002: int, 1003: int, 1004: int];
let g_aord: t_arr = [1001: int, 1002: int, 1003: int, 1004: int];
let g_a2r: t_arr2 = [1001: int, 1002: int, 1003: int, 1004: int];
let g_a2o: t_arr2 = [1001: int, 1002: int, 1003: int, 1004: int];
let g_u32: t_au = [1001: u32, 1002: u32, 1003: u32, 1004: u32];
let g_sc2: t_myint2 = 4242;
let g_sc2o: t_myint2 = 4242;
let g_str2: t_ms2 = "hello";
let g_flt2: t_mf2 = 1.5;
let g_flt2f: t_mg2 = 1.5f32;
let g_st1: t_pt1;
let g_st2: t_pt2;
let g_stlit: t_pt1 = t_pt { x = 1001, y = 2002 };
let g_sl2: t_sl2 = [1001: int, 1002: int, 1003: int];
let g_sarr1: t_sa = ["hello", "worlds!"];
let g_sarr2: t_sa2 = ["hello", "worlds!"];
def G_a2: t_arr2 = [1001: int, 1002: int, 1003: int, 1004: int];
def G_st: t_pt1 = t_pt { x = 1001, y = 2002 };
def G_f2: t_mf2 = 1.5;
let g_hsl: t_sl = [1001: int, 1002: int, 1003: int];
let g_helem: [2]t_row = [[1010: int, 1020: int, 1030: int], [1040: int, 1050: int, 1060: int]];
@test fn ctl_plain() void = {
assert(g_ctl[3] == 1004);
g_ctl[3] = 9999;
assert(g_ctl[3] == 9999);
};
@test fn garr1_read() void = {
assert(g_a1r[0] == 1001);
assert(g_a1r[3] == 1004);
};
@test fn garr1_wr() void = {
g_a1w[3] = 8888;
assert(g_a1w[3] == 8888);
assert(g_a1w[2] == 1003);
};
@test fn garr_ord() void = {
assert(g_aord[3] == 1004);
};
// #78 headline: pre-fix cs emitted NO DATA and read the saved-BP word.
@test fn garr2_read() void = {
assert(g_a2r[0] == 1001);
assert(g_a2r[3] == 1004);
};
@test fn garr2_ordwr() void = {
assert(g_a2o[3] == 1004);
g_a2o[1] = 7777;
assert(g_a2o[1] == 7777);
};
@test fn garr_u32() void = {
assert(g_u32[3] == 1004);
g_u32[3] = 8888;
assert(g_u32[3] == 8888);
assert(g_u32[2] == 1003);
};
@test fn gsc2() void = {
assert(g_sc2 == 4242);
g_sc2 = 9999;
assert(g_sc2 == 9999);
};
@test fn gsc2_ord() void = {
assert(g_sc2o == 4242);
};
@test fn gstr2() void = {
assert(g_str2.len == 5);
};
@test fn gflt2() void = {
assert(g_flt2 == 1.5);
};
@test fn gflt2_f32() void = {
assert(g_flt2f == 1.5f32);
};
// 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).
@test fn gst1() void = {
g_st1.y = 2002;
assert(g_st1.y == 2002);
};
@test fn gst2() void = {
g_st2.y = 2002;
assert(g_st2.y == 2002);
};
@test fn gstlit() void = {
assert(g_stlit.y == 2002);
};
@test fn gsl2() void = {
assert(g_sl2.len == 3);
assert(g_sl2[2] == 1003);
};
// [N]str rows also pin letpreintern's chased array-leg gate: a missed
// pre-intern desyncs _S_ label order vs cstage (byte-id catches it).
@test fn gstrarr1() void = {
assert(g_sarr1[1].len == 7);
};
@test fn gstrarr2() void = {
assert(g_sarr2[1].len == 7);
};
@test fn gdef_a2() void = {
assert(G_a2[3] == 1004);
};
@test fn gdef_st() void = {
assert(G_st.y == 2002);
};
@test fn gdef_f2() void = {
assert(G_f2 == 1.5);
};
// no-regression holds: alias global SLICE (green before the fold) and alias
// ELEMENT type (batch-1 win).
@test fn hold_slice1() void = {
assert(g_hsl.len == 3);
assert(g_hsl[2] == 1003);
};
@test fn hold_elem() void = {
assert(g_helem[0][0] == 1010);
assert(g_helem[1][2] == 1060);
};

View File

@@ -0,0 +1,212 @@
// alias_idx_family_test — #5 alias arc F2a batch 1 (task #60 + #79 init-store
// rider): wwstage INDEX / SLICE / FOR-RANGE / LITERAL-INIT over an alias-NAMED
// base type, migrated from test/wcc/944_alias_idx_family_run.c (#5-C3). The
// tnode-keyed cgen walks saw only the N_TNAME leaf — esz fell to the
// 1-sentinel and the base classified as a POINTER (MOVQ + no IMULQ): SEGV on
// index/range, silent-wrong on slice, alias-[N]u32 literal-init stride-skew
// (#79). cstage reads everything off the chased stamped type and is the
// runtime-correct reference; the fix re-keys the ww sites off tichase'd
// tinfos and every row graduates to byte-id (ww aligned UP).
//
// Values exceed 255 so an esz=1 byte-load cannot pass by little-endian
// prefix-luck; readbacks assert the LAST element. The C driver ran each row
// on both stages + asserted cs==ww exit; here the cstage run is test-lang (T1)
// and the byte-id is test-lang-byteid (T2). The fwd-ref rows' decl-order
// dimension is subsumed by module-level resolution (already order-independent).
//
// Deliberately NOT pinned (g-fold #77/#78): any DIRECT alias-typed global
// ARRAY row (ww link-ERR / cs silent-wrong) — m7c_global2d's alias is on the
// ELEMENT and gslice_alias is a global alias SLICE, both of which resolve.
package alias_idx_family_test;
type arr = [4]int;
type arr2 = arr;
type sl = []int;
type sl2 = sl;
type a4 = [4]u32;
type a6 = [6]u32;
type arrk = [1024]int;
type slk = []int;
type slk2 = slk;
type row = [3]int;
let g_2d: [2]row = [[10: int, 20: int, 30: int], [40: int, 50: int, 60: int]];
let g_slice: sl = [1000: int, 2000: int, 3000: int];
@test fn idx0_ctl() void = {
let a: [4]int = [1000: int, 2000: int, 3000: int, 4000: int];
assert(a[3] == 4000);
a[3] = 9999;
assert(a[3] == 9999);
};
@test fn idx1_alias() void = {
let a: arr = [1000: int, 2000: int, 3000: int, 4000: int];
assert(a[2] == 3000);
assert(a[3] == 4000);
a[3] = 8888;
assert(a[3] == 8888);
};
@test fn idx2_2level() void = {
let a: arr2 = [1000: int, 2000: int, 3000: int, 4000: int];
assert(a[2] == 3000);
a[1] = 9999;
assert(a[1] == 9999);
assert(a[3] == 4000);
};
@test fn idx_fwdref() void = {
let a: arr2 = [1000: int, 2000: int, 3000: int, 4000: int];
assert(a[3] == 4000);
a[3] += 500;
assert(a[3] == 4500);
};
// #79: narrow-elem alias literal-init — pre-fix the per-element store rode the
// esz=8 sentinel + MOVQ over a stride-4 slot (saved-BP/RIP smash); LAST read.
@test fn init_u32_alias() void = {
let a: a4 = [1: u32, 2: u32, 3: u32, 4: u32];
assert(a[3] == 4);
assert(a[0] == 1);
};
@test fn initrep_u32_alias() void = {
let a: a6 = [7: u32...];
assert(a[5] == 7);
assert(a[0] == 7);
};
// uninit alias array + per-index loop fill; pins the bare-let classify (no
// composite zero-fill, cstage-identical).
@test fn loopfill_1024() void = {
let a: arrk;
let i: int = 0;
for (i < 1024) {
a[i] = i * 3 + 1000;
i += 1;
};
assert(a[1023] == 1023 * 3 + 1000);
};
@test fn slice0_ctl() void = {
let a: [4]int = [1000: int, 2000: int, 3000: int, 4000: int];
let s: []int = a[1:3];
assert(s.len == 2);
assert(s[1] == 3000);
};
@test fn slice1_alias() void = {
let a: arr = [1000: int, 2000: int, 3000: int, 4000: int];
let s: sl = a[1:3];
assert(s.len == 2);
assert(s[0] == 2000);
s[1] = 7777;
assert(a[2] == 7777);
};
@test fn slice2_2level() void = {
let a: [4]int = [1000: int, 2000: int, 3000: int, 4000: int];
let s: sl2 = a[1:3];
assert(s.len == 2);
assert(s[0] == 2000);
s[1] = 7777;
assert(a[2] == 7777);
assert(s[1] == 7777);
let r: sl = s[0:2];
assert(r.len == 2);
assert(r[1] == 7777);
};
// 1000 elements, values 300..7293: an esz=1 byte load cannot land on the right
// word; LAST-elem readback breaks prefix-luck. Also pins alias default-hi
// (a[2:]), .cap via the chased cgbasecap leg, and range over the sub-slice.
@test fn slice1big() void = {
let a: [1000]int;
let i: int = 0;
for (i < 1000) {
a[i] = i * 7 + 300;
i += 1;
};
let s: slk = a[1:1000];
assert(s.len == 999);
assert(s[998] == 999 * 7 + 300);
s[998] = 123456;
assert(a[999] == 123456);
let t: slk2 = a[2:];
assert(t.len == 998);
assert(t.cap == 998);
assert(t[997] == 123456);
let cnt: int = 0;
for (let x .. t) { cnt = cnt + 1; assert(x >= 0); };
assert(cnt == 998);
};
@test fn slice_fwdref() void = {
let a: arr2 = [1000: int, 2000: int, 3000: int, 4000: int];
let s: sl2 = a[1:3];
assert(s[1] == 3000);
s[1] *= 3;
assert(a[2] == 9000);
};
@test fn range0_ctl() void = {
let a: [4]int = [1: int, 2: int, 3: int, 4: int];
let sum: int = 0;
for (let x .. a) { sum = sum + x; };
assert(sum == 10);
};
@test fn range1_alias() void = {
let a: arr = [1000: int, 2000: int, 3000: int, 4000: int];
let sum: int = 0;
for (let x .. a) { sum = sum + x; };
assert(sum == 10000);
};
@test fn range2_2level() void = {
let a: arr2 = [1000: int, 2000: int, 3000: int, 4000: int];
let sum: int = 0;
for (let x .. a) { sum = sum + x; };
assert(sum == 10000);
};
@test fn range_slicealias() void = {
let a: [4]int = [1000: int, 2000: int, 3000: int, 4000: int];
let t: sl = a[0:4];
let sum: int = 0;
for (let x .. t) { sum = sum + x; };
assert(sum == 10000);
};
// 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.
@test fn m7c_global2d() void = {
assert(g_2d[0][0] == 10);
assert(g_2d[1][2] == 60);
};
// GLOBAL alias-typed SLICE: DATA emit + .len + indexed read all resolve.
@test fn gslice_alias() void = {
assert(g_slice.len == 3);
assert(g_slice[2] == 3000);
};
// slice-of-alias-array as a CALL ARG exercises the pusharg N_SLICE leg, a
// distinct lowering from cgslice; plus inferred-let receive of an alias-base
// slice.
fn sumof(s: []int) int = {
let t: int = 0;
for (let x .. s) { t = t + x; };
return t;
};
@test fn slicearg_alias() void = {
let a: arr2 = [1000: int, 2000: int, 3000: int, 4000: int];
let s = a[1:3];
assert(s.len == 2);
assert(s[1] == 3000);
assert(sumof(a[0:4]) == 10000);
};

View File

@@ -0,0 +1,55 @@
// alias_structlit_init_test — #63: let-init from an alias-NAMED struct
// LITERAL, migrated from test/wcc/944_alias_structlit_init_run.c (#5-C3).
// wwstage's cglet N_STRUCTLIT arm resolved the struct by a BARE
// structlookup(sname): for an alias `type rep2 = rep` only the base `rep` is
// registered, so the lookup returned nil and the field-fill never fired —
// <=8B silently zeroed the slot and DROPPED the literal, >8B loud-bailed.
// The fix routes the arm through structlookupchain (the #92/W2 SSoT), which
// chases the alias chain to the base struct; cstage was always correct via
// type_chase_named, so this is ww-only align-UP. The >24B sret RETURN twin
// (cgenstmt:1250) had no scalar-default catch and was silently wrong —
// reviewer-63 routed it through structlookupchain too (sret_return_alias32).
//
// The C driver ran each row on both stages + asserted cs==ww exit; here the
// cstage run is test-lang (T1) and the byte-id is test-lang-byteid (T2).
package alias_structlit_init_test;
type rep = struct { id: size };
type rep2 = rep;
type st = struct { a: size, b: size };
type row = st;
type pt2 = struct { a: size, b: size };
type big = struct { a: size, b: size, c: size, d: size };
type biga = big;
fn mk() biga = { return biga{a=1, b=2, c=3, d=4}; };
@test fn letinit_typed() void = {
let r: rep2 = rep2{id=6};
assert(r.id: int == 6);
};
@test fn letinit_untyped() void = {
let r = rep2{id=6};
assert(r.id: int == 6);
};
@test fn letlit_alias16() void = {
let a: row = row{a=3, b=4};
assert((a.a + a.b): int == 7);
};
// control: non-alias 16B let-init — the no-regress guard (the alias hop is
// the trigger).
@test fn control_direct() void = {
let x: pt2 = pt2{a=3, b=4};
assert((x.a + x.b): int == 7);
};
// the >24B sret-RETURN twin of the let-init site (cgenstmt:1250): the alias
// field-fill was SKIPPED and the callee returned an uninitialised sret buffer.
@test fn sret_return_alias32() void = {
let r: biga = mk();
assert((r.a + r.b + r.c + r.d): int == 10);
};

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;
};