13-tagged.ha (6308B)
1 use rt::{compile, exited, EXIT_SUCCESS}; 2 3 fn measurements() void = { 4 const x: (u8 | u16 | u32 | u64) = 1337u16; // With padding 5 const alignment: size = 6 if (size(u64) < size(uint)) size(uint) 7 else size(u64); 8 assert(align((u8 | u16 | u32 | u64)) == alignment); 9 assert(size((u8 | u16 | u32 | u64)) == alignment * 2); 10 assert(&x: uintptr: size % size(uint) == 0); 11 assert(&x: uintptr: size % size(u64) == 0); 12 13 const y: (u8 | u16) = 1337u16; // No padding 14 assert(align((u8 | u16)) == align(uint)); 15 assert(align(((u8 | u16) | (i8 | i16))) == align(uint)); 16 }; 17 18 fn storage() void = { 19 let x: (u8 | u16 | u32 | u64) = 42u8; 20 const y = &x: *struct { 21 tag: uint, 22 union { _u8: u8, _u16: u16, _u32: u32, _u64: u64 }, 23 }; 24 assert(y.tag == 1906196061); // u8 type ID 25 assert(y._u8 == 42); 26 27 x = 1337u16; 28 assert(y.tag == 2206074632); // u16 type ID 29 assert(y._u16 == 1337); 30 31 x = 0xCAFEBABEu32; 32 assert(y.tag == 4119164483); // u32 type ID 33 assert(y._u32 == 0xCAFEBABE); 34 35 x = 0xCAFEBABEDEADBEEFu64; 36 assert(y.tag == 3481467866); // u64 type ID 37 assert(y._u64 == 0xCAFEBABEDEADBEEF); 38 }; 39 40 fn operators() void = { 41 let x: (u8 | u16 | u32 | u64) = 42u8; 42 assert(x is u8); 43 x = 1337u16; 44 assert(x is u16); 45 x = 0xCAFEBABEu32; 46 assert(x is u32); 47 x = 0xCAFEBABEDEADBEEFu64; 48 assert(x is u64); 49 }; 50 51 type signed = (i8 | i16 | i32 | i64 | int); 52 type unsigned = (u8 | u16 | u32 | u64 | uint); 53 type integer = (...signed | ...unsigned); 54 55 fn reduction() void = { 56 const a: (i8 | i16) = 42i8; 57 const b: (i16 | i8) = a; 58 const c: (i8 | i16 | i32) = a; 59 const d: (i8 | i16 | i8 | i16) = a; 60 assert(compile( 61 // Cannot reduce to a single member 62 "fn test() void = { 63 let a: (u8 | u8) = 42u8; 64 };" 65 ) as exited != EXIT_SUCCESS); 66 assert(compile( 67 // Cannot assign from more general type 68 "fn test() void = { 69 let a: (i8 | i16 | i32) = 42i8; 70 let b: (i8 | i16) = a; 71 };" 72 ) as exited != EXIT_SUCCESS); 73 assert(a is i8 && b is i8 && c is i8 && d is i8); 74 assert(size((i8 | i16 | i32)) == size((i8 | (i16 | i32)))); 75 assert(size(integer) == size(signed)); 76 assert(size(integer) != size((signed | unsigned))); 77 const i: integer = 10i; 78 assert(i is int); 79 }; 80 81 fn casts() void = { 82 let a: (u8 | u16) = 42u16; 83 assert(a as u16 == 42); 84 let x = a: u8; 85 assert(x == 42); 86 87 const val = 0xBEEFu16; 88 const is_little = (&val: *[2]u8)[0] == 0xEF; 89 a = 0xCAFEu16; 90 x = a: u8; 91 assert(x == (if (is_little) 0xFEu8 else 0xCAu8)); 92 }; 93 94 fn membercast() void = { 95 // Simple case 96 let x: (int | void) = void; 97 let p = &x: *struct { 98 id: uint, 99 data: int, 100 }; 101 assert(p.id == 2543892678); 102 x = 1337; 103 assert(p.id == 1099590421); 104 assert(p.data == 1337); 105 106 // Align of 4 107 let x: (int | f32 | void) = 1337; 108 let p = &x: *struct { 109 id: uint, 110 data: union { 111 idata: int, 112 fdata: f32, 113 }, 114 }; 115 assert(p.id == 1099590421); 116 assert(p.data.idata == 1337); 117 x = 13.37f32; 118 assert(p.id == 1568378015); 119 assert(p.data.fdata == 13.37f32); 120 121 // Align of 8 122 let x: (size | void) = 1337z; 123 let p = &x: *struct { 124 id: uint, 125 data: size, 126 }; 127 assert(p.id == 1737287038); 128 assert(p.data == 1337z); 129 }; 130 131 fn subsetcast() void = { 132 // Equal alignment 133 // subset -> superset 134 let x: (size | void) = 1337z; 135 let y: (size | int | void) = x; 136 let p = &y: *struct { 137 tag: uint, 138 data: union { 139 z: size, 140 i: int, 141 }, 142 }; 143 assert(p.tag == 1737287038); 144 assert(p.data.z == 1337z); 145 // superset -> subset 146 let x: (size | void | int) = 2z; 147 assert(x: (size | void) as size == 2); 148 assert(x as (size | void) as size == 2); 149 assert(x is (size | void) && (x is size) && !(x is void)); 150 151 // Disjoint alignment 152 // subset -> superset 153 let x: (int | void) = 1337; 154 let y: (size | int | void) = x; 155 let p = &y: *struct { 156 tag: uint, 157 data: union { 158 z: size, 159 i: int, 160 }, 161 }; 162 assert(p.tag == 1099590421); 163 assert(p.data.i == 1337); 164 // superset -> subset 165 let x: (size | int | void) = 2i; 166 assert(x: (int | void) as int == 2); 167 assert(x as (int | void) as int == 2); 168 assert(x is (int | void) && (x is int) && !(x is void)); 169 }; 170 171 type foo = (int | void); 172 type bar = (size | foo); 173 type t1 = t2; 174 type t2 = int; 175 type t3 = (t2 | void); 176 type t4 = t2; 177 type t5 = (t4 | void); 178 179 fn castout() void = { 180 let x: (int | void) = 1337; 181 assert(x: int == 1337); 182 assert(x as int == 1337); 183 assert(x is int); 184 // XXX: We can probably expand this 185 186 let a: bar = 42i; 187 assert(a as int == 42); 188 assert(a: int == 42); 189 assert(a is int); 190 191 const a: t1 = 42; 192 const x = a: t3; 193 assert(x as t2 == 42); 194 const x = a: t5; 195 assert(x as t4 == 42); 196 }; 197 198 fn assertions() void = { 199 let a: (u8 | u16) = 42u16; 200 assert(a is u16); 201 assert(a as u16 == 42u16); 202 }; 203 204 fn reject() void = { 205 // cannot type assert into a disjoint tagged type 206 assert(compile( 207 "fn test() void = { 208 let a: (u8 | u16) = 42u8; 209 let b = a as (str | void); 210 };" 211 ) as exited != EXIT_SUCCESS); 212 213 // cannot type assert into non-member type 214 assert(compile( 215 "fn test() void = { 216 let a: (u8 | u16) = 42u8; 217 let b = a as *str; 218 };" 219 ) as exited != EXIT_SUCCESS); 220 221 // cannot type assert into superset 222 assert(compile( 223 "fn test() void = { 224 let a: (u8 | u16) = 42u8; 225 let b = a as (u8 | u16 | void); 226 };" 227 ) as exited != EXIT_SUCCESS); 228 229 // cannot type assert into the same type 230 assert(compile( 231 "fn test() void = { 232 let a: (u8 | u16) = 42u8; 233 let b = a as (u8 | u16); 234 };" 235 ) as exited != EXIT_SUCCESS); 236 237 // cannot have members of undefined size 238 assert(compile( 239 "fn test() (void | [*]int) = { 240 void; 241 };" 242 ) as exited != EXIT_SUCCESS); 243 244 // cannot have <2 members 245 assert(compile( 246 "fn test() (void | void) = { 247 void; 248 };" 249 ) as exited != EXIT_SUCCESS); 250 }; 251 252 def val1: integer = 8u8; 253 def val1val: u8 = val1 as u8; 254 def val1type: bool = val1 is u8; 255 def val2: integer = val1; 256 def val2val: u8 = val2 as u8; 257 def val2type: bool = val2 is u8; 258 def val3: integer = 8u8: u16; 259 def val3val: u16 = val3 as u16; 260 def val3type: bool = val3 is u16; 261 262 fn translation() void = { 263 assert(val1 as u8 == 8u8); 264 assert(val1val == 8u8); 265 assert(val1type == true); 266 assert(val2 as u8 == 8u8); 267 assert(val2val == 8u8); 268 assert(val2type == true); 269 assert(val3 as u16 == 8u16); 270 assert(val3val == 8u16); 271 assert(val3type == true); 272 }; 273 274 export fn main() void = { 275 measurements(); 276 storage(); 277 operators(); 278 reduction(); 279 casts(); 280 membercast(); 281 subsetcast(); 282 castout(); 283 assertions(); 284 reject(); 285 translation(); 286 };