test: migrate Fam9 match/tagged value tests to @test (#5-C5)
fold-2 chunk C5 (drew's Fam8-13 plan), the highest-risk chunk: 21 match/tagged value-row C drivers re-homed. 20 -> test/lang/*_test.ww @test row-tables + 12 runww //ww:error carriers (both stages reject). The global-tag cluster (globtag*/globstructwiden/taggedderefstore/...), which sits on the #15/#17 global-ptr fix, was empirically probed byte-id CLEAN -- the predicted hotspot surfaced ZERO fresh cs!=ww. Carves: variant_chain_b95 #81 -> _runonly (genuinely diverges at HEAD); callret_bound277 #277 -> slim C pin (cs-runs/ww-rejects), mutation-gated. 929_tagged_memarg kept whole (SSE-ABI asm conformance). 19 drivers deleted, 944_variant_chain slimmed to the #277 pin. The match-on-tagged-struct-field divergence (former #26) probed RESOLVED for all its cited shapes (938 voidstr_field/recursion_torture, tagnorm dedup_match all byte-id cs==ww + value-correct) -- closed no-reproducer-at-HEAD, attribution to #15/#17 INFERRED. Those rows migrate as normal byte-id @test and serve as the REGRESSION SENTINEL for the inferred close (a resurgence trips the gate). LANGBYTEID floor 93->113; test count 374->355 (19 deleted; 929 + 944_variant_chain kept). do-not-auto-batch (926_tagscr/940_global_sret/940_str_forrange) untouched.
This commit is contained in:
29
test/lang/globstructwiden_test.ww
Normal file
29
test/lang/globstructwiden_test.ww
Normal file
@@ -0,0 +1,29 @@
|
||||
// globstructwiden_test — F8-c7 (#50, #263): widening a module-GLOBAL struct
|
||||
// ident into a tagged union must copy the full payload into the box, not just
|
||||
// word0. Was a cat-A both-stage-wrong, now CLOSED both stages (.s byte-id).
|
||||
// Migrated from test/wcc/989_globstructwiden_run.c (K_RUN value rows). The
|
||||
// global lives at module scope so the widen exercises the g(SB) source arm.
|
||||
|
||||
package globstructwiden_test;
|
||||
|
||||
type pt = struct { a: i64, b: i64 };
|
||||
type tri = struct { a: i64, b: i64, c: i64 };
|
||||
|
||||
let gp16: pt = pt { a = 5, b = 6 };
|
||||
let gp24: tri = tri { a = 5, b = 6, c = 7 };
|
||||
|
||||
@test fn widen_16() void = {
|
||||
let x: (pt | str) = gp16;
|
||||
match (x) {
|
||||
case let q: pt => { assert(q.a == 5 && q.b == 6); };
|
||||
case str => { assert(false); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn widen_24() void = {
|
||||
let x: (tri | str) = gp24;
|
||||
match (x) {
|
||||
case let q: tri => { assert(q.a == 5 && q.b == 6 && q.c == 7); };
|
||||
case str => { assert(false); };
|
||||
};
|
||||
};
|
||||
30
test/lang/globtagisas_test.ww
Normal file
30
test/lang/globtagisas_test.ww
Normal file
@@ -0,0 +1,30 @@
|
||||
// globtagisas_test — F8-c3 (#18) + #46: `is`/`as` on a module-GLOBAL tagged-
|
||||
// union ident must read tag/payload from g(SB), not the saved-BP word. The `is`
|
||||
// half was align-UP (ww read 0(BP)); the `as` half was #263 both-wrong (cstage
|
||||
// spilled uninitialized DX). Both CLOSED, .s byte-id. Migrated from
|
||||
// test/wcc/989_globtagisas_run.c (K_RUN value rows). Globals kept at module
|
||||
// scope so the read fires the g(SB) path.
|
||||
|
||||
package globtagisas_test;
|
||||
|
||||
let g_is: (i64 | bool) = 5;
|
||||
let g_asi: (i64 | bool) = 42;
|
||||
let g_ass: (str | i64) = "hello";
|
||||
|
||||
@test fn is_match() void = {
|
||||
assert(g_is is i64);
|
||||
};
|
||||
|
||||
@test fn is_nomatch() void = {
|
||||
assert(!(g_is is bool));
|
||||
};
|
||||
|
||||
@test fn as_i64() void = {
|
||||
let x: i64 = g_asi as i64;
|
||||
assert(x == 42);
|
||||
};
|
||||
|
||||
@test fn as_str() void = {
|
||||
let s: str = g_ass as str;
|
||||
assert(len(s) == 5);
|
||||
};
|
||||
34
test/lang/globtagreassign_test.ww
Normal file
34
test/lang/globtagreassign_test.ww
Normal file
@@ -0,0 +1,34 @@
|
||||
// globtagreassign_test — reassigning a module-GLOBAL tagged-union stores the
|
||||
// full box at g(SB), not just the tag word. Migrated from
|
||||
// test/wcc/989_globtagreassign_run.c (K_RUN value rows, cs==ww). Globals kept
|
||||
// at module scope; each @test reassigns then matches.
|
||||
|
||||
package globtagreassign_test;
|
||||
|
||||
let g_i64: (i64 | void) = 0;
|
||||
let g_str: (str | i64) = 0;
|
||||
let g_union: (i64 | bool) = 0;
|
||||
|
||||
@test fn reassign_i64() void = {
|
||||
g_i64 = 7;
|
||||
match (g_i64) {
|
||||
case let n: i64 => { assert(n == 7); };
|
||||
case void => { assert(false); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn reassign_str() void = {
|
||||
g_str = "hello";
|
||||
match (g_str) {
|
||||
case let s: str => { assert(len(s) == 5); };
|
||||
case i64 => { assert(false); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn reassign_union() void = {
|
||||
g_union = 5;
|
||||
match (g_union) {
|
||||
case let n: i64 => { assert(n == 5); };
|
||||
case bool => { assert(false); };
|
||||
};
|
||||
};
|
||||
37
test/lang/globtagwiden_test.ww
Normal file
37
test/lang/globtagwiden_test.ww
Normal file
@@ -0,0 +1,37 @@
|
||||
// globtagwiden_test — F8-c8 (#51, #263): widening a module-GLOBAL tagged-union
|
||||
// ident into a wider union must copy gi's whole box as the nested payload, not
|
||||
// store its tag as the payload. CLOSED both stages, .s byte-id. Migrated from
|
||||
// test/wcc/989_globtagwiden_run.c (value rows). Globals kept at module scope.
|
||||
|
||||
package globtagwiden_test;
|
||||
|
||||
type inner = (i64 | bool);
|
||||
|
||||
let gi47: inner = 47;
|
||||
let gi99: inner = 99;
|
||||
|
||||
@test fn nest_47() void = {
|
||||
let x: (inner | str) = gi47;
|
||||
match (x) {
|
||||
case let n: inner => {
|
||||
match (n) {
|
||||
case let v: i64 => { assert(v == 47); };
|
||||
case bool => { assert(false); };
|
||||
};
|
||||
};
|
||||
case str => { assert(false); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn nest_99() void = {
|
||||
let x: (inner | str) = gi99;
|
||||
match (x) {
|
||||
case let n: inner => {
|
||||
match (n) {
|
||||
case let v: i64 => { assert(v == 99); };
|
||||
case bool => { assert(false); };
|
||||
};
|
||||
};
|
||||
case str => { assert(false); };
|
||||
};
|
||||
};
|
||||
52
test/lang/idx_tagged_field_test.ww
Normal file
52
test/lang/idx_tagged_field_test.ww
Normal file
@@ -0,0 +1,52 @@
|
||||
// idx_tagged_field_test — xs[i].f tagged-field read (const/var index, 2-tag
|
||||
// union) and assign-back through a pointer. Migrated from
|
||||
// test/wcc/944_idx_tagged_field_run.c (value rows; the C driver asserted cs==ww
|
||||
// .s). The >32B / multi-word / float-payload arms LOUD-STOP (#58) and live as
|
||||
// runww //ww:error carriers (test/wcc/data/idxtagfield_*); #114 graduates them.
|
||||
|
||||
package idx_tagged_field_test;
|
||||
|
||||
type opt = (void | size);
|
||||
type opt3 = (void | bool | size);
|
||||
type row = struct { id: int, m: opt };
|
||||
type row3 = struct { id: int, m: opt3 };
|
||||
|
||||
@test fn const_read() void = {
|
||||
let xs: [2]row = [
|
||||
row { id = 1, m = 7: size },
|
||||
row { id = 2, m = 8: size },
|
||||
];
|
||||
let v: size = xs[0].m as size;
|
||||
assert(v == 7);
|
||||
};
|
||||
|
||||
@test fn var_read() void = {
|
||||
let xs: [2]row = [
|
||||
row { id = 1, m = 7: size },
|
||||
row { id = 2, m = 8: size },
|
||||
];
|
||||
let i: size = 1;
|
||||
let v: size = xs[i].m as size;
|
||||
assert(v == 8);
|
||||
};
|
||||
|
||||
@test fn tag2_read() void = {
|
||||
let xs: [2]row3 = [
|
||||
row3 { id = 1, m = 5: size },
|
||||
row3 { id = 2, m = 9: size },
|
||||
];
|
||||
let i: size = 1;
|
||||
let v: size = xs[i].m as size;
|
||||
assert(v == 9);
|
||||
};
|
||||
|
||||
@test fn assign_back() void = {
|
||||
let xs: [2]row = [
|
||||
row { id = 1, m = 99: size },
|
||||
row { id = 2, m = 2: size },
|
||||
];
|
||||
xs[0].m = 8: size;
|
||||
let p: *row = &xs[0];
|
||||
let v: size = p.m as size;
|
||||
assert(v == 8);
|
||||
};
|
||||
90
test/lang/is_nonident_test.ww
Normal file
90
test/lang/is_nonident_test.ww
Normal file
@@ -0,0 +1,90 @@
|
||||
// is_nonident_test — `e is T` on non-ident scrutinees (indexed, dot-field,
|
||||
// call-result, slice-variant, nullable (*T|void) on dot-field and ident). Each
|
||||
// pins both polarities. Migrated from test/wcc/927_is_nonident_run.c (value
|
||||
// rows; the C driver already asserted cs==ww .s, so byte-id holds).
|
||||
|
||||
package is_nonident_test;
|
||||
|
||||
type p48 = struct { a: i64, b: i64, c: i64, d: i64, e: i64, f: i64 };
|
||||
type small = (p48 | bool);
|
||||
type holder = struct { v: small, k: i64 };
|
||||
|
||||
type val = (i64 | bool);
|
||||
type valslice = (i64 | []u8);
|
||||
|
||||
type t = struct { a: i64 };
|
||||
type maybe = (*t | void);
|
||||
type nholder = struct { m: maybe, k: i64 };
|
||||
|
||||
fn mk(flag: bool) val = {
|
||||
if (flag) {
|
||||
let b: bool = true;
|
||||
return b;
|
||||
};
|
||||
let n: i64 = 7;
|
||||
return n;
|
||||
};
|
||||
|
||||
@test fn indexed() void = {
|
||||
let xs: []small;
|
||||
let b: bool = true;
|
||||
let v: small = b;
|
||||
append(xs, v);
|
||||
assert(xs.len != 0 && xs[xs.len - 1] is bool);
|
||||
assert(!(xs[xs.len - 1] is p48));
|
||||
assert(xs[0] is bool);
|
||||
};
|
||||
|
||||
@test fn dot_field() void = {
|
||||
let b: bool = true;
|
||||
let h: holder = holder { v = b, k = 5 };
|
||||
assert(h.v is bool);
|
||||
assert(!(h.v is p48));
|
||||
};
|
||||
|
||||
@test fn call_result() void = {
|
||||
assert(mk(true) is bool);
|
||||
assert(mk(false) is i64);
|
||||
assert(!(mk(true) is i64));
|
||||
};
|
||||
|
||||
@test fn slice_variant_indexed() void = {
|
||||
let xs: []valslice;
|
||||
let buf: [2]u8 = [1u8, 2u8];
|
||||
let s: []u8 = buf[0:2];
|
||||
let v: valslice = s;
|
||||
append(xs, v);
|
||||
let n: i64 = 5;
|
||||
let w: valslice = n;
|
||||
append(xs, w);
|
||||
assert(xs[0] is []u8);
|
||||
assert(xs[1] is i64);
|
||||
assert(!(xs[0] is i64));
|
||||
};
|
||||
|
||||
@test fn nullable_dot_field() void = {
|
||||
let v: t = t { a = 5 };
|
||||
let h: nholder = nholder { m = &v, k = 1 };
|
||||
assert(h.m is *t);
|
||||
assert(!(h.m is void));
|
||||
let h2: nholder = nholder { m = void, k = 2 };
|
||||
assert(!(h2.m is *t));
|
||||
assert(h2.m is void);
|
||||
};
|
||||
|
||||
@test fn nullable_ident() void = {
|
||||
let v: t = t { a = 5 };
|
||||
let m: maybe = &v;
|
||||
assert(m is *t);
|
||||
assert(!(m is void));
|
||||
let m2: maybe = void;
|
||||
assert(!(m2 is *t));
|
||||
assert(m2 is void);
|
||||
};
|
||||
|
||||
@test fn ident_control() void = {
|
||||
let b: bool = true;
|
||||
let v: val = b;
|
||||
assert(v is bool);
|
||||
assert(!(v is i64));
|
||||
};
|
||||
102
test/lang/match_nonident_idx_test.ww
Normal file
102
test/lang/match_nonident_idx_test.ww
Normal file
@@ -0,0 +1,102 @@
|
||||
// match_nonident_idx_test — match on an N_INDEX scrutinee whose base is a
|
||||
// non-ident (struct-field slice, chained-dot slice, 56B-slot regex-inst union),
|
||||
// plus ident/ident-base controls. Pins arm-order independence and the stamped-
|
||||
// carrier resolve at any base depth. Migrated from
|
||||
// test/wcc/928_match_nonident_idx_run.c (value rows; C driver asserted cs==ww .s).
|
||||
|
||||
package match_nonident_idx_test;
|
||||
|
||||
type va = void;
|
||||
type vb = bool;
|
||||
type vc = size;
|
||||
type tu = (va | vb | vc);
|
||||
|
||||
type holder = struct { xs: []tu, n: size };
|
||||
type inner = struct { xs: []tu, k: size };
|
||||
type outer = struct { in_: inner, n: size };
|
||||
|
||||
type big = struct { a: i64, b: i64, c: i64, d: i64, e: i64, f: i64 };
|
||||
type ilit = struct { r: i64 };
|
||||
type imatch = void;
|
||||
type inst = (big | ilit | imatch);
|
||||
type re = struct { insts: []inst, n: i64 };
|
||||
|
||||
@test fn field_slice_idx() void = {
|
||||
let sl: []tu = [(true: vb), ((7: size): vc)];
|
||||
let h: holder;
|
||||
h.xs = sl;
|
||||
h.n = 2;
|
||||
match (h.xs[0]) {
|
||||
case let b: vb => { assert(b: bool); };
|
||||
case => { assert(false); };
|
||||
};
|
||||
match (h.xs[1]) {
|
||||
case let s: vc => { assert((s: size) == 7); };
|
||||
case => { assert(false); };
|
||||
};
|
||||
match (h.xs[0]) {
|
||||
case va => { assert(false); };
|
||||
case let b: vb => { assert(b: bool); };
|
||||
case vc => { assert(false); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn regex_inst_56b() void = {
|
||||
let sl: []inst;
|
||||
let l: ilit = ilit { r = 65 };
|
||||
let v: inst = l;
|
||||
append(sl, v);
|
||||
let m: inst = void: imatch;
|
||||
append(sl, m);
|
||||
let r: re;
|
||||
r.insts = sl;
|
||||
r.n = 2;
|
||||
match (r.insts[0]) {
|
||||
case let x: ilit => { assert(x.r == 65); };
|
||||
case => { assert(false); };
|
||||
};
|
||||
match (r.insts[1]) {
|
||||
case imatch => { };
|
||||
case => { assert(false); };
|
||||
};
|
||||
match (r.insts[0]) {
|
||||
case big => { assert(false); };
|
||||
case let x: ilit => { assert(x.r == 65); };
|
||||
case imatch => { assert(false); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn dot_depth_idx() void = {
|
||||
let sl: []tu = [(true: vb), ((9: size): vc)];
|
||||
let o: outer;
|
||||
o.in_.xs = sl;
|
||||
o.in_.k = 1;
|
||||
o.n = 2;
|
||||
match (o.in_.xs[0]) {
|
||||
case let b: vb => { assert(b: bool); };
|
||||
case => { assert(false); };
|
||||
};
|
||||
match (o.in_.xs[1]) {
|
||||
case va => { assert(false); };
|
||||
case let s: vc => { assert((s: size) == 9); };
|
||||
case vb => { assert(false); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn ident_and_identbase_controls() void = {
|
||||
let v: tu = (true: vb);
|
||||
match (v) {
|
||||
case let b: vb => { assert(b: bool); };
|
||||
case => { assert(false); };
|
||||
};
|
||||
let arr: [2]tu = [(true: vb), ((7: size): vc)];
|
||||
match (arr[1]) {
|
||||
case let s: vc => { assert((s: size) == 7); };
|
||||
case => { assert(false); };
|
||||
};
|
||||
let sl: []tu = [(true: vb), ((7: size): vc)];
|
||||
match (sl[0]) {
|
||||
case let b: vb => { assert(b: bool); };
|
||||
case => { assert(false); };
|
||||
};
|
||||
};
|
||||
116
test/lang/match_slice_variant_test.ww
Normal file
116
test/lang/match_slice_variant_test.ww
Normal file
@@ -0,0 +1,116 @@
|
||||
// match_slice_variant_test — a `(scalar | []T)` match must select the right arm
|
||||
// and preserve the slice payload (len + first byte) across u8/i8/i32/u64/rune,
|
||||
// in both variant orders, and compose with a trailing str arm. Migrated from
|
||||
// test/wcc/926_match_slice_variant_run.c (value rows, cs==ww byte-id).
|
||||
|
||||
package match_slice_variant_test;
|
||||
|
||||
fn pick_u8(n: (u8 | []u8)) i32 = {
|
||||
match (n) {
|
||||
case let c: u8 => return c: i32;
|
||||
case let s: []u8 => return 100i32 + (s.len: i32) + (s[0]: i32);
|
||||
};
|
||||
return -1;
|
||||
};
|
||||
|
||||
fn pick_slice_first(n: ([]u8 | u8)) i32 = {
|
||||
match (n) {
|
||||
case let s: []u8 => return 100i32 + (s.len: i32) + (s[0]: i32);
|
||||
case let c: u8 => return c: i32;
|
||||
};
|
||||
return -1;
|
||||
};
|
||||
|
||||
fn pick_i8(n: (i8 | []i8)) i32 = {
|
||||
match (n) {
|
||||
case let c: i8 => return c: i32;
|
||||
case let s: []i8 => return 100i32 + (s.len: i32) + (s[0]: i32);
|
||||
};
|
||||
return -1;
|
||||
};
|
||||
|
||||
fn pick_i32(n: (i32 | []i32)) i32 = {
|
||||
match (n) {
|
||||
case let c: i32 => return c;
|
||||
case let s: []i32 => return 1000i32 + (s.len: i32) + s[0];
|
||||
};
|
||||
return -1;
|
||||
};
|
||||
|
||||
fn pick_u64(n: (u64 | []u64)) i32 = {
|
||||
match (n) {
|
||||
case let c: u64 => return c: i32;
|
||||
case let s: []u64 => return 1000i32 + (s.len: i32) + (s[0]: i32);
|
||||
};
|
||||
return -1;
|
||||
};
|
||||
|
||||
fn pick_rune(n: (rune | []rune)) i32 = {
|
||||
match (n) {
|
||||
case let r: rune => return r: i32;
|
||||
case let s: []rune => return 1000i32 + (s.len: i32) + (s[0]: i32);
|
||||
};
|
||||
return -1;
|
||||
};
|
||||
|
||||
fn pick3(n: (u8 | []u8 | str)) i32 = {
|
||||
match (n) {
|
||||
case let c: u8 => return c: i32;
|
||||
case let s: []u8 => return 200i32 + (s.len: i32) + (s[0]: i32);
|
||||
case let t: str => return 300i32 + (t.len: i32);
|
||||
};
|
||||
return -1;
|
||||
};
|
||||
|
||||
@test fn u8_slice_u8() void = {
|
||||
let buf: [3]u8;
|
||||
buf[0] = 7u8; buf[1] = 8u8; buf[2] = 9u8;
|
||||
assert(pick_u8(42u8) == 42);
|
||||
assert(pick_u8(buf[0:3]) == 110);
|
||||
};
|
||||
|
||||
@test fn slice_u8_then_u8() void = {
|
||||
let buf: [3]u8;
|
||||
buf[0] = 7u8; buf[1] = 8u8; buf[2] = 9u8;
|
||||
assert(pick_slice_first(buf[0:3]) == 110);
|
||||
assert(pick_slice_first(42u8) == 42);
|
||||
};
|
||||
|
||||
@test fn i8_slice_i8() void = {
|
||||
let buf: [2]i8;
|
||||
buf[0] = 5i8; buf[1] = 6i8;
|
||||
assert(pick_i8(11i8) == 11);
|
||||
assert(pick_i8(buf[0:2]) == 107);
|
||||
};
|
||||
|
||||
@test fn i32_slice_i32() void = {
|
||||
let buf: [2]i32;
|
||||
buf[0] = 33i32; buf[1] = 44i32;
|
||||
assert(pick_i32(77i32) == 77);
|
||||
assert(pick_i32(buf[0:2]) == 1035);
|
||||
};
|
||||
|
||||
@test fn u64_slice_u64() void = {
|
||||
let buf: [2]u64;
|
||||
buf[0] = 41u64; buf[1] = 42u64;
|
||||
assert(pick_u64(99u64) == 99);
|
||||
assert(pick_u64(buf[0:2]) == 1043);
|
||||
};
|
||||
|
||||
@test fn rune_slice_rune() void = {
|
||||
let buf: [2]rune;
|
||||
buf[0] = 'a'; buf[1] = 'b';
|
||||
assert(pick_rune('Z') == 90);
|
||||
assert(pick_rune(buf[0:2]) == 1099);
|
||||
};
|
||||
|
||||
@test fn u8_slice_u8_str() void = {
|
||||
let buf: [3]u8;
|
||||
buf[0] = 1u8; buf[1] = 2u8; buf[2] = 3u8;
|
||||
let a: i32 = pick3(5u8);
|
||||
let b: i32 = pick3(buf[0:3]);
|
||||
let c: i32 = pick3("hi");
|
||||
assert(a == 5);
|
||||
assert(b == 204);
|
||||
assert(c == 302);
|
||||
};
|
||||
58
test/lang/nested_union_widen_test.ww
Normal file
58
test/lang/nested_union_widen_test.ww
Normal file
@@ -0,0 +1,58 @@
|
||||
// nested_union_widen_test — widening a nested named error-union (inner = !(i32|bool))
|
||||
// into an enclosing (size | inner) union must keep the inner box distinguishable
|
||||
// and destructurable across outer-arm select, fn-return, and let-init. Migrated
|
||||
// from test/wcc/925_nested_union_widen_run.c (value rows). The same-shape
|
||||
// collision row (two distinct names !(i32|bool)) loud-stops both stages and lives
|
||||
// at test/wcc/data/nestunion_collision/ as a runww //ww:error carrier.
|
||||
|
||||
package nested_union_widen_test;
|
||||
|
||||
type inner = !(i32 | bool);
|
||||
|
||||
fn g_dr() (size | inner) = {
|
||||
let e: inner = (5i32: inner);
|
||||
return e;
|
||||
};
|
||||
|
||||
@test fn outer_arm_select() void = {
|
||||
let e: inner = (true: inner);
|
||||
let r: (size | inner) = e;
|
||||
match (r) {
|
||||
case let n: size => { assert(false); };
|
||||
case let x: inner => { };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn destructure_return() void = {
|
||||
match (g_dr()) {
|
||||
case let s: size => { assert(false); };
|
||||
case let x: inner => {
|
||||
match (x) {
|
||||
case let i: i32 => { assert(i == 5); };
|
||||
case let b: bool => { assert(false); };
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@test fn destructure_let() void = {
|
||||
let e: inner = (7i32: inner);
|
||||
let r: (size | inner) = e;
|
||||
match (r) {
|
||||
case let n: size => { assert(false); };
|
||||
case let x: inner => {
|
||||
match (x) {
|
||||
case let i: i32 => { assert(i == 7); };
|
||||
case let b: bool => { assert(false); };
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@test fn single_variant() void = {
|
||||
let r: (i32 | bool) = 7i32;
|
||||
match (r) {
|
||||
case let n: i32 => { assert(n == 7); };
|
||||
case let b: bool => { assert(false); };
|
||||
};
|
||||
};
|
||||
70
test/lang/tagged_call_arg_test.ww
Normal file
70
test/lang/tagged_call_arg_test.ww
Normal file
@@ -0,0 +1,70 @@
|
||||
// tagged_call_arg_test — #21: passing a tagged-union arg sourced from a fn call
|
||||
// that returns the same tagged union must not drop the DX/CX/R8 payload words.
|
||||
// Pins CALL-source (4-variant + 2-variant) and the IDENT-source fast-path that
|
||||
// must stay byte-identical, plus a tagged-CALL-then-scalar pop-count row.
|
||||
// Migrated from test/wcc/924_tagged_call_arg_run.c (value rows, cs==ww).
|
||||
|
||||
package tagged_call_arg_test;
|
||||
|
||||
type done = !void;
|
||||
type more = !void;
|
||||
type invalid = !void;
|
||||
type oserror = !i32;
|
||||
|
||||
fn yield_rune() (rune | done | more | invalid) = {
|
||||
return 65u32: rune;
|
||||
};
|
||||
fn dispatch4(v: (rune | done | more | invalid)) i32 = {
|
||||
match (v) {
|
||||
case let r: rune => return r: i32;
|
||||
case let d: done => return -1;
|
||||
case let m: more => return -2;
|
||||
case let e: invalid => return -3;
|
||||
};
|
||||
return -99;
|
||||
};
|
||||
|
||||
fn yield_ptr() (*u8 | oserror) = {
|
||||
let p: *u8 = nil;
|
||||
return p;
|
||||
};
|
||||
fn yield_err() (*u8 | oserror) = {
|
||||
let e: oserror = 42i32: oserror;
|
||||
return e;
|
||||
};
|
||||
fn dispatch2(v: (*u8 | oserror)) i32 = {
|
||||
match (v) {
|
||||
case let p: *u8 => return 7;
|
||||
case let e: oserror => return e: i32;
|
||||
};
|
||||
return -99;
|
||||
};
|
||||
|
||||
fn use2(v: (*u8 | oserror), k: i32) i32 = {
|
||||
match (v) {
|
||||
case let p: *u8 => return k + 1;
|
||||
case let e: oserror => return k - 1;
|
||||
};
|
||||
return -99;
|
||||
};
|
||||
|
||||
@test fn variant4_call_source_rune() void = {
|
||||
assert(dispatch4(yield_rune()) == 65);
|
||||
};
|
||||
|
||||
@test fn variant4_ident_source_rune() void = {
|
||||
let v: (rune | done | more | invalid) = 65u32: rune;
|
||||
assert(dispatch4(v) == 65);
|
||||
};
|
||||
|
||||
@test fn variant2_call_source_ptr() void = {
|
||||
assert(dispatch2(yield_ptr()) == 7);
|
||||
};
|
||||
|
||||
@test fn variant2_call_source_err() void = {
|
||||
assert(dispatch2(yield_err()) == 42);
|
||||
};
|
||||
|
||||
@test fn tagged_call_then_scalar() void = {
|
||||
assert(use2(yield_ptr(), 41) == 42);
|
||||
};
|
||||
378
test/lang/tagged_structlit_payload_test.ww
Normal file
378
test/lang/tagged_structlit_payload_test.ww
Normal file
@@ -0,0 +1,378 @@
|
||||
// tagged_structlit_payload_test — #23/#33/#38a: constructing a tagged union from
|
||||
// an inline struct literal whose fields are themselves tagged (void|size) /
|
||||
// (void|str) must fill the payload at the WIDENED slot's payload base, copy every
|
||||
// payload word (not just AX), and read/assign tagged leaves down a dot-spine.
|
||||
// Migrated from test/wcc/938_tagged_structlit_payload_run.c (value rows, cs==ww
|
||||
// byte-id). Types are per-row-prefixed because the C rows reused names with
|
||||
// different shapes.
|
||||
//
|
||||
// voidstr_field + recursion_torture do an inner match on a tagged FIELD scrutinee
|
||||
// (o.s, m.t) — historically tagged "match-on-tagged-struct-FIELD cs≠ww" (aliases
|
||||
// regex-arc #26 / cont.9 #42 match-field-cursor); the retired C driver flagged
|
||||
// them noasm=1. Divergence tag (master 6699158) STALE at HEAD: byte-id verified
|
||||
// cs==ww AND T1 value-correct. These rows are the REGRESSION SENTINEL for the
|
||||
// match-on-tagged-field divergence (former #26), closed no-reproducer-at-HEAD with
|
||||
// attribution to the #15/#17 tagged-field-via-ptr cluster INFERRED (not diff-
|
||||
// proven) — a resurgence trips this byte-id row. Reopen with a concrete shape if
|
||||
// it fails.
|
||||
|
||||
package tagged_structlit_payload_test;
|
||||
|
||||
type ir_lit = rune;
|
||||
type ir_rep = struct { id: size, origin: size, min: (void | size), max: (void | size) };
|
||||
type ir_inst = (ir_lit | ir_rep);
|
||||
|
||||
type ra_lit = rune;
|
||||
type ra_rep3 = struct { id: size, min: (void | size), max: (void | size) };
|
||||
type ra_inst = (ra_lit | ra_rep3);
|
||||
|
||||
type to_only = struct { m: (void | size) };
|
||||
type to_u = (rune | to_only);
|
||||
|
||||
type pb_lit = rune;
|
||||
type pb_rep3 = struct { id: size, min: (void | size), max: (void | size) };
|
||||
type pb_inst = (pb_lit | pb_rep3);
|
||||
|
||||
type sat_lit = rune;
|
||||
type sat_named = struct { s: str, m: (void | size) };
|
||||
type sat_inst = (sat_lit | sat_named);
|
||||
|
||||
type vp_lit = rune;
|
||||
type vp_rep3 = struct { id: size, min: (void | size), max: (void | size) };
|
||||
type vp_inst = (vp_rep3 | vp_lit);
|
||||
|
||||
type sec_lit = rune;
|
||||
type sec_rep1 = struct { id: size, m: (void | size) };
|
||||
type sec_inst = (sec_lit | sec_rep1);
|
||||
|
||||
type nsf_inner = struct { a: size, b: size };
|
||||
type nsf_outer = struct { id: size, in_: nsf_inner };
|
||||
type nsf_u = (rune | nsf_outer);
|
||||
|
||||
type ea_st = struct { a: u64, m: (void | size) };
|
||||
|
||||
type tto_d2 = struct { m: (void | size), n: (void | i64), z: u64 };
|
||||
|
||||
type nat_inn = struct { v: u64 };
|
||||
type nat_outt = struct { i: nat_inn, m: (void | size) };
|
||||
|
||||
type pb8_one = struct { a: size };
|
||||
type pb8_u = (rune | pb8_one);
|
||||
|
||||
type sn_plain = struct { a: size, f: f64, s: str };
|
||||
type sn_u = (rune | sn_plain);
|
||||
|
||||
type clr_rep = struct { id: size, min: (void | size), name: (void | str) };
|
||||
type clr_outer = struct { tag: size, r: clr_rep };
|
||||
|
||||
type cas_rep = struct { id: size, min: (void | size) };
|
||||
type cas_outer = struct { tag: size, r: cas_rep };
|
||||
|
||||
type cd2_rep = struct { id: size, min: (void | size) };
|
||||
type cd2_mid = struct { m: size, r: cd2_rep };
|
||||
type cd2_outer = struct { tag: size, w: cd2_mid };
|
||||
|
||||
type csv_rep = struct { id: size, nm: (void | str) };
|
||||
type csv_outer = struct { tag: size, r: csv_rep };
|
||||
|
||||
type cpr_rep = struct { id: size, min: (void | size) };
|
||||
type cpr_outer = struct { tag: size, r: cpr_rep };
|
||||
|
||||
type cpm_rep = struct { id: size, min: (void | size) };
|
||||
type cpm_outer = struct { tag: size, p: *cpm_rep };
|
||||
|
||||
type vsf_st = struct { id: size, s: (void | str) };
|
||||
type vsf_u = (rune | vsf_st);
|
||||
|
||||
type leaf = struct { p: size };
|
||||
type t1 = (void | leaf);
|
||||
type rt_mid = struct { t: t1 };
|
||||
type t2 = (void | rt_mid);
|
||||
type rt_outr = struct { id: size, t: t2 };
|
||||
type rt_u = (rune | rt_outr);
|
||||
|
||||
fn take_uib(v: (void | size)) i32 = {
|
||||
if (v is size) { return (v as size): i32; };
|
||||
return -1;
|
||||
};
|
||||
|
||||
@test fn inst_repeat_shape() void = {
|
||||
let v: ir_inst = ir_rep { id = 1: size, origin = 2: size, min = void, max = 5: size };
|
||||
match (v) {
|
||||
case let ir: ir_rep => {
|
||||
assert(ir.id == 1);
|
||||
assert(ir.origin == 2);
|
||||
assert(ir.min is void);
|
||||
assert(ir.max is size);
|
||||
assert(ir.max as size == 5);
|
||||
};
|
||||
case let l: ir_lit => { assert(false); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn rep3_allsize() void = {
|
||||
let v: ra_inst = ra_rep3 { id = 1: size, min = 2: size, max = 5: size };
|
||||
match (v) {
|
||||
case let ir: ra_rep3 => {
|
||||
assert(ir.id == 1);
|
||||
assert(ir.min is size);
|
||||
assert(ir.min as size == 2);
|
||||
assert(ir.max is size);
|
||||
assert(ir.max as size == 5);
|
||||
};
|
||||
case let l: ra_lit => { assert(false); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn tagged_only16() void = {
|
||||
let v: to_u = to_only { m = 7: size };
|
||||
match (v) {
|
||||
case let o: to_only => {
|
||||
assert(o.m is size);
|
||||
assert(o.m as size == 7);
|
||||
};
|
||||
case => { assert(false); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn prebound_tagged_field() void = {
|
||||
let mn: (void | size) = 2: size;
|
||||
let v: pb_inst = pb_rep3 { id = 3: size, min = mn, max = void };
|
||||
match (v) {
|
||||
case let ir: pb_rep3 => {
|
||||
assert(ir.id == 3);
|
||||
assert(ir.min is size);
|
||||
assert(ir.min as size == 2);
|
||||
assert(ir.max is void);
|
||||
};
|
||||
case let l: pb_lit => { assert(false); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn str_and_tagged() void = {
|
||||
let v: sat_inst = sat_named { s = "hi", m = 9: size };
|
||||
match (v) {
|
||||
case let nm: sat_named => {
|
||||
assert(len(nm.s) == 2);
|
||||
assert(nm.m is size);
|
||||
assert(nm.m as size == 9);
|
||||
};
|
||||
case let l: sat_lit => { assert(false); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn variant_pos0() void = {
|
||||
let v: vp_inst = vp_rep3 { id = 1: size, min = void, max = 8: size };
|
||||
match (v) {
|
||||
case let ir: vp_rep3 => {
|
||||
assert(ir.id == 1);
|
||||
assert(ir.min is void);
|
||||
assert(ir.max is size);
|
||||
assert(ir.max as size == 8);
|
||||
};
|
||||
case let l: vp_lit => { assert(false); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn slice_elem_cursorfit() void = {
|
||||
let insts: []sec_inst = [];
|
||||
append(insts, ('a': sec_lit));
|
||||
let v: sec_inst = sec_rep1 { id = 4: size, m = 6: size };
|
||||
append(insts, v);
|
||||
assert(len(insts) == 2);
|
||||
match (insts[1]) {
|
||||
case let r: sec_rep1 => {
|
||||
assert(r.id == 4);
|
||||
assert(r.m is size);
|
||||
assert(r.m as size == 6);
|
||||
};
|
||||
case let l: sec_lit => { assert(false); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn nested_struct_field() void = {
|
||||
let v: nsf_u = nsf_outer { id = 1: size, in_ = nsf_inner { a = 2: size, b = 3: size } };
|
||||
match (v) {
|
||||
case let o: nsf_outer => {
|
||||
assert(o.id == 1);
|
||||
assert(o.in_.a == 2);
|
||||
assert(o.in_.b == 3);
|
||||
};
|
||||
case => { assert(false); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn ellipsis_autofill() void = {
|
||||
let e: (void | ea_st) = ea_st { m = 5: size, ... };
|
||||
match (e) {
|
||||
case let s: ea_st => {
|
||||
assert(s.a == 0u64);
|
||||
assert(s.m is size);
|
||||
assert(s.m as size == 5);
|
||||
};
|
||||
case void => { assert(false); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn two_tagged_offset0() void = {
|
||||
let e: (void | tto_d2) = tto_d2 { m = 4: size, n = (-9): i64, z = 77u64 };
|
||||
match (e) {
|
||||
case let s: tto_d2 => {
|
||||
assert(s.m is size);
|
||||
assert(s.m as size == 4);
|
||||
assert(s.n is i64);
|
||||
assert(s.n as i64 == -9);
|
||||
assert(s.z == 77u64);
|
||||
};
|
||||
case void => { assert(false); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn nested_and_tagged() void = {
|
||||
let e: (void | nat_outt) = nat_outt { i = nat_inn { v = 11u64 }, m = 8: size };
|
||||
match (e) {
|
||||
case let s: nat_outt => {
|
||||
assert(s.i.v == 11u64);
|
||||
assert(s.m is size);
|
||||
assert(s.m as size == 8);
|
||||
};
|
||||
case void => { assert(false); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn payload8_boundary() void = {
|
||||
let v: pb8_u = pb8_one { a = 42: size };
|
||||
match (v) {
|
||||
case let o: pb8_one => { assert(o.a == 42); };
|
||||
case => { assert(false); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn scalar_neighbor() void = {
|
||||
let v: sn_u = sn_plain { a = 11: size, f = 2.5, s = "xyz" };
|
||||
match (v) {
|
||||
case let p: sn_plain => {
|
||||
assert(p.a == 11);
|
||||
assert(p.f == 2.5);
|
||||
assert(len(p.s) == 3);
|
||||
};
|
||||
case => { assert(false); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn chained_tagged_literal_read() void = {
|
||||
let o = clr_outer { tag = 4: size, r = clr_rep { id = 6: size, min = 8: size, name = void } };
|
||||
assert(o.tag == 4);
|
||||
assert(o.r.id == 6);
|
||||
assert(o.r.min is size);
|
||||
assert(o.r.min as size == 8);
|
||||
assert(o.r.name is void);
|
||||
};
|
||||
|
||||
@test fn chained_tagged_assign() void = {
|
||||
let o: cas_outer = cas_outer { tag = 4: size, r = cas_rep { id = 6: size, min = void } };
|
||||
o.r.min = 8: size;
|
||||
assert(o.r.min is size);
|
||||
assert(o.r.min as size == 8);
|
||||
o.r.min = 9;
|
||||
assert(o.r.min is size);
|
||||
assert(o.r.min as size == 9);
|
||||
};
|
||||
|
||||
@test fn chained_tagged_depth2() void = {
|
||||
let o = cd2_outer { tag = 4: size, w = cd2_mid { m = 2: size, r = cd2_rep { id = 6: size, min = 5: size } } };
|
||||
assert(o.w.r.min is size);
|
||||
assert(o.w.r.min as size == 5);
|
||||
o.w.r.min = 8: size;
|
||||
assert(o.w.m == 2);
|
||||
assert(o.w.r.id == 6);
|
||||
assert(o.w.r.min is size);
|
||||
assert(o.w.r.min as size == 8);
|
||||
};
|
||||
|
||||
@test fn chained_tagged_strvariant() void = {
|
||||
let o = csv_outer { tag = 4: size, r = csv_rep { id = 6: size, nm = void } };
|
||||
o.r.nm = "hello";
|
||||
assert(o.r.nm is str);
|
||||
assert((o.r.nm as str).len == 5);
|
||||
match (o.r.nm) {
|
||||
case let s: str => { assert(s.len == 5); };
|
||||
case void => { assert(false); };
|
||||
};
|
||||
o.r.nm = void;
|
||||
assert(o.r.nm is void);
|
||||
assert(o.r.id == 6);
|
||||
};
|
||||
|
||||
@test fn chained_tagged_ptrroot() void = {
|
||||
let o = cpr_outer { tag = 4: size, r = cpr_rep { id = 6: size, min = void } };
|
||||
let p: *cpr_outer = &o;
|
||||
p.r.min = 8: size;
|
||||
assert(p.r.id == 6);
|
||||
assert(p.r.min is size);
|
||||
assert(p.r.min as size == 8);
|
||||
};
|
||||
|
||||
@test fn chained_tagged_ptrmid() void = {
|
||||
let r = cpm_rep { id = 6: size, min = void };
|
||||
let o = cpm_outer { tag = 4: size, p = &r };
|
||||
o.p.min = 8: size;
|
||||
assert(o.p.id == 6);
|
||||
assert(o.p.min is size);
|
||||
assert(o.p.min as size == 8);
|
||||
};
|
||||
|
||||
@test fn untyped_int_bare_widen() void = {
|
||||
let e: (void | size) = 5;
|
||||
assert(e is size);
|
||||
assert(e as size == 5);
|
||||
let mn: (void | size) = void;
|
||||
mn = 7;
|
||||
assert(mn is size);
|
||||
assert(mn as size == 7);
|
||||
let b: (bool | u64) = 9;
|
||||
assert(b is u64);
|
||||
assert(take_uib(9) == 9);
|
||||
let cf: (void | size) = 5: size;
|
||||
assert(cf is size);
|
||||
assert(cf as size == 5);
|
||||
let f: (void | i64) = 9;
|
||||
assert(f is i64);
|
||||
assert(f as i64 == 9);
|
||||
};
|
||||
|
||||
// voidstr_field/recursion_torture: regression-sentinel rows for the former-#26
|
||||
// match-on-tagged-field divergence (STALE at HEAD: byte-id cs==ww + value-correct;
|
||||
// closed no-reproducer, #15/#17 attribution inferred). See the file header.
|
||||
@test fn voidstr_field() void = {
|
||||
let v: vsf_u = vsf_st { id = 3: size, s = "hello" };
|
||||
match (v) {
|
||||
case let o: vsf_st => {
|
||||
assert(o.id == 3);
|
||||
match (o.s) {
|
||||
case let sv: str => { assert(len(sv) == 5); };
|
||||
case void => { assert(false); };
|
||||
};
|
||||
};
|
||||
case => { assert(false); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn recursion_torture() void = {
|
||||
let v: rt_u = rt_outr { id = 1: size, t = rt_mid { t = leaf { p = 9: size } } };
|
||||
match (v) {
|
||||
case let o: rt_outr => {
|
||||
assert(o.id == 1);
|
||||
match (o.t) {
|
||||
case let m: rt_mid => {
|
||||
match (m.t) {
|
||||
case let l: leaf => { assert(l.p == 9); };
|
||||
case void => { assert(false); };
|
||||
};
|
||||
};
|
||||
case void => { assert(false); };
|
||||
};
|
||||
};
|
||||
case => { assert(false); };
|
||||
};
|
||||
};
|
||||
73
test/lang/tagged_widen_arg_test.ww
Normal file
73
test/lang/tagged_widen_arg_test.ww
Normal file
@@ -0,0 +1,73 @@
|
||||
// tagged_widen_arg_test — a narrower tagged source (ident/deref/index/dot) passed
|
||||
// into a wider tagged param must widen + tag-remap so the callee reads the right
|
||||
// arm. The aligned set keeps i64 at tag0 in both; the remap set has i64 at tag1
|
||||
// in the source (un16b) but tag0 in the param (un3b), forcing the remap.
|
||||
// Migrated from test/wcc/944_tagged_widen_arg_run.c (value rows, all cs==ww byte-id).
|
||||
|
||||
package tagged_widen_arg_test;
|
||||
|
||||
type s16 = struct { a: i64, b: i64 };
|
||||
type un16 = (i64 | bool);
|
||||
type un3 = (i64 | bool | s16);
|
||||
type un16b = (bool | i64);
|
||||
type un3b = (i64 | bool | s16);
|
||||
type wrap_a = struct { f: un16 };
|
||||
type wrap_b = struct { f: un16b };
|
||||
|
||||
fn take_aligned(e: un3) i64 = {
|
||||
match (e) {
|
||||
case let v: i64 => { return v; };
|
||||
case let b: bool => { return -1; };
|
||||
case let s: s16 => { return s.a + s.b; };
|
||||
};
|
||||
};
|
||||
|
||||
fn take_remap(e: un3b) i64 = {
|
||||
match (e) {
|
||||
case let v: i64 => { return v; };
|
||||
case let b: bool => { return -1; };
|
||||
case let s: s16 => { return s.a + s.b; };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn ident_aligned() void = {
|
||||
let v: un16 = (42: i64);
|
||||
assert(take_aligned(v) == 42);
|
||||
};
|
||||
|
||||
@test fn deref_aligned() void = {
|
||||
let v: un16 = (42: i64);
|
||||
let p: *un16 = &v;
|
||||
assert(take_aligned(*p) == 42);
|
||||
};
|
||||
|
||||
@test fn index_aligned() void = {
|
||||
let xs: [2]un16 = [(42: i64), (7: i64)];
|
||||
assert(take_aligned(xs[0]) == 42);
|
||||
};
|
||||
|
||||
@test fn dot_aligned() void = {
|
||||
let w: wrap_a = wrap_a { f = (42: i64) };
|
||||
assert(take_aligned(w.f) == 42);
|
||||
};
|
||||
|
||||
@test fn ident_remap() void = {
|
||||
let v: un16b = (42: i64);
|
||||
assert(take_remap(v) == 42);
|
||||
};
|
||||
|
||||
@test fn deref_remap() void = {
|
||||
let v: un16b = (42: i64);
|
||||
let p: *un16b = &v;
|
||||
assert(take_remap(*p) == 42);
|
||||
};
|
||||
|
||||
@test fn index_remap() void = {
|
||||
let xs: [2]un16b = [(42: i64), (7: i64)];
|
||||
assert(take_remap(xs[0]) == 42);
|
||||
};
|
||||
|
||||
@test fn dot_remap() void = {
|
||||
let w: wrap_b = wrap_b { f = (42: i64) };
|
||||
assert(take_remap(w.f) == 42);
|
||||
};
|
||||
67
test/lang/taggedderefstore_test.ww
Normal file
67
test/lang/taggedderefstore_test.ww
Normal file
@@ -0,0 +1,67 @@
|
||||
// taggedderefstore_test — #17 teeth: `*p = v` into a tagged-union pointee must
|
||||
// store the full box (route through the widener + scratch word-copy), not a
|
||||
// single tag-word store. Was both-stage-wrong AND byte-id-green (#263-class),
|
||||
// now CLOSED both stages. Migrated from test/wcc/989_taggedderefstore_run.c
|
||||
// (value rows; scalarctl pins the non-tagged single-store path stays unchanged).
|
||||
|
||||
package taggedderefstore_test;
|
||||
|
||||
type pair = struct { a: i64, b: i64 };
|
||||
|
||||
@test fn taglo() void = {
|
||||
let v: (int | bool) = false;
|
||||
let p: *(int | bool) = &v;
|
||||
*p = 42;
|
||||
match (v) {
|
||||
case let n: int => { assert(n == 42); };
|
||||
case bool => { assert(false); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn taghi() void = {
|
||||
let v: (int | bool) = 0;
|
||||
let p: *(int | bool) = &v;
|
||||
*p = true;
|
||||
match (v) {
|
||||
case int => { assert(false); };
|
||||
case let b: bool => { assert(b); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn str3w() void = {
|
||||
let v: (int | str) = 0;
|
||||
let p: *(int | str) = &v;
|
||||
*p = "hello";
|
||||
match (v) {
|
||||
case int => { assert(false); };
|
||||
case let s: str => { assert(s.len: int == 5); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn struct2w() void = {
|
||||
let v: (int | pair) = 0;
|
||||
let p: *(int | pair) = &v;
|
||||
*p = pair { a = 0x1111, b = 0x2222 };
|
||||
match (v) {
|
||||
case int => { assert(false); };
|
||||
case let q: pair => { assert(q.a == 0x1111 && q.b == 0x2222); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn nullfold() void = {
|
||||
let a: int = 7;
|
||||
let v: (*int | void) = void;
|
||||
let p: *(*int | void) = &v;
|
||||
*p = &a;
|
||||
match (v) {
|
||||
case let q: *int => { assert(*q == 7); };
|
||||
case void => { assert(false); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn scalarctl() void = {
|
||||
let v: int = 3;
|
||||
let p: *int = &v;
|
||||
*p = 42;
|
||||
assert(v == 42);
|
||||
};
|
||||
71
test/lang/taggedglobalindex_test.ww
Normal file
71
test/lang/taggedglobalindex_test.ww
Normal file
@@ -0,0 +1,71 @@
|
||||
// taggedglobalindex_test — #16 teeth: `gs[i] = v` into a global tagged array
|
||||
// must use the global base g(SB) and store the full box. Migrated from
|
||||
// test/wcc/989_taggedglobalindex_run.c (value rows; loc_ctl/scalar_ctl pin the
|
||||
// frame-base and scalar-array control arms stay unperturbed). Globals kept at
|
||||
// module scope.
|
||||
|
||||
package taggedglobalindex_test;
|
||||
|
||||
type pair = struct { a: i64, b: i64 };
|
||||
|
||||
let gs_lo: [2](int | bool) = [0, 0];
|
||||
let gs_hi: [2](int | bool) = [0, 0];
|
||||
let gs_var: [3](int | bool) = [0, 0, 0];
|
||||
let gs_str: [2](int | str) = [0, 0];
|
||||
let gs_struct: [2](int | pair) = [0, 0];
|
||||
let g_scalar: [3]int = [0, 0, 0];
|
||||
|
||||
@test fn glo_taglo() void = {
|
||||
gs_lo[1] = 42;
|
||||
match (gs_lo[1]) {
|
||||
case let n: int => { assert(n == 42); };
|
||||
case bool => { assert(false); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn glo_taghi() void = {
|
||||
gs_hi[1] = true;
|
||||
match (gs_hi[1]) {
|
||||
case int => { assert(false); };
|
||||
case let b: bool => { assert(b); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn glo_varidx() void = {
|
||||
let i: int = 2;
|
||||
gs_var[i] = 99;
|
||||
match (gs_var[2]) {
|
||||
case let n: int => { assert(n == 99); };
|
||||
case bool => { assert(false); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn glo_str3w() void = {
|
||||
gs_str[1] = "hello";
|
||||
match (gs_str[1]) {
|
||||
case int => { assert(false); };
|
||||
case let s: str => { assert(s.len: int == 5); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn glo_struct2w() void = {
|
||||
gs_struct[1] = pair { a = 0x1111, b = 0x2222 };
|
||||
match (gs_struct[1]) {
|
||||
case int => { assert(false); };
|
||||
case let q: pair => { assert(q.a == 0x1111 && q.b == 0x2222); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn loc_ctl() void = {
|
||||
let a: [2](int | bool) = [0, 0];
|
||||
a[1] = 42;
|
||||
match (a[1]) {
|
||||
case let n: int => { assert(n == 42); };
|
||||
case bool => { assert(false); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn scalar_ctl() void = {
|
||||
g_scalar[1] = 42;
|
||||
assert(g_scalar[1] == 42);
|
||||
};
|
||||
48
test/lang/taggedidx_test.ww
Normal file
48
test/lang/taggedidx_test.ww
Normal file
@@ -0,0 +1,48 @@
|
||||
// taggedidx_test — #23: a tagged element off a non-ident base (slice `arr[1:][0]`,
|
||||
// call `getrows()[1]`) must load the full cursor, not just the tag word. The
|
||||
// N_IDENT base control already worked and must not regress. Migrated from
|
||||
// test/wcc/989_taggedidx_run.c (value rows).
|
||||
|
||||
package taggedidx_test;
|
||||
|
||||
type box = (i64 | bool);
|
||||
|
||||
fn getrows() []box = {
|
||||
let arr: [3]box;
|
||||
arr[0] = 10; arr[1] = 50; arr[2] = 70;
|
||||
return arr[0:];
|
||||
};
|
||||
|
||||
@test fn slice_tagged_idx() void = {
|
||||
let arr: [3]box;
|
||||
arr[0] = 10; arr[1] = 40; arr[2] = 70;
|
||||
let v: box = arr[1:][0];
|
||||
let r: i64 = 0;
|
||||
match (v) {
|
||||
case let x: i64 => { r = x; };
|
||||
case let b: bool => { r = 99; };
|
||||
};
|
||||
assert(r == 40);
|
||||
};
|
||||
|
||||
@test fn call_tagged_idx() void = {
|
||||
let v: box = getrows()[1];
|
||||
let r: i64 = 0;
|
||||
match (v) {
|
||||
case let x: i64 => { r = x; };
|
||||
case let b: bool => { r = 99; };
|
||||
};
|
||||
assert(r == 50);
|
||||
};
|
||||
|
||||
@test fn ident_tagged_idx() void = {
|
||||
let arr: [3]box;
|
||||
arr[0] = 10; arr[1] = 40; arr[2] = 70;
|
||||
let v: box = arr[1];
|
||||
let r: i64 = 0;
|
||||
match (v) {
|
||||
case let x: i64 => { r = x; };
|
||||
case let b: bool => { r = 99; };
|
||||
};
|
||||
assert(r == 40);
|
||||
};
|
||||
80
test/lang/tagnorm_test.ww
Normal file
80
test/lang/tagnorm_test.ww
Normal file
@@ -0,0 +1,80 @@
|
||||
// tagnorm_test — tagged-union normalization: nullable folds to an 8B ptr slot;
|
||||
// `never` drops; duplicate variants dedup; size/align ride the normalized chain;
|
||||
// and a bare `return;` void tag comes off the NORMALIZED (deduped) variant index
|
||||
// at positions 0/1/2. dedup_match pins that a deduped (i32|i32|str) constructs +
|
||||
// matches its str variant in both stages. Migrated from
|
||||
// test/wcc/989_tagnorm_run.c (value rows). dedup_match: the old C driver's comment
|
||||
// claimed its str tag-NUMBER diverged (cs $1 vs ww $2) — that divergence tag is
|
||||
// STALE at HEAD: byte-id verified cs==ww AND T1 value-correct (the @test runs and
|
||||
// asserts r==7), so it migrates as a NORMAL byte-id @test row, not a runonly.
|
||||
|
||||
package tagnorm_test;
|
||||
|
||||
type tn_p = (*u8 | void);
|
||||
type tn_q = (i32 | never);
|
||||
type tn_d = (i32 | i32);
|
||||
type tn_u3str = (i32 | i32 | str);
|
||||
type tn_uvoid = (i32 | i32 | void);
|
||||
type tn_vpos0 = (void | i32);
|
||||
type tn_vpos2 = (i32 | str | void);
|
||||
|
||||
fn f_void_dedup() tn_uvoid = { return; };
|
||||
fn f_void_pos0() tn_vpos0 = { return; };
|
||||
fn f_void_pos2() tn_vpos2 = { return; };
|
||||
|
||||
@test fn nullable_size() void = {
|
||||
assert(size(tn_p): int == 8);
|
||||
};
|
||||
|
||||
@test fn never_size() void = {
|
||||
assert(size(tn_q): int == 4);
|
||||
};
|
||||
|
||||
@test fn dup_size() void = {
|
||||
assert(size(tn_d): int == 4);
|
||||
};
|
||||
|
||||
@test fn never_align() void = {
|
||||
assert(align(tn_q): int == 4);
|
||||
};
|
||||
|
||||
@test fn dedup_match() void = {
|
||||
let v: tn_u3str = "hi";
|
||||
let r: i64 = 0;
|
||||
match (v) {
|
||||
case let s: str => { r = 7; };
|
||||
case let x: i32 => { r = 1; };
|
||||
};
|
||||
assert(r == 7);
|
||||
};
|
||||
|
||||
@test fn void_dedup_ret() void = {
|
||||
let v: tn_uvoid = f_void_dedup();
|
||||
let r: i64 = 0;
|
||||
match (v) {
|
||||
case void => { r = 5; };
|
||||
case let x: i32 => { r = 9; };
|
||||
};
|
||||
assert(r == 5);
|
||||
};
|
||||
|
||||
@test fn void_pos0_ret() void = {
|
||||
let v: tn_vpos0 = f_void_pos0();
|
||||
let r: i64 = 0;
|
||||
match (v) {
|
||||
case void => { r = 5; };
|
||||
case let x: i32 => { r = 9; };
|
||||
};
|
||||
assert(r == 5);
|
||||
};
|
||||
|
||||
@test fn void_pos2_ret() void = {
|
||||
let v: tn_vpos2 = f_void_pos2();
|
||||
let r: i64 = 0;
|
||||
match (v) {
|
||||
case void => { r = 5; };
|
||||
case let s: str => { r = 8; };
|
||||
case let x: i32 => { r = 9; };
|
||||
};
|
||||
assert(r == 5);
|
||||
};
|
||||
82
test/lang/tryprop_tag_remap_test.ww
Normal file
82
test/lang/tryprop_tag_remap_test.ww
Normal file
@@ -0,0 +1,82 @@
|
||||
// tryprop_tag_remap_test — the `?` try-operator must remap variant tags when the
|
||||
// propagated error union's variant ORDER differs between callee and caller
|
||||
// ((i32|e1|e2) propagated through (i32|e2|e1)), and pass multiword (str) error
|
||||
// payloads intact. Migrated from test/wcc/925_tryprop_tag_remap_run.c (value rows).
|
||||
|
||||
package tryprop_tag_remap_test;
|
||||
|
||||
type e1 = !void;
|
||||
type e2 = !void;
|
||||
type emsg = !str;
|
||||
|
||||
fn g(which: i32) (i32 | e1 | e2) = {
|
||||
if (which == 1) { return e1{}; };
|
||||
if (which == 2) { return e2{}; };
|
||||
return 100;
|
||||
};
|
||||
|
||||
// caller variant order (i32|e2|e1) differs from g's (i32|e1|e2): the remap fires.
|
||||
fn f_diff(which: i32) (i32 | e2 | e1) = {
|
||||
let v: i32 = g(which)?;
|
||||
return v + 1;
|
||||
};
|
||||
|
||||
// caller order matches g's: no remap (control).
|
||||
fn f_same(which: i32) (i32 | e1 | e2) = {
|
||||
let v: i32 = g(which)?;
|
||||
return v + 1;
|
||||
};
|
||||
|
||||
fn g_mw(which: i32) (i32 | e1 | emsg) = {
|
||||
if (which == 1) { return e1{}; };
|
||||
if (which == 2) { let m: emsg = "AB": emsg; return m; };
|
||||
return 100;
|
||||
};
|
||||
fn f_mw(which: i32) (i32 | emsg | e1) = {
|
||||
let v: i32 = g_mw(which)?;
|
||||
return v + 1;
|
||||
};
|
||||
|
||||
@test fn diff_order_e1() void = {
|
||||
match (f_diff(1)) {
|
||||
case let v: i32 => { assert(false); };
|
||||
case e2 => { assert(false); };
|
||||
case e1 => { };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn diff_order_e2() void = {
|
||||
match (f_diff(2)) {
|
||||
case let v: i32 => { assert(false); };
|
||||
case e2 => { };
|
||||
case e1 => { assert(false); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn diff_order_success() void = {
|
||||
match (f_diff(0)) {
|
||||
case let v: i32 => { assert(v == 101); };
|
||||
case e2 => { assert(false); };
|
||||
case e1 => { assert(false); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn same_order() void = {
|
||||
match (f_same(1)) {
|
||||
case let v: i32 => { assert(false); };
|
||||
case e1 => { };
|
||||
case e2 => { assert(false); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn multiword() void = {
|
||||
match (f_mw(2)) {
|
||||
case let v: i32 => { assert(false); };
|
||||
case let s: emsg => {
|
||||
assert(s.len == 2);
|
||||
assert(s[0] == 65u8);
|
||||
assert(s[1] == 66u8);
|
||||
};
|
||||
case e1 => { assert(false); };
|
||||
};
|
||||
};
|
||||
38
test/lang/variant_chain_b95_runonly_test.ww
Normal file
38
test/lang/variant_chain_b95_runonly_test.ww
Normal file
@@ -0,0 +1,38 @@
|
||||
// variant_chain_b95_runonly_test — the two #95 CALL-source chain rows whose mk()
|
||||
// frame carries the pre-existing #81 uninit-local zero-fill asm divergence: the
|
||||
// `is` result is cs==ww runtime-correct, but the surrounding frame byte-diverges
|
||||
// cs≠ww (probed at HEAD: real, both standalone and @test forms). So these migrate
|
||||
// VALUE-ONLY (_runonly, byte-id-EXCLUDED) per the divergence carve; the byte-id
|
||||
// net is waived pending #81. Migrated from test/wcc/944_variant_chain_b95_run.c
|
||||
// (K_RUN_NOID rows, #5-C5).
|
||||
|
||||
package variant_chain_b95_runonly_test;
|
||||
|
||||
type cc1_base = struct { a: int, b: int };
|
||||
type cc1_al0 = cc1_base;
|
||||
|
||||
type cc2_base = struct { a: int, b: int };
|
||||
type cc2_al0 = cc2_base;
|
||||
type cc2_ali = cc2_al0;
|
||||
|
||||
fn cc1_mk() cc1_base = {
|
||||
let s: cc1_base;
|
||||
s.a = 4; s.b = 9;
|
||||
return s;
|
||||
};
|
||||
|
||||
fn cc2_mk() cc2_base = {
|
||||
let s: cc2_base;
|
||||
s.a = 4; s.b = 9;
|
||||
return s;
|
||||
};
|
||||
|
||||
@test fn chain_call_bound81() void = {
|
||||
let v: (void | cc1_al0) = cc1_mk();
|
||||
assert(v is cc1_al0);
|
||||
};
|
||||
|
||||
@test fn chain_call2_bound81() void = {
|
||||
let v: (void | cc2_ali) = cc2_mk();
|
||||
assert(v is cc2_ali);
|
||||
};
|
||||
145
test/lang/variant_chain_b95_test.ww
Normal file
145
test/lang/variant_chain_b95_test.ww
Normal file
@@ -0,0 +1,145 @@
|
||||
// variant_chain_b95_test — #95: widening a source whose TYPE reaches a union
|
||||
// variant through an alias CHAIN (or by structural fallback) must tag the right
|
||||
// variant. Pins 1/2/deep-level chain membership, exact-precedence (ali|ali2),
|
||||
// nominal (str|linerr) regression, bare-pointer source, and unrelated-struct
|
||||
// structural fallback. Migrated from test/wcc/944_variant_chain_b95_run.c
|
||||
// (K_RUN rows: build+run cs==ww + asm byte-id). The K_BUILDERR reject rows are
|
||||
// runww //ww:error carriers (test/wcc/data/vchain_*); the cstage-runs/ww-rejects
|
||||
// #277 row + the #81 call-source byte-id-waived rows are carried separately.
|
||||
// Types are per-row-prefixed because the C rows reused names with different shapes.
|
||||
|
||||
package variant_chain_b95_test;
|
||||
|
||||
type c1_base = struct { a: int, b: int };
|
||||
type c1_al0 = c1_base;
|
||||
|
||||
type c2_base = struct { a: int, b: int };
|
||||
type c2_al0 = c2_base;
|
||||
type c2_ali = c2_al0;
|
||||
|
||||
type cds_base = struct { a: int, b: int };
|
||||
type cds_ali = cds_base;
|
||||
type cds_ali2 = cds_ali;
|
||||
|
||||
type cdv_base = struct { a: int, b: int };
|
||||
type cdv_ali = cdv_base;
|
||||
type cdv_ali2 = cdv_ali;
|
||||
|
||||
type casa_base = struct { a: int, b: int };
|
||||
type casa_ali = casa_base;
|
||||
type casa_ali2 = casa_ali;
|
||||
|
||||
type casb_base = struct { a: int, b: int };
|
||||
type casb_ali = casb_base;
|
||||
type casb_ali2 = casb_ali;
|
||||
|
||||
type ns_linerr = str;
|
||||
type ne_linerr = str;
|
||||
|
||||
type ec_base = struct { a: int, b: int };
|
||||
type ec_al0 = ec_base;
|
||||
type ec_ali = ec_al0;
|
||||
|
||||
type bc_vt = struct { a: int };
|
||||
type bc_stream = *bc_vt;
|
||||
|
||||
type b2_vt = struct { a: int };
|
||||
type b2_st0 = *b2_vt;
|
||||
type b2_stream = b2_st0;
|
||||
|
||||
type us_ta = struct { a: int, b: int };
|
||||
type us_tb = struct { a: int, b: int };
|
||||
|
||||
@test fn chain_1lvl_i() void = {
|
||||
let s: c1_base;
|
||||
s.a = 4; s.b = 9;
|
||||
let v: (void | c1_al0) = s;
|
||||
assert(v is c1_al0);
|
||||
};
|
||||
|
||||
@test fn chain_2lvl_i() void = {
|
||||
let s: c2_base;
|
||||
s.a = 4; s.b = 9;
|
||||
let v: (void | c2_ali) = s;
|
||||
assert(v is c2_ali);
|
||||
};
|
||||
|
||||
@test fn chain_deep_src() void = {
|
||||
let s: cds_ali2;
|
||||
s.a = 4; s.b = 9;
|
||||
let v: (void | cds_ali) = s;
|
||||
assert(v is cds_ali);
|
||||
};
|
||||
|
||||
@test fn chain_deep_var() void = {
|
||||
let s: cdv_base;
|
||||
s.a = 4; s.b = 9;
|
||||
let v: (void | cdv_ali2) = s;
|
||||
assert(v is cdv_ali2);
|
||||
};
|
||||
|
||||
@test fn chain_amb_srcA() void = {
|
||||
let s: casa_ali;
|
||||
s.a = 4; s.b = 9;
|
||||
let v: (casa_ali | casa_ali2) = s;
|
||||
assert(v is casa_ali);
|
||||
assert(!(v is casa_ali2));
|
||||
};
|
||||
|
||||
@test fn chain_amb_srcB() void = {
|
||||
let s: casb_ali2;
|
||||
s.a = 4; s.b = 9;
|
||||
let v: (casb_ali | casb_ali2) = s;
|
||||
assert(v is casb_ali2);
|
||||
assert(!(v is casb_ali));
|
||||
};
|
||||
|
||||
@test fn nom_str() void = {
|
||||
let s: str = "ok";
|
||||
let v: (str | ns_linerr) = s;
|
||||
assert(v is str);
|
||||
assert(!(v is ns_linerr));
|
||||
};
|
||||
|
||||
@test fn nom_err() void = {
|
||||
let e: ne_linerr = "bad";
|
||||
let v: (str | ne_linerr) = e;
|
||||
assert(v is ne_linerr);
|
||||
assert(!(v is str));
|
||||
};
|
||||
|
||||
@test fn exact_ctl() void = {
|
||||
let s: ec_ali;
|
||||
s.a = 4; s.b = 9;
|
||||
let v: (void | ec_ali) = s;
|
||||
assert(v is ec_ali);
|
||||
};
|
||||
|
||||
@test fn bare_ctl() void = {
|
||||
let x: bc_vt;
|
||||
x.a = 7;
|
||||
let v: (void | bc_stream) = &x;
|
||||
assert(v is bc_stream);
|
||||
match (v) {
|
||||
case let s: bc_stream => { assert(s.a == 7); };
|
||||
case void => { assert(false); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn bare_2lvl() void = {
|
||||
let x: b2_vt;
|
||||
x.a = 7;
|
||||
let v: (void | b2_stream) = &x;
|
||||
assert(v is b2_stream);
|
||||
match (v) {
|
||||
case let s: b2_stream => { assert(s.a == 7); };
|
||||
case void => { assert(false); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn unrel_struct() void = {
|
||||
let s: us_ta;
|
||||
s.a = 4; s.b = 9;
|
||||
let v: (void | us_tb) = s;
|
||||
assert(v is us_tb);
|
||||
};
|
||||
46
test/lang/variant_typekey_test.ww
Normal file
46
test/lang/variant_typekey_test.ww
Normal file
@@ -0,0 +1,46 @@
|
||||
// variant_typekey_test — nominal-type-key variant discrimination. A call-
|
||||
// returned value with no surface name (str or i32) widened into (alias | base)
|
||||
// must tag the structural (base) variant, not the leading alias. Both the str
|
||||
// axis ((linerr|str), linerr=!str) and the scalar axis ((ec|i32), ec=!i32).
|
||||
// Migrated from test/wcc/931_variant_typekey_run.c (value rows, cs==ww).
|
||||
|
||||
package variant_typekey_test;
|
||||
|
||||
type linerr = !str;
|
||||
type ec = !i32;
|
||||
|
||||
fn getstr() str = { return "hi"; };
|
||||
fn produce_str(k: i32) (linerr | str) = {
|
||||
if (k == 0) { return getstr(); };
|
||||
let e: linerr = "boom";
|
||||
return e;
|
||||
};
|
||||
fn classify_str(k: i32) i32 = {
|
||||
match (produce_str(k)) {
|
||||
case let er: linerr => return 1;
|
||||
case let v: str => return 2;
|
||||
};
|
||||
};
|
||||
|
||||
fn getint() i32 = { return 7; };
|
||||
fn produce_int(k: i32) (ec | i32) = {
|
||||
if (k == 0) { return getint(); };
|
||||
let e: ec = 9;
|
||||
return e;
|
||||
};
|
||||
fn classify_int(k: i32) i32 = {
|
||||
match (produce_int(k)) {
|
||||
case let er: ec => return 1;
|
||||
case let v: i32 => return 2;
|
||||
};
|
||||
};
|
||||
|
||||
@test fn linerr_str_alias_first_callret() void = {
|
||||
assert(classify_str(0) == 2);
|
||||
assert(classify_str(1) == 1);
|
||||
};
|
||||
|
||||
@test fn errint_int_alias_first_callret() void = {
|
||||
assert(classify_int(0) == 2);
|
||||
assert(classify_int(1) == 1);
|
||||
};
|
||||
75
test/lang/void_error_singleton_test.ww
Normal file
75
test/lang/void_error_singleton_test.ww
Normal file
@@ -0,0 +1,75 @@
|
||||
// void_error_singleton_test — a `!void` error singleton (tag-only) across
|
||||
// return / let-init / assign / call-arg positions, plus a wide (str) success
|
||||
// payload exercising CX/R8 zeroing on the tag-only return. Migrated from
|
||||
// test/wcc/949_void_error_singleton_run.c (value rows; C driver asserted cs==ww .s).
|
||||
|
||||
package void_error_singleton_test;
|
||||
|
||||
type too_long = !void;
|
||||
|
||||
fn f_ret_singleton() (i64 | too_long) = {
|
||||
return too_long;
|
||||
};
|
||||
|
||||
fn f_ret_success() (i64 | too_long) = {
|
||||
return 42i64;
|
||||
};
|
||||
|
||||
fn use_callarg(r: (i64 | too_long)) i32 = {
|
||||
match (r) {
|
||||
case let v: i64 => return 1;
|
||||
case too_long => return 0;
|
||||
};
|
||||
return 2;
|
||||
};
|
||||
|
||||
fn f_wide(ok: bool) (str | too_long) = {
|
||||
if (ok) { return "hello"; };
|
||||
return too_long;
|
||||
};
|
||||
|
||||
@test fn return_singleton() void = {
|
||||
match (f_ret_singleton()) {
|
||||
case let v: i64 => { assert(false); };
|
||||
case too_long => { };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn return_success() void = {
|
||||
match (f_ret_success()) {
|
||||
case let v: i64 => { assert(v == 42); };
|
||||
case too_long => { assert(false); };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn letinit_singleton() void = {
|
||||
let e: (i64 | too_long) = too_long;
|
||||
match (e) {
|
||||
case let v: i64 => { assert(false); };
|
||||
case too_long => { };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn assign_singleton() void = {
|
||||
let e: (i64 | too_long) = 5i64;
|
||||
e = too_long;
|
||||
match (e) {
|
||||
case let v: i64 => { assert(false); };
|
||||
case too_long => { };
|
||||
};
|
||||
};
|
||||
|
||||
@test fn callarg_singleton() void = {
|
||||
assert(use_callarg(too_long) == 0);
|
||||
};
|
||||
|
||||
@test fn return_singleton_wide() void = {
|
||||
match (f_wide(false)) {
|
||||
case let s: str => { assert(false); };
|
||||
case too_long => { };
|
||||
};
|
||||
match (f_wide(true)) {
|
||||
case let s: str => { assert(s.len == 5); };
|
||||
case too_long => { assert(false); };
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user