harec

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

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