harec

[hare] Hare compiler, written in C11 for POSIX OSs
Log | Files | Refs | README | LICENSE

18-match.ha (3663B)


      1 type foo = void;
      2 type bar = void;
      3 type foobar = (foo | bar);
      4 type baz = int;
      5 type foobarbaz = (foobar | baz);
      6 type signed = (i8 | i16 | i32 | i64 | int);
      7 type unsigned = (u8 | u16 | u32 | u64 | uint | size);
      8 type integer = (...signed | ...unsigned);
      9 type align_4 = (void | int);
     10 type align_8 = (void | int | i64);
     11 
     12 fn tagged() void = {
     13 	let cases: [3](int | uint | str) = [10i, 10u, "hello"];
     14 	let expected: [_]size = [1, 2, 5];
     15 	for (let i = 0z; i < len(cases); i += 1) {
     16 		let y: size = match (cases[i]) {
     17 		case int =>
     18 			yield 1;
     19 		case uint =>
     20 			yield 2;
     21 		case let s: str =>
     22 			yield len(s);
     23 		};
     24 		assert(y == expected[i]);
     25 	};
     26 };
     27 
     28 fn termination() void = {
     29 	let x: (int | uint | str) = 1337i;
     30 	for (true) {
     31 		let y: int = match (x) {
     32 		case int =>
     33 			yield 42;
     34 		case uint =>
     35 			abort();
     36 		case str =>
     37 			break;
     38 		};
     39 		assert(y == 42);
     40 		x = "hi";
     41 	};
     42 };
     43 
     44 fn _default() void = {
     45 	let x: (int | uint | str) = 1337u;
     46 	let y: int = match (x) {
     47 	case int =>
     48 		yield 42;
     49 	case =>
     50 		yield 24;
     51 	};
     52 	assert(y == 24);
     53 };
     54 
     55 fn pointer() void = {
     56 	let x = 42;
     57 	let y: nullable *int = &x;
     58 	let z: int = match (y) {
     59 	case let y: *int =>
     60 		yield *y;
     61 	case null =>
     62 		abort();
     63 	};
     64 	assert(z == 42);
     65 
     66 	y = null;
     67 	z = match (y) {
     68 	case *int =>
     69 		abort();
     70 	case null =>
     71 		yield 1337;
     72 	};
     73 	assert(z == 1337);
     74 };
     75 
     76 fn alias() void = {
     77 	let cases: []foobar = [foo, bar];
     78 	let expected = [42, 24];
     79 	for (let i = 0z; i < len(cases); i += 1) {
     80 		let y: int = match (cases[i]) {
     81 		case foo =>
     82 			yield 42;
     83 		case bar =>
     84 			yield 24;
     85 		};
     86 		assert(y == expected[i]);
     87 	};
     88 };
     89 
     90 fn tagged_result() void = {
     91 	let x: (int | uint) = 42i;
     92 	let y: (int | uint) = match (x) {
     93 	case let x: int =>
     94 		yield x;
     95 	case let x: uint =>
     96 		yield x;
     97 	};
     98 	assert(y is int);
     99 
    100 	x = 42u;
    101 	y = match (x) {
    102 	case let x: int =>
    103 		yield x;
    104 	case let x: uint =>
    105 		yield x;
    106 	};
    107 	assert(y is uint);
    108 };
    109 
    110 fn implicit_cast() void = {
    111 	let x: foobar = foo;
    112 	let y: nullable *int = null;
    113 	let a: (int | foobar) = match (y) {
    114 	case null =>
    115 		yield foo;
    116 	case let z: *int =>
    117 		yield *z;
    118 	};
    119 	assert(a is foobar);
    120 };
    121 
    122 fn transitivity() void = {
    123 	let x: (foobar | int) = 10;
    124 	match (x) {
    125 	case let i: int =>
    126 		assert(i == 10);
    127 	case foo =>
    128 		abort();
    129 	case bar =>
    130 		abort();
    131 	};
    132 	x = foo;
    133 	let visit = false;
    134 	match (x) {
    135 	case int =>
    136 		abort();
    137 	case foo =>
    138 		visit = true;
    139 	case bar =>
    140 		abort();
    141 	};
    142 	assert(visit);
    143 
    144 	x = bar;
    145 	visit = false;
    146 	match (x) {
    147 	case int =>
    148 		abort();
    149 	case foo =>
    150 		abort();
    151 	case foobar =>
    152 		visit = true;
    153 	};
    154 	assert(visit);
    155 
    156 	visit = false;
    157 	match (x) {
    158 	case let z: (foo | bar) =>
    159 		visit = true;
    160 		assert(z is bar);
    161 	case int =>
    162 		abort();
    163 	};
    164 	assert(visit);
    165 
    166 	let y: foobarbaz = 10;
    167 	visit = false;
    168 	match (y) {
    169 	case baz =>
    170 		visit = true;
    171 	case foo =>
    172 		abort();
    173 	case bar =>
    174 		abort();
    175 	};
    176 	assert(visit);
    177 
    178 	y = foo;
    179 	visit = false;
    180 	match (y) {
    181 	case baz =>
    182 		abort();
    183 	case foo =>
    184 		visit = true;
    185 	case bar =>
    186 		abort();
    187 	};
    188 	assert(visit);
    189 };
    190 
    191 fn numeric() void = {
    192 	// Real-world test
    193 	let visit = true;
    194 	let x: integer = 1337i;
    195 	match (x) {
    196 	case let s: signed =>
    197 		match (s) {
    198 		case let i: int =>
    199 			visit = true;
    200 			assert(i == 1337);
    201 		case =>
    202 			abort();
    203 		};
    204 	case let u: unsigned =>
    205 		abort();
    206 	};
    207 	assert(visit);
    208 };
    209 
    210 fn alignment_conversion() void = {
    211 	let x: align_8 = 1234i;
    212 	match (x) {
    213 	case let y: align_4 =>
    214 		assert(y as int == 1234);
    215 	case =>
    216 		abort();
    217 	};
    218 	let y: align_4 = 4321i;
    219 	x = y: align_8;
    220 	assert(x as int == 4321);
    221 };
    222 
    223 export fn main() void = {
    224 	tagged();
    225 	termination();
    226 	_default();
    227 	pointer();
    228 	alias();
    229 	tagged_result();
    230 	implicit_cast();
    231 	transitivity();
    232 	numeric();
    233 	alignment_conversion();
    234 	// TODO: Test exhaustiveness and dupe detection
    235 };