harec

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

18-match.ha (3899B)


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