00-constants.ha (14068B)
1 use rt::{compile, exited, EXIT_SUCCESS, toutf8}; 2 3 type my_enum = enum u8 { 4 FOO, 5 }; 6 7 fn assignment() void = { 8 let i = 0i8; 9 let u = 0u64; 10 let f = 0.0f64; 11 let r = 'a'; 12 let e = my_enum::FOO; 13 14 // There are five cases that need to be tested for tagged unions: 15 // - The default type for the constant is a member of the union 16 // - A single non-default type the constant could assume is a member of 17 // the union 18 // - The default type for the constant along with at least one other 19 // type the constant could assume are both members of the union 20 // - At least two types the constant could assume are members of the 21 // union, and the default type isn't a member of the union 22 // - None of the types the constant could assume are members of the 23 // union 24 // All but the fourth and fifth case are valid, and the invalid cases 25 // should error out gracefully. 26 let itu1: (int | void) = void; 27 let itu2: (u64 | void) = void; 28 let itu3: (int | u64 | void) = void; 29 let ftu1: (f64 | void) = void; 30 let ftu2: (f32 | void) = void; 31 let ftu3: (f32 | f64 | void) = void; 32 let rtu1: (rune | void) = void; 33 let rtu2: (u64 | void) = void; 34 let rtu3: (rune | u64 | void) = void; 35 36 i = 127; 37 u = 18446744073709551615; 38 e = 0; 39 itu1 = 0; 40 itu2 = 0; 41 itu3 = 0; 42 f = 0.0; 43 ftu1 = 0.0; 44 ftu2 = 0.0; 45 ftu3 = 0.0; 46 47 i = 'a'; 48 u = 'a'; 49 r = 'a'; 50 e = 'a'; 51 rtu1 = 'a'; 52 rtu2 = 'a'; 53 rtu3 = 'a'; 54 assert(rtu3 is rune); 55 let u2: uint = 'a'; 56 let u2: uintptr = 'a'; 57 let z: size = 'a'; 58 59 let failures = [ 60 "fn f() void = { let i = 0i8; i = 128; };", 61 62 "fn f() void = { let u = 0u32; u = 4294967296; };", 63 "fn f() void = { let f = 0.0f64; f = 0; };", 64 "fn f() void = { let r = 'a'; r = 0; };", 65 66 "type my_enum = enum u8 { FOO }; fn f() void = { let e: my_enum = my_enum::FOO; e = 256; };", 67 "fn f() void = { let p: nullable *void = null; p = 0; };", 68 "fn f() void = { let b = false; b = 0; };", 69 "fn f() void = { let n = null; n = 0; };", 70 "fn f() void = { let s: struct { i: int } = struct { i: int = 0 }; s = 0; };", 71 "fn f() void = { let t = (0, 1); t = 0; };", 72 "fn f() void = { let a = [0, 1]; a = 0; };", 73 "fn f() void = { let s = \"\"; s = 0; };", 74 75 "fn f() void = { let itu4: (u32 | u64 | void) = void; itu4 = 0; };", 76 "fn f() void = { let itu5: (str | void) = void; itu5 = 0; };", 77 78 "fn f() void = { let i = 0i8; i = 0.0; };", 79 "fn f() void = { let u = 0u8; u = 0.0; };", 80 81 "fn f() void = { let r = 'a'; r = 0.0; };", 82 "type my_enum = enum u8 { FOO }; fn f() void = { let e: my_enum = my_enum::FOO; e = 0.0; };", 83 "fn f() void = { let p: nullable *void = null; p = 0.0; };", 84 "fn f() void = { let b = false; b = 0.0; };", 85 "fn f() void = { let n = null; n = 0.0; };", 86 "fn f() void = { let s: struct { i: int } = struct { i: int = 0 }; s = 0.0; };", 87 "fn f() void = { let t = (0, 1); t = 0.0; };", 88 "fn f() void = { let a = [0, 1]; a = 0.0; };", 89 "fn f() void = { let s = ""; s = 0.0; };", 90 91 "type my_f32 = f32; fn f() void = { let ftu4: (f32 | my_f32 | void) = void; ftu4 = 0.0; };", 92 "fn f() void = { let ftu5: (str | void) = void; ftu5 = 0.0; };", 93 94 "type my_f32 = f32; fn f() void = { let ftu4: (f32 | my_f32 | void) = void; ftu4 = 0.0; };", 95 "fn f() void = { let ftu5: (str | void) = void; ftu5 = 0.0; };", 96 97 "fn f() void = { let f = 0.0f64; f = 'a'; };", 98 99 "fn f() void = { let p: nullable *void = null; p = 'a'; };", 100 "fn f() void = { let b = false; b = 'a'; };", 101 "fn f() void = { let n = null; n = 'a'; };", 102 "fn f() void = { let s: struct { i: int } = struct { i: int = 0 }; s = 'a'; };", 103 "fn f() void = { let t = (0, 1); t = 'a'; };", 104 "fn f() void = { let a = [0, 1]; a = 'a'; };", 105 "fn f() void = { let s = ""; s = 'a'; };", 106 107 "fn f() void = { let rtu4: (u32 | u64 | void) = void; rtu4 = 'a'; };", 108 "fn f() void = { let rtu5: (str | void) = void; rtu5 = 'a'; };", 109 ]; 110 111 for (let i = 0z; i < len(failures); i += 1) { 112 assert(compile(failures[i]) as exited != EXIT_SUCCESS); 113 }; 114 }; 115 116 fn aggregates() void = { 117 // Pointers 118 119 // Kinda hacky way to verify that something has the expected type 120 // The variables are necessary in order to avoid type hints, which would 121 // avoid verifying that constants are lowered when entering aggregate 122 // types 123 let maxiptr = if (true) alloc(2147483647) else void; 124 free(maxiptr as *int); 125 let miniptr = if (true) alloc(-2147483648) else void; 126 free(miniptr as *int); 127 let smalli64ptr = if (true) alloc(2147483648) else void; 128 free(smalli64ptr as *i64); 129 let negi64ptr = if (true) alloc(-2147483649) else void; 130 free(negi64ptr as *i64); 131 let maxi64ptr = if (true) alloc(9223372036854775807) else void; 132 free(maxi64ptr as *i64); 133 // -9223372036854775808 can't be made to work without lots of hacks 134 let mini64ptr = if (true) alloc(-9223372036854775807) else void; 135 free(mini64ptr as *i64); 136 let fptr = if (true) alloc(0.0) else void; 137 free(fptr as *f64); 138 let rptr = if (true) alloc('a') else void; 139 free(rptr as *rune); 140 141 // Tuples 142 143 // The edge cases of the iconst lowering algorithm were already tested 144 // above, and tuple items can't affect each other, so this suffices 145 let tuple = if (true) (2147483647, 0.0, 'a') else void; 146 tuple as (int, f64, rune); 147 148 // Arrays 149 let iarr = if (true) [0, 1, 2] else void; 150 iarr as [3]int; 151 let uarr = if (true) [0u8, 1, 2] else void; 152 uarr as [3]u8; 153 let u2arr = if (true) [0, 1u8, 2] else void; 154 u2arr as [3]u8; 155 }; 156 157 fn numeric() void = { 158 let want: [_]i64 = [ 159 42, 42, 42, 42, 42, 42, 42, 42, 160 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 161 100, 100, 100, 100 162 ]; 163 let i = [ 164 // basics 165 (42, 42i, 42i8, 42i16, 42i32, 42i64), // decimal 166 (42e0, 42e0i, 42e0i8, 42e0i16, 42e0i32, 42e0i64), // with exp 167 (42e00, 42e00i, 42e00i8, 42e00i16, 42e00i32, 42e00i64), // with leading zeros in exp 168 (42e+0, 42e+0i, 42e+0i8, 42e+0i16, 42e+0i32, 42e+0i64), // with + in exp 169 (42e+00, 42e+00i, 42e+00i8, 42e+00i16, 42e+00i32, 42e+00i64), // with + and leading zeros in exp 170 (0b101010, 0b101010i, 0b101010i8, 0b101010i16, 0b101010i32, 0b101010i64), // binary 171 (0o52, 0o52i, 0o52i8, 0o52i16, 0o52i32, 0o52i64), // octal 172 (0x2a, 0x2ai, 0x2ai8, 0x2ai16, 0x2ai32, 0x2ai64), // hex 173 174 // single digit 175 (0, 0i, 0i8, 0i16, 0i32, 0i64), // zero 176 (0b0, 0b0i, 0b0i8, 0b0i16, 0b0i32, 0b0i64), // binary 177 (0o0, 0o0i, 0o0i8, 0o0i16, 0o0i32, 0o0i64), // octal 178 (0x0, 0x0i, 0x0i8, 0x0i16, 0x0i32, 0x0i64), // hex 179 180 (1, 1i, 1i8, 1i16, 1i32, 1i64), // nonzero 181 (0b1, 0b1i, 0b1i8, 0b1i16, 0b1i32, 0b1i64), // binary 182 (0o1, 0o1i, 0o1i8, 0o1i16, 0o1i32, 0o1i64), // octal 183 (0x1, 0x1i, 0x1i8, 0x1i16, 0x1i32, 0x1i64), // hex 184 185 // with leading zero 186 (0b00, 0b00i, 0b00i8, 0b00i16, 0b00i32, 0b00i64), // binary 187 (0o00, 0o00i, 0o00i8, 0o00i16, 0o00i32, 0o00i64), // octal 188 (0x00, 0x00i, 0x00i8, 0x00i16, 0x00i32, 0x00i64), // hex 189 190 (0b01, 0b01i, 0b01i8, 0b01i16, 0b01i32, 0b01i64), // binary with leading zero 191 (0o01, 0o01i, 0o01i8, 0o01i16, 0o01i32, 0o01i64), // octal 192 (0x01, 0x01i, 0x01i8, 0x01i16, 0x01i32, 0x01i64), // hex 193 194 // exponents 195 (1e2, 1e2i, 1e2i8, 1e2i16, 1e2i32, 1e2i64), 196 (1e02, 1e02i, 1e02i8, 1e02i16, 1e02i32, 1e02i64), // with leading zeros in exp 197 (1e+2, 1e+2i, 1e+2i8, 1e+2i16, 1e+2i32, 1e+2i64), // with + in exp 198 (1e+02, 1e+02i, 1e+02i8, 1e+02i16, 1e+02i32, 1e+02i64), // with + and leading zeros in exp 199 ]; 200 for (let j = 0z; j < len(i); j += 1) { 201 let t = &i[j]; 202 assert(want[j] == t.0 && t.0 == t.1 && t.1 == t.2 && t.2 == t.3 203 && t.3 == t.4 && t.4 == t.5); 204 }; 205 206 let u = [ 207 // basics 208 (42z, 42u, 42u8, 42u16, 42u32, 42u64), // decimal 209 (42e0z, 42e0u, 42e0u8, 42e0u16, 42e0u32, 42e0u64), // with exp 210 (42e00z, 42e00u, 42e00u8, 42e00u16, 42e00u32, 42e00u64), // with leading zeros in exp 211 (42e+0z, 42e+0u, 42e+0u8, 42e+0u16, 42e+0u32, 42e+0u64), // with + in exp 212 (42e+00z, 42e+00u, 42e+00u8, 42e+00u16, 42e+00u32, 42e+00u64), // with + and leading zeros in exp 213 (0b101010z, 0b101010u, 0b101010u8, 0b101010u16, 0b101010u32, 0b101010u64), // binary 214 (0o52z, 0o52u, 0o52u8, 0o52u16, 0o52u32, 0o52u64), // octal 215 (0x2az, 0x2au, 0x2au8, 0x2au16, 0x2au32, 0x2au64), // hex 216 217 // single digit 218 (0z, 0u, 0u8, 0u16, 0u32, 0u64), // zero 219 (0b0z, 0b0u, 0b0u8, 0b0u16, 0b0u32, 0b0u64), // binary 220 (0o0z, 0o0u, 0o0u8, 0o0u16, 0o0u32, 0o0u64), // octal 221 (0x0z, 0x0u, 0x0u8, 0x0u16, 0x0u32, 0x0u64), // hex 222 223 (1z, 1u, 1u8, 1u16, 1u32, 1u64), // nonzero 224 (0b1z, 0b1u, 0b1u8, 0b1u16, 0b1u32, 0b1u64), // binary 225 (0o1z, 0o1u, 0o1u8, 0o1u16, 0o1u32, 0o1u64), // octal 226 (0x1z, 0x1u, 0x1u8, 0x1u16, 0x1u32, 0x1u64), // hex 227 228 // with leading zero 229 (0b00z, 0b00u, 0b00u8, 0b00u16, 0b00u32, 0b00u64), // binary 230 (0o00z, 0o00u, 0o00u8, 0o00u16, 0o00u32, 0o00u64), // octal 231 (0x00z, 0x00u, 0x00u8, 0x00u16, 0x00u32, 0x00u64), // hex 232 233 (0b01z, 0b01u, 0b01u8, 0b01u16, 0b01u32, 0b01u64), // binary with leading zero 234 (0o01z, 0o01u, 0o01u8, 0o01u16, 0o01u32, 0o01u64), // octal 235 (0x01z, 0x01u, 0x01u8, 0x01u16, 0x01u32, 0x01u64), // hex 236 237 // exponents 238 (1e2z, 1e2u, 1e2u8, 1e2u16, 1e2u32, 1e2u64), 239 (1e02z, 1e02u, 1e02u8, 1e02u16, 1e02u32, 1e02u64), // with leading zeros in exp 240 (1e+2z, 1e+2u, 1e+2u8, 1e+2u16, 1e+2u32, 1e+2u64), // with + in exp 241 (1e+02z, 1e+02u, 1e+02u8, 1e+02u16, 1e+02u32, 1e+02u64), // with + and leading zeros in exp 242 ]; 243 for (let j = 0z; j < len(u); j += 1) { 244 let t = &u[j]; 245 assert(want[j]: u64 == t.0: u64 && t.0: u64 == t.1 246 && t.1 == t.2 && t.2 == t.3 && t.3 == t.4 && t.4 == t.5); 247 }; 248 249 let f = [0.0, 0.00, 0.0e0, 0.00e0, 0.0e1, 0.00e1, 0.0e+0, 0.0e+1, 0.0e-0, 0.0e00, 250 0.0e01, 0.0e+01, 0.0e+00, 0.0e-00, 0e-0, 0e-00, 0e-1, 0e-01]; 251 for (let j = 0z; j < len(f); j+= 1) { 252 assert(f[j] == 0.0); 253 }; 254 255 let _f32 = [0.0f32, 0.00f32, 0.0e0f32, 0.00e0f32, 0.0e1f32, 0.00e1f32, 0.0e+0f32, 256 0.0e+1f32, 0.0e-0f32, 0.0e00f32, 0.0e01f32, 0.0e+01f32, 0.0e+00f32, 0.0e-00, 257 0f32, 0e0f32, 0e1f32, 0e00f32, 0e01f32, 0e+0f32, 0e+00f32, 0e+1f32, 258 0e+01f32, 0e-0f32, 0e-00f32, 0e-1f32, 0e-01f32]; 259 for (let j = 0z; j < len(_f32); j+= 1) { 260 assert(_f32[j] == 0f32); 261 }; 262 263 let _f64 = [0.0f64, 0.00f64, 0.0e0f64, 0.00e0f64, 0.0e1f64, 0.00e1f64, 0.0e+0f64, 264 0.0e+1f64, 0.0e-0f64, 0.0e00f64, 0.0e01f64, 0.0e+01f64, 0.0e+00f64, 0.0e-00, 265 0f64, 0e0f64, 0e1f64, 0e00f64, 0e01f64, 0e+0f64, 0e+00f64, 0e+1f64, 266 0e+01f64, 0e-0f64, 0e-00f64, 0e-1f64, 0e-01f64]; 267 for (let j = 0z; j < len(_f64); j+= 1) { 268 assert(_f64[j] == 0f64); 269 }; 270 271 // double tuple subscript special case 272 let tup = (('a', 'b'), 'c'); 273 assert(tup.0.0 == 'a'); 274 // exponents 275 assert(tup.0e0.0 == 'a'); 276 assert(tup.0.0e0 == 'a'); 277 assert(tup.0e0.0e0 == 'a'); 278 assert(tup.0e+0.0 == 'a'); 279 assert(tup.0.0e+0 == 'a'); 280 assert(tup.0e+0.0e+0 == 'a'); 281 // signed 282 assert(tup.0i.0 == 'a'); 283 assert(tup.0.0i == 'a'); 284 assert(tup.0i.0i == 'a'); 285 assert(tup.0i32.0 == 'a'); 286 assert(tup.0.0i32 == 'a'); 287 assert(tup.0i32.0i32 == 'a'); 288 // unsigned 289 assert(tup.0u.0 == 'a'); 290 assert(tup.0.0u == 'a'); 291 assert(tup.0u.0u == 'a'); 292 assert(tup.0u32.0 == 'a'); 293 assert(tup.0.0u32 == 'a'); 294 assert(tup.0u32.0u32 == 'a'); 295 // bases 296 assert(tup.0b0.0 == 'a'); 297 assert(tup.0.0b0 == 'a'); 298 assert(tup.0b0.0b0 == 'a'); 299 assert(tup.0o0.0 == 'a'); 300 assert(tup.0.0o0 == 'a'); 301 assert(tup.0o0.0o0 == 'a'); 302 assert(tup.0x0.0 == 'a'); 303 assert(tup.0.0x0 == 'a'); 304 assert(tup.0x0.0x0 == 'a'); 305 306 // zero with large exponent 307 assert(0e10000000 == 0); 308 assert(0e010000000 == 0); 309 assert(0e+10000000 == 0); 310 assert(0e+010000000 == 0); 311 312 // f32 and f64 are valid hex literals 313 assert(0xf32 == 3890); 314 assert(0xf64 == 3940); 315 assert(0x1f32 == 7986); 316 assert(0x1f64 == 8036); 317 assert(0xf321 == 62241); 318 assert(0xf641 == 63041); 319 320 321 // e is a valid hex digit 322 assert(0xe == 14); 323 assert(0xe+1 == 15); 324 assert(0xe-1 == 13); 325 assert(0x1e == 30); 326 assert(0x1e+1 == 31); 327 assert(0x1e-1 == 29); 328 assert(0x1e1 == 481); 329 assert(0x1e1f32 == 1974066); 330 331 let v = if (true) 5else 10; 332 assert(v == 5); 333 334 let invalid: [_]str = [ 335 336 // invalid base 337 "0b", "0o", // 0x tested separately 338 "00b", "00o", "00x", 339 "01b", "01o", "01x", 340 "1b", "1o", "1x", 341 "11b", "11o", "11x", 342 343 // base with exponent 344 "0b1e1", 345 "0o1e1", 346 // with +/- 347 "0b1e+1", 348 "0o1e+1", 349 350 // invalid digits in smaller bases 351 "0b41", "0b14", 352 "0o82", "0o28", 353 354 // leading zeroes 355 "05", "00000010", "00.0", "01.0", 356 "05e3", "00000010e3", "00.0e3", "01.0e3", 357 "05e+3", "00000010e+3", "00.0e+3", "01.0e+3", 358 "05e-3", "00000010e-3", "00.0e-3", "01.0e-3", 359 360 // invalid sequences of special characters 361 "1.", 362 "1..", 363 "1..1", 364 "1.1.", 365 "1.1.1", 366 367 "1e", 368 "1e+", 369 "1e-", 370 371 "1e1+", 372 "1e1-", 373 374 "1ee", 375 "1e+e", "1ee+", "1e+e+", 376 "1e-e", "1ee-", "1e-e-", 377 "1e+e-", "1e-e+", 378 379 "1ee1", 380 "1e+e1", "1ee+1", "1e+e+1", 381 "1e-e1", "1ee-1", "1e-e-1", 382 "1e+e-1", "1e-e+1", 383 384 "1e1e", 385 "1e+1e", "1e1e+", "1e+1e+", 386 "1e-1e", "1e1e-", "1e-1e-", 387 "1e+1e-", "1e-1e+", 388 389 "1e1e1", 390 "1e+1e1", "1e1e+1", "1e+1e+1", 391 "1e-1e1", "1e1e-1", "1e-1e-1", 392 "1e+1e-1", "1e-1e+1", 393 394 "1.e", "1e.", 395 "1.e1", "1e.1", 396 "1.1e", "1e1.", 397 "1e1.1", 398 399 "1.e+", "1e+.", 400 "1.e+1", "1e+.1", 401 "1.1e+", "1e+1.", 402 "1e+1.1", 403 404 "1.e-", "1e-.", 405 "1.e-1", "1e-.1", 406 "1.1e-", "1e-1.", 407 "1e-1.1", 408 ]; 409 let extra: [_]str = [ 410 "4e-0i;", "4e-1i;", 411 "4e-0i8;", "4e-1i8;", 412 413 "0b1e-1f32;", 414 "0o1e-1f32;", 415 "0x1e+1f32;", 416 "0x1e-1f32;", 417 418 // exponent overflow 419 "let t: u64 = 1e1000;", 420 ]; 421 let suffix = [";", "i;", "i8;", "f32;"]; 422 let buf: [256]u8 = [0...]; 423 for (let i = 0z; i < len(invalid); i += 1) { 424 for (let j = 0z; j < len(suffix); j += 1) { 425 let buf = buf[..0]; 426 append(buf, toutf8("let t = ")...); 427 append(buf, toutf8(invalid[i])...); 428 append(buf, toutf8(suffix[j])...); 429 assert(compile(*(&buf: *str)) as exited != EXIT_SUCCESS); 430 }; 431 }; 432 for (let i = 0z; i < len(extra); i += 1) { 433 assert(compile(extra[i]) as exited != EXIT_SUCCESS); 434 }; 435 }; 436 437 fn basics() void = { 438 let b1 = true, b2 = false; 439 let p1: nullable *int = null; 440 let r1 = ['x', '\x0A', '\u1234', '\0', '\a', '\b', '\f', '\n', '\r', '\t', 441 '\v', '\\', '\'', '\"', '\U12345678']; 442 }; 443 444 export fn main() void = { 445 // The interaction between constants and result type reduction is tested 446 // in 30-reduction.c 447 basics(); 448 numeric(); 449 assignment(); 450 aggregates(); 451 };