diff --git a/Makefile b/Makefile index 34084b44..f504f448 100644 --- a/Makefile +++ b/Makefile @@ -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; \ diff --git a/test/lang/alias_accept_runonly_test.ww b/test/lang/alias_accept_runonly_test.ww new file mode 100644 index 00000000..786ef9f9 --- /dev/null +++ b/test/lang/alias_accept_runonly_test.ww @@ -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); +}; diff --git a/test/lang/alias_accept_test.ww b/test/lang/alias_accept_test.ww new file mode 100644 index 00000000..de259f7b --- /dev/null +++ b/test/lang/alias_accept_test.ww @@ -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); +}; diff --git a/test/lang/alias_cgen_b5_test.ww b/test/lang/alias_cgen_b5_test.ww new file mode 100644 index 00000000..739ea99e --- /dev/null +++ b/test/lang/alias_cgen_b5_test.ww @@ -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); +}; diff --git a/test/lang/alias_cgen_b6_test.ww b/test/lang/alias_cgen_b6_test.ww new file mode 100644 index 00000000..e6393eaf --- /dev/null +++ b/test/lang/alias_cgen_b6_test.ww @@ -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); }; + }; +}; diff --git a/test/lang/alias_decl_order_size_runonly_test.ww b/test/lang/alias_decl_order_size_runonly_test.ww new file mode 100644 index 00000000..02dbe9d3 --- /dev/null +++ b/test/lang/alias_decl_order_size_runonly_test.ww @@ -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); +}; diff --git a/test/lang/alias_decl_order_size_test.ww b/test/lang/alias_decl_order_size_test.ww new file mode 100644 index 00000000..d4104d07 --- /dev/null +++ b/test/lang/alias_decl_order_size_test.ww @@ -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); +}; diff --git a/test/lang/alias_emit_b7_test.ww b/test/lang/alias_emit_b7_test.ww new file mode 100644 index 00000000..b5b39792 --- /dev/null +++ b/test/lang/alias_emit_b7_test.ww @@ -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); +}; diff --git a/test/lang/alias_global_decl_test.ww b/test/lang/alias_global_decl_test.ww new file mode 100644 index 00000000..5e9531b5 --- /dev/null +++ b/test/lang/alias_global_decl_test.ww @@ -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); +}; diff --git a/test/lang/alias_idx_family_test.ww b/test/lang/alias_idx_family_test.ww new file mode 100644 index 00000000..613afa84 --- /dev/null +++ b/test/lang/alias_idx_family_test.ww @@ -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); +}; diff --git a/test/lang/alias_structlit_init_test.ww b/test/lang/alias_structlit_init_test.ww new file mode 100644 index 00000000..6a9ba913 --- /dev/null +++ b/test/lang/alias_structlit_init_test.ww @@ -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); +}; diff --git a/test/wcc/944_alias_accept_run.c b/test/wcc/944_alias_accept_run.c index 2e7cdd97..4acfbd3b 100644 --- a/test/wcc/944_alias_accept_run.c +++ b/test/wcc/944_alias_accept_run.c @@ -1,75 +1,19 @@ /* - * 944_alias_accept_run — #5 alias arc F1: cstage acceptance ALIGN-UP - * through the transitive TY_NAMED chase (type_chase_named, promoted to - * cmd/wcc/type.c). harec dealiases at every promotion/cond/assign - * consumer (ref/harec/src/types.c:53 type_dealias; :989-996 - * type_is_assignable; src/check.c:1083-1105 type_promote; :2141 if, - * :2515 for, :3229 &&/||, :3572 !) — wwstage already accepted these - * shapes AND ran them Hare-right (F0 census /tmp/f0/livelist.md), so - * the cstage single-peel rejects were the lean side aligned UP. + * 944_alias_accept_run — SLIM CARRIER (#5-C3 alias fold-2). The 62 K_RUN value + * rows migrated to test/lang/alias_accept_test.ww (@test, cs==ww byte-id via + * test-lang-byteid); the cs!=ww NOID row (v2_struct2, #81) to + * test/lang/alias_accept_runonly_test.ww; the symmetric K_BUILDERR rejects + * (assert_stays_loud, v2_ambig, v2_ambig2, union_as_bound_54) + the two + * now-symmetric ex-K_BUILDERR_CS rows (binop_alias_vs_alias, untyped_nestvar, + * superseded at HEAD) to test/wcc/data/alias_/case.ww runww //ww:error. * - * row | shape | want - * ---------------------+--------------------------------------+----- - * binop_alias_base | myint + int (F0 m1_binop) | 0 - * binop_2level | myint2 % int, myu / u32 (m1_binop2) | 0 - * ret_through_2level | fn(x: myint2) int = x * 2 | 0 - * assign_alias_alias | k1 → k2 (same base; harec dealias- | - * | both admits) | 0 - * binop_alias_vs_alias | k1 + k2 — cstage stays LOUD per | - * | harec type_promote ALIAS+ALIAS→NULL | err(cs) - * cond_if/for/bang/ | alias-of-bool at every cond consumer | - * andor/fnparam | (F0 m2_* family) | 0 - * assert_stays_loud | alias-bool assert — BOTH stages loud | - * | (F0 2a DISSOLVED-SYMMETRIC; the Hare | - * | widening is parked on #5) | err - * dot_2level | field access via a3=b3=c3=struct | - * | (task #70, ken c3_chain3) | 0 - * deref_alias_ptr | *p through pi2=pi=*int | 0 - * idx/slice/range_ | index/slice/for-range over 2-level | - * 2level, slice_arg | alias bases (F0 8b) — cs cgen index | - * | family chased (idx_eff + base | - * | classify); ww half landed (#60, F2a | - * | batch 1 tichase) — graduated K_RUN | 0 - * arg_2level_* | task #61: alias-NAMED struct PARAM | - * | classify (fwd-ref / lit-init / 40B | - * | 5-eightbyte / f64 SSE class legs + | - * | base control) | 0 - * float_alias_param* / | ken-v3 leg: 2-level f64/str/slice | - * str_alias_2level / | aliases at the cgen KIND classifiers | - * slice_alias_param | (slice leg graduated, #60 F2a b1) | 0 - * slicefield_* / | reviewer-F1 leg: 2-level alias of | - * strfield_store_2lvl | slice/str as a STRUCT FIELD type — | - * | cgen field gates chased (stores, | - * | struct-lit, walk leaves, reads); | - * | unprobed gates LOUD-tripwired (#73, | - * | K_BUILDERR_CS pin) | 0 - * union_store_* + | task #62 Layer-2: alias-NAMED struct | - * union_push_arg | as union member — widen store/push | - * | word0-only; cs half c138605, ww half | - * | F2a batch-2 c2 — graduated K_RUN; | - * | base ctl + #54-bound `as` row loud | 0 - * union_slit_* | task #92 (F2a batch-3 c3): alias- | - * | named struct LITERAL into a union — | - * | rhsstructpayload N_STRUCTLIT arm | - * | routed through structlookupchain; | - * | base ctl + 1/2-level + decl order | 0 - * nested_alias_field_* | task #71: alias-typed nested-field | - * | store/read/addr-of walks fold to | - * | direct offsets (byte-id graduation, | - * | both decl orders) | 0 - * - * K_RUN rows also assert cstage/wwstage asm byte-id (acceptance - * graduations land byte-identical — F0's accept side was wwstage). - * K_RUN_CS / K_BUILDERR_CS rows run the cstage driver only, each - * citing the task that graduates them. K_RUN_CS_WWERR rows also run - * the wwstage driver expecting a LOUD build failure (the bound row's - * job is preventing a silent ww regression while the leg is parked); - * K_RUN_NOID rows run both but waive the byte-id cell, citing the - * blocking task at the row. binop_alias_vs_alias is - * CS-only loud: the wwstage checker stays silent on typed mismatches - * by design (5-lite discipline) — cs pins the harec-parity reject. - * NNN<950, self-contained (/tmp, no imports) — rule-14's selfhost- - * sibling race does not apply (941/944 precedent). + * What survives here is the IRREDUCIBLE per-stage-asymmetric pin no in-language + * surface can host: cstage builds+RUNS exit 0 while wwstage LOUD-REJECTS + * (@test needs ww to build; runww //ww:error needs BOTH to fail). Held + * divergence task #96: ww `&s.len` / `&s.cap` over an alias-typed slice PARAM + * is "unsupported address-of shape"; cstage classifies the address shape + * through the alias chase and runs correct. Drew-ruled slim-carrier home + * (#5-C3, 954_tuprecv precedent). */ #include #include @@ -87,38 +31,7 @@ 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 drivers, exit==want, + byte-id */ -#define K_BUILDERR 1 /* build FAILS with experr on BOTH drivers */ -#define K_RUN_CS 2 /* cstage only — ww half pending (cite at row) */ -#define K_BUILDERR_CS 3 /* cstage-only loud (ww silent by design) */ -#define K_RUN_NOID 4 /* build+run BOTH, exit==want, byte-id - * SKIPPED — cite the blocking task */ -#define K_RUN_CS_WWERR 5 /* LOUD-HOLD bound row: cstage build+run, - * exit==want; WWSTAGE build must FAIL - * with experr — cite the blocking task */ - -struct row { const char *label; const char *src; int want; - int kind; const char *experr; }; - -/* errlog_has — a BUILDERR row must fail WITH its diagnostic; any other - * failure (parse error, crash, hang-kill) is a vacuous reject (940 - * precedent). */ +/* a reject must fail WITH its diagnostic; a crash (no body) is vacuous. */ static int errlog_has(const char *path, const char *needle) { @@ -131,938 +44,49 @@ errlog_has(const char *path, const char *needle) return strstr(buf, needle) != NULL; } +/* cstage builds+runs (exit 0); wwstage frontend (w6c_ww) loud-rejects wwerr. */ +static int +run_row(const char *bin, const char *label, const char *src, + const char *wwerr, int i) +{ + char dir[96], srcf[160], outbin[160], wwe[160], ss[160], rm[200], cmd[2048]; + snprintf(dir, sizeof dir, "/tmp/aacc_%d_%d", getpid(), i); + mkdir(dir, 0755); + snprintf(srcf, sizeof srcf, "%s/c.ww", dir); + snprintf(outbin, sizeof outbin, "%s/bin", 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, + "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", label); + ok = 0; + } else if (runwait(outbin) != 0) { + fprintf(stderr, "row[%s]: cstage run != 0\n", label); + 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 *wwerr; }; + static const struct row rows[] = { - { "binop_alias_base", - "package main;\n" - "type myint = int;\n" - "export fn main() i32 = {\n" - " let a: myint = 5;\n" - " let b: int = 3;\n" - " let c = a + b;\n" - " if (c != 8) { return 1; };\n" - " let d: myint = 2;\n" - " if (a * d != 10) { return 2; };\n" - " if (a < b) { return 3; };\n" - " if (a - b != 2) { return 4; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - { "binop_2level", - "package main;\n" - "type myint = int;\n" - "type myint2 = myint;\n" - "type myu = u32;\n" - "export fn main() i32 = {\n" - " let a: myint2 = 7;\n" - " let b: int = 2;\n" - " if (a % b != 1) { return 1; };\n" - " let u: myu = 10: u32;\n" - " let v: u32 = 3: u32;\n" - " if (u / v != 3: u32) { return 2; };\n" - " if (u + v != 13: u32) { return 3; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - { "ret_through_2level", - "package main;\n" - "type myint = int;\n" - "type myint2 = myint;\n" - "fn dbl(x: myint2) int = {\n" - " return x * 2;\n" - "};\n" - "export fn main() i32 = {\n" - " let a: myint2 = 21;\n" - " if (dbl(a) != 42) { return 1; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - { "assign_alias_alias", - "package main;\n" - "type k1 = int;\n" - "type k2 = int;\n" - "export fn main() i32 = {\n" - " let x: k1 = 5;\n" - " let y: k2 = x;\n" - " if (y != 5) { return 1; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - /* harec type_promote: ALIAS+ALIAS → NULL even on a shared base - * (ref/harec/src/check.c:1087-1089). wwstage's checker is silent - * on typed mismatches (5-lite) — cs-only pin. */ - { "binop_alias_vs_alias", - "package main;\n" - "type k1 = int;\n" - "type k2 = int;\n" - "export fn main() i32 = {\n" - " let x: k1 = 5;\n" - " let y: k2 = 3;\n" - " if (x + y != 8) { return 1; };\n" - " return 0;\n" - "};\n", 0, K_BUILDERR_CS, "operands have differing types" }, - { "cond_if", - "package main;\n" - "type myb = bool;\n" - "export fn main() i32 = {\n" - " let b: myb = true;\n" - " if (b) { return 0; };\n" - " return 1;\n" - "};\n", 0, K_RUN, NULL }, - { "cond_for", - "package main;\n" - "type myb = bool;\n" - "export fn main() i32 = {\n" - " let b: myb = true;\n" - " let i: int = 0;\n" - " for (b) {\n" - " i = i + 1;\n" - " if (i >= 3) { b = false; };\n" - " };\n" - " if (i != 3) { return 1; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - { "cond_bang", - "package main;\n" - "type myb = bool;\n" - "export fn main() i32 = {\n" - " let b: myb = false;\n" - " let n = !b;\n" - " if (!n) { return 1; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - { "cond_andor", - "package main;\n" - "type myb = bool;\n" - "export fn main() i32 = {\n" - " let b: myb = true;\n" - " let c: myb = false;\n" - " if (b && !c) { } else { return 1; };\n" - " if (c || b) { } else { return 2; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - { "cond_fnparam", - "package main;\n" - "type myb = bool;\n" - "fn pick(b: myb) i32 = {\n" - " if (b) { return 0; };\n" - " return 1;\n" - "};\n" - "export fn main() i32 = {\n" - " let b: myb = true;\n" - " return pick(b);\n" - "};\n", 0, K_RUN, NULL }, - { "assert_stays_loud", - "package main;\n" - "type myb = bool;\n" - "export fn main() i32 = {\n" - " let b: myb = true;\n" - " assert(b);\n" - " return 0;\n" - "};\n", 0, K_BUILDERR, "assert: cond must be bool" }, - { "dot_2level", - "package main;\n" - "type a3 = b3;\n" - "type b3 = c3;\n" - "type c3 = struct { x: size, y: size, z: size };\n" - "export fn main() i32 = {\n" - " if (size(a3) != 24) { return 1; };\n" - " if (size((void | a3)) != 32) { return 2; };\n" - " let v: a3;\n" - " v.x = 1; v.y = 2; v.z = 3;\n" - " if (v.x + v.y + v.z != 6) { return 3; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - { "deref_alias_ptr", - "package main;\n" - "type pi = *int;\n" - "type pi2 = pi;\n" - "export fn main() i32 = {\n" - " let v: int = 41;\n" - " let p: pi2 = &v;\n" - " if (*p != 41) { return 1; };\n" - " *p = 7;\n" - " if (v != 7) { return 2; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - /* ---- reviewer-F1 find: 2-level alias of slice/str as a STRUCT - * FIELD type. The acceptance above admits every construction; the - * cgen FIELD-TYPE gates single-peeled, so the slice/str 3-word - * arms fell to word0-only scalar tails — SILENT wrong (ww correct, - * every shape LOUD at pristine 738d7f4 = opened by this commit). - * Chased gates: single-dot store (+via-ptr), struct-lit fill, - * chained store-walk leaf, chained-ptr-field store, single-dot / - * via-ptr / chained-walk reads. Each row pins one gate; the - * noise() call clobbers BX/CX so stale-register luck can't pass a - * word0-only header. Unprobed sibling gates are LOUD-tripwired, - * pinned by the #73 row at the end of this block. Rows whose - * `.len` readback rides the chained-dot READ walk entered as - * K_RUN_CS (runtime-correct both stages; cs took the generic - * spine) and graduated to K_RUN with the #71 walk chase. */ - { "slicefield_store_2lvl", - "package main;\n" - "type sl = []int;\n" - "type sl2 = sl;\n" - "type box = struct { s: sl2, n: int };\n" - "export fn main() i32 = {\n" - " let a: [3]int = [700: int, 800: int, 900: int];\n" - " let b: box;\n" - " b.n = 5;\n" - " b.s = a[0:3];\n" - " if (b.n != 5) { return 9; };\n" - " if (b.s[0] != 700) { return 1; };\n" - " if (b.s[2] != 900) { return 2; };\n" - " if (b.s.len != 3) { return 3; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - { "slicefield_range_2lvl", - "package main;\n" - "type sl = []int;\n" - "type sl2 = sl;\n" - "type box = struct { s: sl2, n: int };\n" - "export fn main() i32 = {\n" - " let a: [3]int = [700: int, 800: int, 900: int];\n" - " let b: box;\n" - " b.s = a[0:3];\n" - " b.n = 5;\n" - " if (b.s.len != 3) { return 1; };\n" - " if (b.s[2] != 900) { return 2; };\n" - " for (let x .. b.s) {\n" - " if (x < 700) { return 3; };\n" - " };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - { "strfield_store_2lvl", - "package main;\n" - "type s1t = str;\n" - "type s2t = s1t;\n" - "type box = struct { s: s2t, n: int };\n" - "export fn main() i32 = {\n" - " let b: box;\n" - " b.s = \"hello\";\n" - " b.n = 5;\n" - " if (b.s.len != 5) { return 1; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - { "slicefield_structlit_2lvl", - "package main;\n" - "type sl = []int;\n" - "type sl2 = sl;\n" - "type box = struct { s: sl2, n: int };\n" - "export fn main() i32 = {\n" - " let a: [3]int = [700: int, 800: int, 900: int];\n" - " let b: box = box { s = a[0:3], n = 5: int };\n" - " if (b.n != 5) { return 1; };\n" - " if (b.s.len != 3) { return 2; };\n" - " if (b.s[2] != 900) { return 3; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - { "slicefield_viaptr_2lvl", - "package main;\n" - "type sl = []int;\n" - "type sl2 = sl;\n" - "type box = struct { s: sl2, n: int };\n" - "export fn main() i32 = {\n" - " let a: [3]int = [700: int, 800: int, 900: int];\n" - " let b: box;\n" - " let p = &b;\n" - " p.s = a[0:3];\n" - " if (p.s.len != 3) { return 1; };\n" - " if (p.s[2] != 900) { return 2; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - { "slicefield_chainstore_2lvl", - "package main;\n" - "type sl = []int;\n" - "type sl2 = sl;\n" - "type inner = struct { s: sl2 };\n" - "type outer = struct { i: inner };\n" - "export fn main() i32 = {\n" - " let a: [3]int = [700: int, 800: int, 900: int];\n" - " let v: outer;\n" - " v.i.s = a[0:3];\n" - " if (v.i.s.len != 3) { return 1; };\n" - " if (v.i.s[2] != 900) { return 2; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - { "slicefield_ptrchain_2lvl", - "package main;\n" - "type sl = []int;\n" - "type sl2 = sl;\n" - "type inner = struct { s: sl2, n: int };\n" - "type outer = struct { pi: *inner };\n" - "export fn main() i32 = {\n" - " let a: [3]int = [700: int, 800: int, 900: int];\n" - " let i: inner;\n" - " i.n = 1;\n" - " let v: outer;\n" - " v.pi = &i;\n" - " v.pi.s = a[0:3];\n" - " if (i.s.len != 3) { return 1; };\n" - " if (i.s[2] != 900) { return 2; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - { "slicefield_chainread_2lvl", - "package main;\n" - "type sl = []int;\n" - "type sl2 = sl;\n" - "type inner = struct { s: sl2 };\n" - "type outer = struct { i: inner };\n" - "fn noise(x: int) int = {\n" - " return x * 7 + 3;\n" - "};\n" - "export fn main() i32 = {\n" - " let a: [3]int = [700: int, 800: int, 900: int];\n" - " let v: outer;\n" - " v.i.s = a[0:3];\n" - " let k = noise(9);\n" - " if (k != 66) { return 9; };\n" - " let w = v.i.s;\n" - " if (w.len != 3) { return 1; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - { "slicefield_ptrread_2lvl", - "package main;\n" - "type sl = []int;\n" - "type sl2 = sl;\n" - "type box = struct { s: sl2, n: int };\n" - "fn noise(x: int) int = {\n" - " return x * 7 + 3;\n" - "};\n" - "export fn main() i32 = {\n" - " let a: [3]int = [700: int, 800: int, 900: int];\n" - " let b: box;\n" - " b.s = a[0:3];\n" - " let p = &b;\n" - " let k = noise(9);\n" - " if (k != 66) { return 9; };\n" - " let w = p.s;\n" - " if (w.len != 3) { return 1; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - /* whole-field read into a local: cs runtime-correct post-chase - * (the clobbered-register r1b probe). The `let w = b.s` receive - * spine divergence noted at pristine 738d7f4 no longer - * reproduces at the F1-merged base, and ww's `w[i]` read (the - * task-#60 esz half) landed in F2a batch 1 — byte-id + 0/0 - * verified, graduated K_RUN. */ - { "slicefield_wholeread_2lvl", - "package main;\n" - "type sl = []int;\n" - "type sl2 = sl;\n" - "type box = struct { s: sl2, n: int };\n" - "fn noise(x: int) int = {\n" - " return x * 7 + 3;\n" - "};\n" - "export fn main() i32 = {\n" - " let a: [3]int = [700: int, 800: int, 900: int];\n" - " let b: box;\n" - " b.s = a[0:3];\n" - " let k = noise(9);\n" - " if (k != 66) { return 9; };\n" - " let w = b.s;\n" - " if (w.len != 3) { return 1; };\n" - " if (w[2] != 900) { return 2; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, /* graduated: #60 (F2a batch 1) */ - /* #73 GRADUATED (B5-c2): the tripwired single-peel field gates - * (indexed-elem store/read, ptr-chain read, heap fill, tuple-elem - * read, static emit) now chase the field type — the loud bound - * flipped to working 0/0 byte-id. Per-gate-arm rows live in - * 944_alias_cgen_b5_run. */ - { "slicefield_idx_tripwire_73", - "package main;\n" - "type sl = []int;\n" - "type sl2 = sl;\n" - "type box = struct { s: sl2, n: int };\n" - "export fn main() i32 = {\n" - " let a: [3]int = [700: int, 800: int, 900: int];\n" - " let xs: [2]box;\n" - " xs[0].s = a[0:3];\n" - " if (xs[0].s.len != 3) { return 1; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, /* graduated: #73 (B5-c2) */ - /* Values >255 break the esz=1 prefix-luck; the write-then-read - * pins the IMULQ stride on both the read and write spines. */ - { "idx_2level", - "package main;\n" - "type arr = [4]int;\n" - "type arr2 = arr;\n" - "export fn main() i32 = {\n" - " let a: arr2 = [1000: int, 2000: int, 3000: int, 4000: int];\n" - " if (a[2] != 3000) { return 1; };\n" - " a[1] = 9999;\n" - " if (a[1] != 9999) { return 2; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, /* graduated: #60 (F2a batch 1) */ - { "slice_2level", - "package main;\n" - "type sl = []int;\n" - "type sl2 = sl;\n" - "export fn main() i32 = {\n" - " let a: [4]int = [1000: int, 2000: int, 3000: int, 4000: int];\n" - " let s: sl2 = a[1:3];\n" - " if (s.len != 2) { return 1; };\n" - " if (s[0] != 2000) { return 2; };\n" - " s[1] = 7777;\n" - " if (a[2] != 7777) { return 3; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, /* graduated: #60 (F2a batch 1) */ - { "range_2level", - "package main;\n" - "type arr = [4]int;\n" - "type arr2 = arr;\n" - "export fn main() i32 = {\n" - " let a: arr2 = [1: int, 2: int, 3: int, 4: int];\n" - " let sum: int = 0;\n" - " for (let x .. a) {\n" - " sum = sum + x;\n" - " };\n" - " if (sum != 10) { return 1; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, /* graduated: #60 (F2a batch 1) */ - { "slice_of_alias_arg", - "package main;\n" - "type arr = [4]int;\n" - "type arr2 = arr;\n" - "fn sum(s: []int) int = {\n" - " let t: int = 0;\n" - " for (let x .. s) { t = t + x; };\n" - " return t;\n" - "};\n" - "export fn main() i32 = {\n" - " let a: arr2 = [1000: int, 2000: int, 3000: int, 4000: int];\n" - " let s = a[1:3];\n" - " if (s.len != 2) { return 1; };\n" - " if (s[1] != 3000) { return 2; };\n" - " if (sum(a[0:4]) != 10000) { return 3; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, /* graduated: #60 (F2a batch 1) */ - /* ---- ken-v3 leg: the acceptance align above opens 2-level - * float/str/slice aliases to the cgen KIND classifiers - * (cg_isfloat/type_isf32/fld_isfloat/type_isstr/type_isslice), - * whose single peel classed them scalar/INT — the f64-alias param - * would read the wrong register class (cs exit 1 SILENT, ww - * correct). The classifiers chase IN THIS SAME COMMIT so the - * widening never ships a loud->silent flip (rule 7; ken root- - * verify /tmp/ken_f1, his v3 row below). */ - { "float_alias_param_kenv3", - "package main;\n" - "type fa = fb;\n" - "type fb = f64;\n" - "fn take(x: fa) f64 = {\n" - " return x * 2.0;\n" - "};\n" - "export fn main() i32 = {\n" - " if (take(1.5) != 3.0) { return 1; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - { "float_alias_param", - "package main;\n" - "type f1t = f64;\n" - "type f2t = f1t;\n" - "fn half(x: f2t) f64 = {\n" - " return x / 2.0;\n" - "};\n" - "export fn main() i32 = {\n" - " let v: f2t = 5.0;\n" - " if (half(v) != 2.5) { return 1; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - { "str_alias_2level", - "package main;\n" - "type s1t = str;\n" - "type s2t = s1t;\n" - "fn taillen(s: s2t) int = {\n" - " return (s.len: int);\n" - "};\n" - "export fn main() i32 = {\n" - " let v: s2t = \"hello\";\n" - " if (v.len != 5) { return 1; };\n" - " if (taillen(v) != 5) { return 2; };\n" - " let w: s2t = v;\n" - " if (w.len != 5) { return 3; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - /* slice leg: cs classify fixed; the ww half of the indexed read - * (task-#60 esz family) landed in F2a batch 1. Values >255 - * break the esz=1 prefix-luck. */ - { "slice_alias_param", - "package main;\n" - "type b1 = []int;\n" - "type b2 = b1;\n" - "fn first(s: b2) int = {\n" - " return s[0];\n" - "};\n" - "export fn main() i32 = {\n" - " let a: [3]int = [1000: int, 2000: int, 3000: int];\n" - " let s: b2 = a[0:3];\n" - " if (first(s) != 1000) { return 1; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, /* graduated: #60 (F2a batch 1) */ - /* ---- task #61: cstage alias-NAMED struct PARAM classify. - * The single peel classified a 2-level-alias param SCALAR: caller - * pushed and callee spilled ONE eightbyte, fields read saved-BP/ - * return-address garbage (F0 m5_arg/m8b_arg1lit, cs exit 1 SILENT, - * ww correct). Fix = struct_arg_size/aggarg_size/struct_float_ - * class + the prologue classify chase. Values are distinct and the - * LAST field is always checked (multi-eightbyte exit-checked). */ - { "arg_2level_fwdref", - "package main;\n" - "type ali = base;\n" - "type base = struct { a: size, b: size, c: size };\n" - "fn take(s: ali) size = {\n" - " return s.a + s.b + s.c;\n" - "};\n" - "export fn main() i32 = {\n" - " let x: ali;\n" - " x.a = 4; x.b = 9; x.c = 13;\n" - " if (take(x) != 26) { return 1; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - { "arg_2level_litinit", - "package main;\n" - "type st = struct { a: size, b: size, c: size };\n" - "type row = st;\n" - "fn take(s: row) size = {\n" - " return s.a + s.b + s.c;\n" - "};\n" - "export fn main() i32 = {\n" - " let x: st = st { a = 4: size, b = 9: size, c = 13: size };\n" - " if (take(x) != 26) { return 1; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - /* 40B struct: 5 GP eightbytes through the aggarg (>16B) leg. */ - { "arg_2level_5word", - "package main;\n" - "type big = struct { a: size, b: size, c: size, d: size, e: size };\n" - "type big2 = big;\n" - "fn take(s: big2) size = {\n" - " return s.a + s.e;\n" - "};\n" - "export fn main() i32 = {\n" - " let v: big2;\n" - " v.a = 1000; v.b = 2; v.c = 3; v.d = 4; v.e = 5000;\n" - " if (take(v) != 6000) { return 1; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - /* f64-bearing 16B struct: the struct_float_class SSE leg. */ - { "arg_2level_floatclass", - "package main;\n" - "type fs = struct { x: f64, n: size };\n" - "type fs2 = fs;\n" - "fn take(s: fs2) size = {\n" - " if (s.x != 2.5) { return 99; };\n" - " return s.n;\n" - "};\n" - "export fn main() i32 = {\n" - " let v: fs2;\n" - " v.x = 2.5; v.n = 7;\n" - " if (take(v) != 7) { return 1; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - /* control: base-named param spelling stays green + byte-id. */ - { "arg_base_control", - "package main;\n" - "type base = struct { a: size, b: size, c: size };\n" - "fn take(s: base) size = {\n" - " return s.a + s.b + s.c;\n" - "};\n" - "export fn main() i32 = {\n" - " let x: base;\n" - " x.a = 4; x.b = 9; x.c = 13;\n" - " if (take(x) != 26) { return 1; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - /* ---- task #62 Layer-2: alias-NAMED struct as a UNION MEMBER. - * The widen store/push source classify fell past the struct arm - * to the scalar arm — word0-only payload (the banked rows - * /tmp/impl62r_layer2_rows.md; both-wrong-identical at normal - * decl order = gate-blind byte-id). cs half c138605 - * (cg_widen_tagged_store/push su chase); ww half F2a batch-2 c2 - * (rhsstructpayload -> structlookupchain) — K_RUN, byte-id. - * Values distinct per word; the LAST payload word is always - * checked. The RETURN-position leg stays both-stage divergent — - * cs cgreturn residual, task #89 (ww runtime-correct since c2; - * not pinned here until the cs half lands). */ - { "union_store_norm", /* banked row L2-1 (= F0 m5b_match1) */ - "package main;\n" - "type base = struct { a: size, b: size };\n" - "type ali = base;\n" - "export fn main() i32 = {\n" - " let x: ali;\n" - " x.a = 4; x.b = 9;\n" - " let v: (void | ali) = x;\n" - " match (v) {\n" - " case let s: ali => {\n" - " if (s.a != 4) { return 1; };\n" - " if (s.b != 9) { return 2; };\n" - " };\n" - " case void => { return 3; };\n" - " };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - { "union_store_fwd", /* banked row L2-2 (= F0 m5_match) */ - "package main;\n" - "type ali = base;\n" - "type base = struct { a: size, b: size };\n" - "export fn main() i32 = {\n" - " let x: ali;\n" - " x.a = 4; x.b = 9;\n" - " let v: (void | ali) = x;\n" - " match (v) {\n" - " case let s: ali => {\n" - " if (s.a != 4) { return 1; };\n" - " if (s.b != 9) { return 2; };\n" - " };\n" - " case void => { return 3; };\n" - " };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - { "union_store_3word", /* banked row L2-4: pins the width LOOP */ - "package main;\n" - "type base = struct { a: size, b: size, c: size };\n" - "type ali = base;\n" - "export fn main() i32 = {\n" - " let x: ali;\n" - " x.a = 4; x.b = 9; x.c = 3;\n" - " let v: (void | ali) = x;\n" - " match (v) {\n" - " case let s: ali => {\n" - " if (s.a != 4) { return 1; };\n" - " if (s.c != 3) { return 2; };\n" - " };\n" - " case void => { return 3; };\n" - " };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - { "union_push_arg", /* the cg_widen_tagged_push twin (F1 find) */ - "package main;\n" - "type base = struct { a: size, b: size };\n" - "type ali = base;\n" - "fn peek(v: (void | ali)) size = {\n" - " match (v) {\n" - " case let s: ali => { return s.b; };\n" - " case void => { return 0; };\n" - " };\n" - "};\n" - "export fn main() i32 = {\n" - " let x: ali;\n" - " x.a = 4; x.b = 9;\n" - " if (peek(x) != 9) { return 1; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - /* banked row L2-5: the m5b_match0 gold invariant — base spelling - * indistinguishable (ken oracle PART 1.7). */ - { "union_store_base_ctl", - "package main;\n" - "type base = struct { a: size, b: size, c: size };\n" - "export fn main() i32 = {\n" - " let x: base;\n" - " x.a = 4; x.b = 9; x.c = 3;\n" - " let v: (void | base) = x;\n" - " match (v) {\n" - " case let s: base => {\n" - " if (s.a != 4) { return 1; };\n" - " if (s.c != 3) { return 2; };\n" - " };\n" - " case void => { return 3; };\n" - " };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - /* ---- F2a batch-3 c3 (task #92, reviewer-B2 find): the same - * rhsstructpayload widen, sourced from a struct LITERAL instead - * of a local ident — the N_STRUCTLIT arm still did bare - * structlookup, so `ali{...}` into a union fell to the scalar - * widen arm (cs 0 / ww EXIT 1, byte-id NO, pre-existing on - * master at 486f7f8). Graduated by routing the arm through - * structlookupchain (entry gate widened to the literal's N_IDENT - * type-ref leaf — consumer census in the commit body). Values - * distinct per word, LAST word checked. The alias struct-LIT - * LET-INIT zero-fill (task #63) does NOT green at this site — - * probed post-c3, documented there, deliberately no row here. */ - { "union_slit_base_ctl", - "package main;\n" - "type base = struct { a: size, b: size };\n" - "export fn main() i32 = {\n" - " let v: (void | base) = base{a=4000, b=9000};\n" - " match (v) {\n" - " case let s: base => {\n" - " if (s.a != 4000) { return 1; };\n" - " if (s.b != 9000) { return 2; };\n" - " };\n" - " case void => { return 3; };\n" - " };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - { "union_slit_alias", - "package main;\n" - "type base = struct { a: size, b: size };\n" - "type ali = base;\n" - "export fn main() i32 = {\n" - " let v: (void | ali) = ali{a=4000, b=9000};\n" - " match (v) {\n" - " case let s: ali => {\n" - " if (s.a != 4000) { return 1; };\n" - " if (s.b != 9000) { return 2; };\n" - " };\n" - " case void => { return 3; };\n" - " };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - /* 2-level: the chain walk (structlookupchain's alias loop). */ - { "union_slit_alias2", - "package main;\n" - "type base = struct { a: size, b: size };\n" - "type ali = base;\n" - "type ali2 = ali;\n" - "export fn main() i32 = {\n" - " let v: (void | ali2) = ali2{a=4000, b=9000};\n" - " match (v) {\n" - " case let s: ali2 => {\n" - " if (s.a != 4000) { return 1; };\n" - " if (s.b != 9000) { return 2; };\n" - " };\n" - " case void => { return 3; };\n" - " };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - { "union_slit_order", - "package main;\n" - "export fn main() i32 = {\n" - " let v: (void | ali) = ali{a=4000, b=9000};\n" - " match (v) {\n" - " case let s: ali => {\n" - " if (s.a != 4000) { return 1; };\n" - " if (s.b != 9000) { return 2; };\n" - " };\n" - " case void => { return 3; };\n" - " };\n" - " return 0;\n" - "};\n" - "type ali = base;\n" - "type base = struct { a: size, b: size };\n", 0, K_RUN, NULL }, - /* ---- F2a batch-2 c3/B1: exprprimresolved's N_DOT base walk was - * a hand-rolled 2-peel — a 3-level alias base (or ptr-to-2-level) - * left the cast-source width unknowable on wwstage only, so the - * #33 identity clamp stayed emitted where cstage (castsrcprim, - * F1-chased) skipped it: runtime-correct both, byte-id NO. - * Graduated by the tichase walk; 1/2-level controls held all - * along (the 2-peel covered them by accident). */ - { "castprim_3lvl_base", - "package main;\n" - "type s1 = struct { f: u32 };\n" - "type s2 = s1;\n" - "type s3 = s2;\n" - "export fn main() i32 = {\n" - " let x: s3;\n" - " x.f = 70000;\n" - " let y: u64 = (x.f: u32): u64;\n" - " if (y != 70000) { return 1; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - { "castprim_ptr2lvl_base", - "package main;\n" - "type s1 = struct { f: u32 };\n" - "type s2 = s1;\n" - "export fn main() i32 = {\n" - " let x: s2;\n" - " x.f = 70000;\n" - " let p: *s2 = &x;\n" - " let y: u64 = (p.f: u32): u64;\n" - " if (y != 70000) { return 1; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - /* 2-level control (was already byte-id pre-c3; pins the accident - * out of existence). */ - { "castprim_2lvl_base_ctl", - "package main;\n" - "type s1 = struct { f: u32 };\n" - "type s2 = s1;\n" - "export fn main() i32 = {\n" - " let x: s2;\n" - " x.f = 70000;\n" - " let y: u64 = (x.f: u32): u64;\n" - " if (y != 70000) { return 1; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - /* ---- F2a batch-2 c4 (rob FINAL RULING (i)): tyassignableuntyped - * full-chase — STRUCTURAL alignment to cs type.c:369-385 / harec - * type_is_assignable; ZERO acceptance graduations in this commit - * (graduations ride task #90). Holds + controls pin the chase as - * behavior-neutral on every reachable shape; the tagged-dst rows - * are the #33 pins (drill semantics unchanged). */ - { "untyped_hold33_pin", /* (void|T) untyped-int init — #33 fixed - * behavior, tagged-dst drill HOLD */ - "package main;\n" - "export fn main() i32 = {\n" - " let mn: (void | size) = 5;\n" - " if (!(mn is size)) { return 1; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - { "untyped_tagdst_2lvl_hold", /* 2-level alias TAGGED dst holds */ - "package main;\n" - "type r1 = (void | size);\n" - "type r2 = r1;\n" - "export fn main() i32 = {\n" - " let v: r2 = 5;\n" - " if (!(v is size)) { return 1; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - { "untyped_str2lvl_ctl", /* masked twin: ww stamps the str - * literal CONCRETE (#14 cluster), the - * shape fallback rescues the tag — 0/0 - * all along; documents the rescue */ - "package main;\n" - "type sa1 = str;\n" - "type sa2 = sa1;\n" - "export fn main() i32 = {\n" - " let v: (void | sa2) = \"hi\";\n" - " if (!(v is sa2)) { return 1; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - { "untyped_int2lvl_ctl", /* typeisnum NAMED-recursion control */ - "package main;\n" - "type ia1 = i64;\n" - "type ia2 = ia1;\n" - "export fn main() i32 = {\n" - " let v: (void | ia2) = 7;\n" - " if (!(v is ia2)) { return 1; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - { "untyped_bool1lvl_ctl", /* 1 level: ww passes via the - * fallback's one peel — 0/0 observed */ - "package main;\n" - "type ba1 = bool;\n" - "export fn main() i32 = {\n" - " let v: (void | ba1) = true;\n" - " if (!(v is ba1)) { return 1; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - /* GRADUATED at F2a batch-4 c2 (route-trace case (b)): the - * pass-2 full chase alone took this 0/0 byte-id — ww's CONCRETE - * bool (the #90 stamp divergence, still open at c2) now matches - * the 2-level alias variant through the chased structural - * fallback, converging with cs's untyped-funnel route on the - * same tag. #90's stamp flip pins its own rows (c5). */ - { "untyped_bool2lvl_bound90", - "package main;\n" - "type bb1 = bool;\n" - "type bb2 = bb1;\n" - "export fn main() i32 = {\n" - " let v: (void | bb2) = true;\n" - " if (!(v is bb2)) { return 1; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - /* ---- F2a batch-4 c2: flatvariantidxt/cg_tag_for_variant pass-2 - * FULL CHASE, fused both stages (probe: v2_alias2 was exit 1/1 - * BOTH-WRONG-IDENTICAL pre-fix — the one-level pu unwrap missed - * every pass on a 2-level alias variant, tag 0 silent). v2_ctrl - * pins the #15 io-vtable consumer (1-level, held throughout); - * v2_ambig pins drew's >=2-candidate hard-error applied to the - * CHASED match set. */ - { "v2_ctrl", /* bare *T into 1-LEVEL named-ptr variant (io shape) */ - "package main;\n" - "type pc = *i64;\n" - "export fn main() i32 = {\n" - " let x: i64 = 7;\n" - " let v: (void | pc) = &x;\n" - " if (v is pc) { return 0; };\n" - " return 1;\n" - "};\n", 0, K_RUN, NULL }, - { "v2_alias2", /* bare *T into 2-LEVEL alias variant */ - "package main;\n" - "type pa = *i64;\n" - "type pb = pa;\n" - "export fn main() i32 = {\n" - " let x: i64 = 7;\n" - " let v: (void | pb) = &x;\n" - " if (v is pb) { return 0; };\n" - " return 1;\n" - "};\n", 0, K_RUN, NULL }, - { "v2_struct2", /* bare (anonymous-let) struct into 2-level alias - * variant. NOID: asm diverges on 3 pre-existing - * cglet zero-fill lines (cs XORQ+2 stores, ww none - * — task #81 class, runtime-correct both, ORTHOGONAL - * to the variant tag). Flip to K_RUN when the - * zero-fill divergence closes. The adjacent - * NAMED-source shape is task #95 (ken b4-oracle), - * out of this fix's set. */ - "package main;\n" - "type sa = struct { a: i64, };\n" - "type sb = sa;\n" - "export fn main() i32 = {\n" - " let s: struct { a: i64, } = sa{a=7};\n" - " let v: (void | sb) = s;\n" - " if (v is sb) { return 0; };\n" - " return 1;\n" - "};\n", 0, K_RUN_NOID, NULL }, - { "v2_ambig", /* bare source matching >=2 NAMED variants stays a - * hard error on the CHASED set (drew's proviso) */ - "package main;\n" - "type p1 = *i64;\n" - "type p2 = *i64;\n" - "export fn main() i32 = {\n" - " let x: i64 = 7;\n" - " let v: (void | p1 | p2) = &x;\n" - " if (v is p1) { return 0; };\n" - " return 1;\n" - "};\n", 0, K_BUILDERR, - "bare source structurally matches >=2 NAMED variants" }, - /* The RATIFIED acceptance-narrowing pin (FLAG-P1, kb4_v2_ambig2): - * 2-LEVEL twin variants. Pre-c2 the chase-less fallback matched - * NEITHER twin — the build ACCEPTED on both stages and ran a - * silent mis-tag (byte-identical, gate-blind). The chased set - * sees both twins structurally -> drew's >=2-candidate - * hard-error, BOTH stages. */ - { "v2_ambig2", - "package main;\n" - "type q1 = *i64;\n" - "type p1 = q1;\n" - "type q2 = *i64;\n" - "type p2 = q2;\n" - "export fn main() i32 = {\n" - " let x: i64 = 7;\n" - " let v: (void | p1 | p2) = &x;\n" - " if (v is p1) { return 0; };\n" - " return 1;\n" - "};\n", 0, K_BUILDERR, - "bare source structurally matches >=2 NAMED variants" }, - /* ---- F2a batch-4 c3: check.ww behavior pair (ww-only align-up; - * both cs twins already full-chase: spread check.c:755, &len/cap - * check.c:1198-1201). */ - { "sp_alias1", /* 1-level spread control — held throughout */ - "package main;\n" - "type inner = (i64 | str);\n" - "type outer = (...inner | void);\n" - "export fn main() i32 = {\n" - " let v: outer = 5: i64;\n" - " if (v is i64) { return 0; };\n" - " return 1;\n" - "};\n", 0, K_RUN, NULL }, - { "sp_alias2", /* 2-level-alias inner union spread into outer - * tagged: pre = runtime 0/0 BUT byte-DIVERGE (ww - * sized the box off the SURFACE member — $48 vs $32 - * frame); post = 0/0 byte-id (spliced). */ - "package main;\n" - "type inner = (i64 | str);\n" - "type inner2 = inner;\n" - "type outer = (...inner2 | void);\n" - "export fn main() i32 = {\n" - " let v: outer = 5: i64;\n" - " if (v is i64) { return 0; };\n" - " return 1;\n" - "};\n", 0, K_RUN, NULL }, - { "amplen_plain", /* &s.len plain []i64 base control */ - "package main;\n" - "export fn main() i32 = {\n" - " let s: []i64 = [1, 2, 3];\n" - " let p: *i64 = &s.len;\n" - " if (*p == 3) { return 0; };\n" - " return 1;\n" - "};\n", 0, K_RUN, NULL }, - /* &len/cap through alias bases (param route — the let-init - * spelling is blocked upstream by the #83-documented "let: not - * assignable" acceptance divergence): the c3-B2 chase aligns the - * CHECKER stamp to cs, but the ww cgen ADDRESS tail stays loud - * ("unsupported address-of shape") for ALL alias bases 1+ level — - * task #96 (ken b4-oracle), outside check.ww's grant. Rows - * graduate K_RUN when #96 lands. */ { "amplen1_bound96", "package main;\n" "type sl1 = []i64;\n" @@ -1074,8 +98,7 @@ static const struct row rows[] = { "export fn main() i32 = {\n" " let b: []i64 = [1, 2, 3];\n" " return check(b);\n" - "};\n", 0, K_RUN_CS_WWERR, - "unsupported address-of shape" }, /* ww: task #96 */ + "};\n", "unsupported address-of shape" }, /* ww: task #96 */ { "amplen2_bound96", "package main;\n" "type sl1 = []i64;\n" @@ -1088,8 +111,7 @@ static const struct row rows[] = { "export fn main() i32 = {\n" " let b: []i64 = [1, 2, 3];\n" " return check(b);\n" - "};\n", 0, K_RUN_CS_WWERR, - "unsupported address-of shape" }, /* ww: task #96 */ + "};\n", "unsupported address-of shape" }, /* ww: task #96 */ { "ampcap2_bound96", "package main;\n" "type sl1 = []i64;\n" @@ -1102,197 +124,9 @@ static const struct row rows[] = { "export fn main() i32 = {\n" " let b: []i64 = [1, 2, 3];\n" " return check(b);\n" - "};\n", 0, K_RUN_CS_WWERR, - "unsupported address-of shape" }, /* ww: task #96 */ - /* ---- F2a batch-4 c4 (#80): bare-binder N_FORRANGE over an - * alias-typed iterable — the binder type derivation read the - * scrutinee's type expr without dealiasing (N_TNAME missed the - * N_TSLICE/N_TARRAY tests), binder fell to the untyped fallback - * decl, `untyped_lit * rangevar` asserttyped-bailed on ww only - * (cs scope_define types the elem). Re-probed AFTER c1 per spec: - * still live (the chase set didn't cover this AST-keyed read). - * Tuple-destructure arm sibling FILED (task #97, double-masked). */ - { "rangevar_alias2", /* the #80 repro shape */ - "package main;\n" - "type slk = []int;\n" - "export fn main() i32 = {\n" - " let a: [4]int = [10: int, 20: int, 30: int, 40: int];\n" - " let t: slk = a[2:];\n" - " if (t.len != 2) { return 1; };\n" - " if (t.cap != 2) { return 2; };\n" - " let sum: int = 0;\n" - " for (let x .. t) { sum = sum + 0 * x + 1; };\n" - " if (sum != 2) { return 3; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - { "rangevar_plain_ctl", /* non-alias control — held throughout */ - "package main;\n" - "export fn main() i32 = {\n" - " let a: [4]int = [10: int, 20: int, 30: int, 40: int];\n" - " let t: []int = a[2:];\n" - " let sum: int = 0;\n" - " for (let x .. t) { sum = sum + 0 * x + 1; };\n" - " if (sum != 2) { return 3; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - /* BOUND expected-state row (#199α + #90): untyped literal into a - * NESTED-tagged alias-wrapped variant. cs CHECKER loud-rejects — - * the #199α ww-stricter no-transitive-drill rule (type.c:316-324); - * ww's node-keyed checker ACCEPTS and the binary runs exit 0 - * (observed post-c4; the harness has no cs-reject+ww-runs mode, - * so the ww half is pinned via #90's metadata, not here). The c4 - * pu-chase aligned the CGEN drill structure to cs; the acceptance - * gate is check.ww — batch-4 aligns ww down, then this row flips - * to K_BUILDERR (loud BOTH). */ - { "untyped_nestvar_bound", - "package main;\n" - "type inner = (i64 | str);\n" - "type inner2 = inner;\n" - "export fn main() i32 = {\n" - " let v: (void | inner2) = 7;\n" - " if (v is void) { return 1; };\n" - " return 0;\n" - "};\n", 0, K_BUILDERR_CS, "not assignable" }, - /* ---- task #71 (rob probe-ruled F1 enrollment): nested fields - * whose TYPES are aliases. The chained-dot store/read/addr-of - * walks single-peeled each hop, aborted on the alias, and fell - * to the generic PUSHQ/LEAQ/ADDQ/POPQ address spine — runtime- - * correct but byte-id NO vs wwstage's folded direct offsets. - * Chasing the walks converges cs onto the direct arm = ww's asm. - * Distinct values; the LAST field of the SECOND member checked. */ - { "nested_alias_field_norm", - "package main;\n" - "type fa = inner;\n" - "type inner = struct { a: size, b: size };\n" - "type outer = struct { x: fa, y: fa };\n" - "export fn main() i32 = {\n" - " let v: outer;\n" - " v.x.a = 4; v.x.b = 9;\n" - " v.y.a = 7; v.y.b = 3;\n" - " if (v.x.b != 9) { return 1; };\n" - " if (v.y.b != 3) { return 2; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - { "nested_alias_field_fwd", - "package main;\n" - "type outer = struct { x: fa, y: fa };\n" - "type fa = inner;\n" - "type inner = struct { a: size, b: size };\n" - "export fn main() i32 = {\n" - " let v: outer;\n" - " v.x.a = 4; v.x.b = 9;\n" - " v.y.a = 7; v.y.b = 3;\n" - " if (v.x.b != 9) { return 1; };\n" - " if (v.y.b != 3) { return 2; };\n" - " let pa = &v.y.b;\n" - " *pa = 11;\n" - " if (v.y.b != 11) { return 3; };\n" - " return 0;\n" - "};\n", 0, K_RUN, NULL }, - /* banked row L2-3 (`v as ali` readback) trips task #54's as-binding - * aggregate-init bound — LOUD both stages today; fold the row into - * #54's pin set on its fold (do not drop). Pinned here as the - * loud-both bound so a silent regression can't hide. */ - { "union_as_bound_54", - "package main;\n" - "type base = struct { a: size, b: size };\n" - "type ali = base;\n" - "export fn main() i32 = {\n" - " let x: ali;\n" - " x.a = 4; x.b = 9;\n" - " let v: (void | ali) = x;\n" - " if (!(v is ali)) { return 1; };\n" - " let w = v as ali;\n" - " if (w.b != 9) { return 2; };\n" - " return 0;\n" - "};\n", 0, K_BUILDERR, - "aggregate init from unhandled rhs shape" }, + "};\n", "unsupported address-of shape" }, /* ww: task #96 */ }; -static int -run_driver(const char *driver, const struct row *r, int i) -{ - char tmpdir[96], src[160], errf[160], outbin[160], cmd[1024], rmcmd[200]; - snprintf(tmpdir, sizeof tmpdir, "/tmp/aac_%d_d_%d", getpid(), i); - mkdir(tmpdir, 0755); - snprintf(src, sizeof src, "%s/aac_%d_%d.ww", tmpdir, getpid(), i); - snprintf(errf, sizeof errf, "%s/err", tmpdir); - snprintf(outbin, sizeof outbin, "%s/aac_%d_%d", tmpdir, getpid(), i); - snprintf(rmcmd, sizeof rmcmd, "rm -rf %s", tmpdir); - - FILE *f = fopen(src, "wb"); - if (!f) { runwait(rmcmd); return -1; } - fputs(r->src, f); - fclose(f); - - /* #8: -o pins binary + .sepwork scratch under tmpdir; rm -rf on - * every exit path removes the now-non-empty dir. */ - snprintf(cmd, sizeof cmd, - "timeout 20 %s build -o %s %s >/dev/null 2>%s", - driver, outbin, src, errf); - int brc = runwait(cmd); - if (r->kind == K_BUILDERR || r->kind == K_BUILDERR_CS) { - int ok = (brc != 0) - && (r->experr == NULL || errlog_has(errf, r->experr)); - if (!ok) - fprintf(stderr, "row[%s]: %s expected loud builderr " - "\"%s\" (brc=%d)\n", r->label, driver, - r->experr ? r->experr : "", brc); - runwait(rmcmd); - return ok ? 0 : 1; - } - if (brc != 0) { - fprintf(stderr, "row[%s]: build via %s failed\n", - r->label, driver); - runwait(rmcmd); - return -1; - } - - int got = runwait(outbin); - - runwait(rmcmd); - if (got != r->want) { - fprintf(stderr, "row[%s]: %s exit %d, want %d\n", - r->label, driver, got, r->want); - return 1; - } - return 0; -} - -static int -asm_byte_identical(const char *bin, const struct row *r, int i) -{ - char src[96], cs[96], ws[96], cmd[1024]; - snprintf(src, sizeof src, "/tmp/aac_asm_%d_%d.ww", getpid(), i); - snprintf(cs, sizeof cs, "/tmp/aac_asm_%d_%d_c.s", getpid(), i); - snprintf(ws, sizeof ws, "/tmp/aac_asm_%d_%d_w.s", getpid(), i); - - FILE *f = fopen(src, "wb"); - if (!f) return -1; - fputs(r->src, f); - fclose(f); - - snprintf(cmd, sizeof cmd, "%s/w6c -o %s %s 2>/dev/null", bin, cs, src); - if (runwait(cmd) != 0) { - fprintf(stderr, "row[%s]: w6c errored\n", r->label); - unlink(src); - return -1; - } - snprintf(cmd, sizeof cmd, "%s/w6c_ww -o %s %s 2>/dev/null", - bin, ws, src); - if (runwait(cmd) != 0) { - fprintf(stderr, "row[%s]: w6c_ww errored\n", r->label); - unlink(src); unlink(cs); - return -1; - } - int rc = slurp_eq(cs, ws); - if (rc != 0) - fprintf(stderr, "row[%s]: cstage vs wwstage asm differs\n", - r->label); - unlink(src); unlink(cs); unlink(ws); - return rc; -} - int main(void) { @@ -1306,49 +140,16 @@ 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 (run_driver(cdrv, &rows[i], i) != 0) fail++; - } - if (access(wdrv, X_OK) == 0) { - for (int i = 0; i < n; i++) { - if (rows[i].kind == K_RUN_CS - || rows[i].kind == K_BUILDERR_CS) - continue; /* K_RUN_NOID: ww half RUNS */ - if (rows[i].kind == K_RUN_CS_WWERR) { - /* LOUD-HOLD: the parked ww leg must keep - * failing LOUD with experr — a silent ww - * accept-and-run is the regression this - * row exists to catch (cite at row). */ - struct row tmp = rows[i]; - tmp.kind = K_BUILDERR; - total++; - if (run_driver(wdrv, &tmp, i) != 0) fail++; - continue; - } - total++; - if (run_driver(wdrv, &rows[i], i) != 0) fail++; - } - for (int i = 0; i < n; i++) { - if (rows[i].kind != K_RUN) - continue; - total++; - if (asm_byte_identical(bin, &rows[i], i) != 0) fail++; - } - } + int fail = 0; + for (int i = 0; i < n; i++) + if (run_row(bin, rows[i].label, rows[i].src, rows[i].wwerr, i) != 0) + fail++; if (fail) { - fprintf(stderr, "alias_accept: %d/%d checks failed\n", - fail, total); + fprintf(stderr, "alias_accept (slim): %d/%d rows failed\n", fail, n); return 1; } - printf("alias_accept: %d/%d ok\n", total, total); + printf("alias_accept (slim): %d/%d ok\n", n, n); return 0; } diff --git a/test/wcc/944_alias_cgen_b5_run.c b/test/wcc/944_alias_cgen_b5_run.c index d14b54a4..17f34639 100644 --- a/test/wcc/944_alias_cgen_b5_run.c +++ b/test/wcc/944_alias_cgen_b5_run.c @@ -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 #include -#include #include #include #include @@ -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; } diff --git a/test/wcc/944_alias_cgen_b6_run.c b/test/wcc/944_alias_cgen_b6_run.c index 0e5af5bb..aabb2d31 100644 --- a/test/wcc/944_alias_cgen_b6_run.c +++ b/test/wcc/944_alias_cgen_b6_run.c @@ -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 #include @@ -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; } diff --git a/test/wcc/944_alias_decl_order_size_run.c b/test/wcc/944_alias_decl_order_size_run.c deleted file mode 100644 index be90315f..00000000 --- a/test/wcc/944_alias_decl_order_size_run.c +++ /dev/null @@ -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 -#include -#include -#include -#include -#include - -static int -runwait(const char *cmd) -{ - int rc = system(cmd); - if (rc == -1) return -1; - if (WIFEXITED(rc)) return WEXITSTATUS(rc); - return -1; -} - -static int -slurp_eq(const char *a, const char *b) -{ - FILE *fa = fopen(a, "rb"); - FILE *fb = fopen(b, "rb"); - if (!fa || !fb) { if (fa) fclose(fa); if (fb) fclose(fb); return -1; } - int rc = 0; - for (;;) { - int ca = fgetc(fa), cb = fgetc(fb); - if (ca != cb) { rc = -1; break; } - if (ca == EOF) break; - } - fclose(fa); fclose(fb); - return rc; -} - -#define K_RUN 0 /* build+run both drivers, exit==want, + 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; -} diff --git a/test/wcc/944_alias_emit_b7_run.c b/test/wcc/944_alias_emit_b7_run.c index 42a98032..4aa17801 100644 --- a/test/wcc/944_alias_emit_b7_run.c +++ b/test/wcc/944_alias_emit_b7_run.c @@ -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 #include @@ -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; } diff --git a/test/wcc/944_alias_global_decl_run.c b/test/wcc/944_alias_global_decl_run.c deleted file mode 100644 index 10b3249a..00000000 --- a/test/wcc/944_alias_global_decl_run.c +++ /dev/null @@ -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 -#include -#include -#include -#include - -static int -runwait(const char *cmd) -{ - int rc = system(cmd); - if (rc == -1) return -1; - if (WIFEXITED(rc)) return WEXITSTATUS(rc); - return -1; -} - -static int -slurp_eq(const char *a, const char *b) -{ - FILE *fa = fopen(a, "rb"); - FILE *fb = fopen(b, "rb"); - if (!fa || !fb) { if (fa) fclose(fa); if (fb) fclose(fb); return -1; } - int rc = 0; - for (;;) { - int ca = fgetc(fa), cb = fgetc(fb); - if (ca != cb) { rc = -1; break; } - if (ca == EOF) break; - } - fclose(fa); fclose(fb); - return rc; -} - -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; -} diff --git a/test/wcc/944_alias_idx_family_run.c b/test/wcc/944_alias_idx_family_run.c deleted file mode 100644 index d67f7000..00000000 --- a/test/wcc/944_alias_idx_family_run.c +++ /dev/null @@ -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 -#include -#include -#include -#include - -static int -runwait(const char *cmd) -{ - int rc = system(cmd); - if (rc == -1) return -1; - if (WIFEXITED(rc)) return WEXITSTATUS(rc); - return -1; -} - -static int -slurp_eq(const char *a, const char *b) -{ - FILE *fa = fopen(a, "rb"); - FILE *fb = fopen(b, "rb"); - if (!fa || !fb) { if (fa) fclose(fa); if (fb) fclose(fb); return -1; } - int rc = 0; - for (;;) { - int ca = fgetc(fa), cb = fgetc(fb); - if (ca != cb) { rc = -1; break; } - if (ca == EOF) break; - } - fclose(fa); fclose(fb); - return rc; -} - -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; -} diff --git a/test/wcc/944_alias_structlit_init_run.c b/test/wcc/944_alias_structlit_init_run.c deleted file mode 100644 index 42d905d3..00000000 --- a/test/wcc/944_alias_structlit_init_run.c +++ /dev/null @@ -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 -#include -#include -#include -#include - -static int -runwait(const char *cmd) -{ - int rc = system(cmd); - if (rc == -1) return -1; - if (WIFEXITED(rc)) return WEXITSTATUS(rc); - return -1; -} - -static int -slurp_eq(const char *a, const char *b) -{ - FILE *fa = fopen(a, "rb"); - FILE *fb = fopen(b, "rb"); - if (!fa || !fb) { if (fa) fclose(fa); if (fb) fclose(fb); return -1; } - int rc = 0; - for (;;) { - int ca = fgetc(fa), cb = fgetc(fb); - if (ca != cb) { rc = -1; break; } - if (ca == EOF) break; - } - fclose(fa); fclose(fb); - return rc; -} - -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; -} diff --git a/test/wcc/data/alias_assert_bool/case.ww b/test/wcc/data/alias_assert_bool/case.ww new file mode 100644 index 00000000..22abae5d --- /dev/null +++ b/test/wcc/data/alias_assert_bool/case.ww @@ -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; +}; diff --git a/test/wcc/data/alias_binop_vs_alias/case.ww b/test/wcc/data/alias_binop_vs_alias/case.ww new file mode 100644 index 00000000..04982f17 --- /dev/null +++ b/test/wcc/data/alias_binop_vs_alias/case.ww @@ -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; +}; diff --git a/test/wcc/data/alias_cycle_alias/case.ww b/test/wcc/data/alias_cycle_alias/case.ww new file mode 100644 index 00000000..b5faff7b --- /dev/null +++ b/test/wcc/data/alias_cycle_alias/case.ww @@ -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; +}; diff --git a/test/wcc/data/alias_cycle_self/case.ww b/test/wcc/data/alias_cycle_self/case.ww new file mode 100644 index 00000000..235d3461 --- /dev/null +++ b/test/wcc/data/alias_cycle_self/case.ww @@ -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; +}; diff --git a/test/wcc/data/alias_cycle_struct/case.ww b/test/wcc/data/alias_cycle_struct/case.ww new file mode 100644 index 00000000..004b8625 --- /dev/null +++ b/test/wcc/data/alias_cycle_struct/case.ww @@ -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; +}; diff --git a/test/wcc/data/alias_fill0_ctl/case.ww b/test/wcc/data/alias_fill0_ctl/case.ww new file mode 100644 index 00000000..102b9f98 --- /dev/null +++ b/test/wcc/data/alias_fill0_ctl/case.ww @@ -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; +}; diff --git a/test/wcc/data/alias_fill2_loud/case.ww b/test/wcc/data/alias_fill2_loud/case.ww new file mode 100644 index 00000000..308f38dc --- /dev/null +++ b/test/wcc/data/alias_fill2_loud/case.ww @@ -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; +}; diff --git a/test/wcc/data/alias_fsarg0_loud/case.ww b/test/wcc/data/alias_fsarg0_loud/case.ww new file mode 100644 index 00000000..ee0a4617 --- /dev/null +++ b/test/wcc/data/alias_fsarg0_loud/case.ww @@ -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; +}; diff --git a/test/wcc/data/alias_g73_static_str/case.ww b/test/wcc/data/alias_g73_static_str/case.ww new file mode 100644 index 00000000..16aaaf98 --- /dev/null +++ b/test/wcc/data/alias_g73_static_str/case.ww @@ -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; +}; diff --git a/test/wcc/data/alias_slcslc/case.ww b/test/wcc/data/alias_slcslc/case.ww new file mode 100644 index 00000000..7d67c724 --- /dev/null +++ b/test/wcc/data/alias_slcslc/case.ww @@ -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; +}; diff --git a/test/wcc/data/alias_slcstr_plain/case.ww b/test/wcc/data/alias_slcstr_plain/case.ww new file mode 100644 index 00000000..391c9e74 --- /dev/null +++ b/test/wcc/data/alias_slcstr_plain/case.ww @@ -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; +}; diff --git a/test/wcc/data/alias_try_loud_38b/case.ww b/test/wcc/data/alias_try_loud_38b/case.ww new file mode 100644 index 00000000..fae7b878 --- /dev/null +++ b/test/wcc/data/alias_try_loud_38b/case.ww @@ -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; +}; diff --git a/test/wcc/data/alias_union_as_bound/case.ww b/test/wcc/data/alias_union_as_bound/case.ww new file mode 100644 index 00000000..49bbc6cb --- /dev/null +++ b/test/wcc/data/alias_union_as_bound/case.ww @@ -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; +}; diff --git a/test/wcc/data/alias_untyped_nestvar/case.ww b/test/wcc/data/alias_untyped_nestvar/case.ww new file mode 100644 index 00000000..80847ca2 --- /dev/null +++ b/test/wcc/data/alias_untyped_nestvar/case.ww @@ -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; +}; diff --git a/test/wcc/data/alias_v2_ambig/case.ww b/test/wcc/data/alias_v2_ambig/case.ww new file mode 100644 index 00000000..bb86a33f --- /dev/null +++ b/test/wcc/data/alias_v2_ambig/case.ww @@ -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; +}; diff --git a/test/wcc/data/alias_v2_ambig2/case.ww b/test/wcc/data/alias_v2_ambig2/case.ww new file mode 100644 index 00000000..cf562756 --- /dev/null +++ b/test/wcc/data/alias_v2_ambig2/case.ww @@ -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; +};