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