harec

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

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