harec

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

34-declarations.ha (11030B)


      1 use rt::{compile, exited, EXIT_SUCCESS};
      2 
      3 def ARR: [3]u8 = [1, 2, 3];
      4 
      5 // interdependent constants
      6 def A1: int = -1;
      7 def A2: int = A1 + 2;
      8 def A3: [A2 + 2]int = [A1, A2, 0];
      9 // reverse order
     10 def B3: [B2 + 2]int = [B1, B2, 0];
     11 def B2: int = B1 + 2;
     12 def B1: int = -1;
     13 
     14 fn constants() void = {
     15 	assert(ARR[0] == 1 && ARR[1] == 2 && ARR[2] == 3);
     16 	assert(A1 == -1 && B1 == -1);
     17 	assert(A2 == 1 && B2 == 1);
     18 	assert(len(B3) == 3);
     19 	assert(A3[0] == -1 && B3[0] == -1);
     20 	assert(A3[1] == 1 && B3[1] == 1);
     21 	assert(A3[2] == 0 && B3[2] == 0);
     22 };
     23 
     24 // elementary self-referential types
     25 type self_slice = []self_slice;
     26 type self_ptr = *self_ptr;
     27 type self_slice_ptr = *[]self_slice_ptr;
     28 type self_ptr_slice = []*self_ptr_slice;
     29 
     30 // type referencing a constant
     31 type arr1 = [sizearr1]str;
     32 def sizearr1: size = 5z;
     33 // reverse order
     34 def sizearr2: size = 5z;
     35 type arr2 = [sizearr2]str;
     36 
     37 // self-referential struct
     38 type struct1 = struct { a: []struct1 };
     39 
     40 // self-referential struct with multiple indirections
     41 type struct2 = struct { a: []**[]**nullable *struct2 };
     42 
     43 // self-referential struct with self-reference having a nonzero offset
     44 type struct3 = struct { a: int, data: *struct3 };
     45 
     46 // struct with multiple self-refences
     47 type struct4 = struct { ptr: *struct4, slice: []struct4, ptr2: *[]struct4 };
     48 
     49 
     50 // self-referential indirect struct
     51 type pstruct1 = []struct { a: pstruct1 };
     52 
     53 // self-referential indirect struct with multiple indirections
     54 type pstruct2 = []***[]struct { a: pstruct2 };
     55 
     56 // self-referential indirect struct with self-reference having a nonzero offset
     57 type pstruct3 = *struct { a: int, data: pstruct3 };
     58 
     59 // indirect struct with multiple self-refences
     60 type pstruct4 = *struct { a: pstruct4, b: [5]pstruct4, c: pstruct4 };
     61 
     62 
     63 // self-referential tagged union
     64 type tagged1 = (*tagged1 | void);
     65 
     66 // self-referential tagged union with multiple indirections
     67 type tagged2 = (***[][]nullable *tagged2 | int);
     68 
     69 // tagged union with multiple self-references
     70 type tagged3 = (*tagged3 | **tagged3 | []tagged3);
     71 
     72 // tagged union with duplicate self-referential members
     73 type tagged4 = (void | *tagged4 | int | *tagged4 | *tagged4 | str);
     74 
     75 
     76 // self-referential indirect tagged union
     77 type ptagged1 = *(ptagged1 | void);
     78 
     79 // self-referential indirect tagged union with multiple indirections
     80 type ptagged2 = []*nullable *[]*(ptagged2 | int);
     81 
     82 // indirect tagged union with multiple self-references
     83 type ptagged3 = *([2]ptagged3 | ptagged3 | (ptagged3, ptagged3));
     84 
     85 // indirect tagged union with duplicate self-referential members
     86 type ptagged4 = [](void | ptagged4 | int | ptagged4 | ptagged4 | str);
     87 
     88 
     89 // self-referential tuple
     90 type tuple1 = (*tuple1, u16);
     91 
     92 // self-referential tuple with multiple indirections
     93 type tuple2 = (***[][]nullable *tuple2, str);
     94 
     95 // tuple with multiple self-references
     96 type tuple3 = (*tuple3, *tuple3, []tuple3);
     97 
     98 
     99 // self-referential indirect tuple
    100 type ptuple1 = *(ptuple1, u16);
    101 
    102 // self-referential indirect tuple with multiple indirections
    103 type ptuple2 = ***[][]nullable *(ptuple2, str);
    104 
    105 // tuple with multiple self-references
    106 type ptuple3 = [](ptuple3, ptuple3, [3]ptuple3);
    107 
    108 
    109 // elementary mutually recursive types
    110 type mut_A1 = *mut_A2, mut_A2 = *mut_A1;
    111 
    112 type mut_A3 = []mut_A4, mut_A4 = []mut_A3;
    113 
    114 type mut_A5 = *mut_A6, mut_A6 = []mut_A5;
    115 
    116 type mut_A7 = []mut_A8, mut_A8 = *mut_A7;
    117 
    118 type mut_A9 = mut_A10, mut_A10 = *mut_A9;
    119 type mut_B10 = *mut_B9, mut_B9 = mut_B10; // reverse
    120 
    121 type mut_A11 = mut_A12, mut_A12 = []mut_A11;
    122 type mut_B12 = []mut_B11, mut_B11 = mut_B12; // reverse
    123 
    124 // mutually recursive structs
    125 type mut_struct_A1 = struct { data: *mut_struct_A2 },
    126 	mut_struct_A2 = struct { data: mut_struct_A1 };
    127 type mut_struct_B2 = struct { data: mut_struct_B1 }, // reverse
    128 	mut_struct_B1 = struct { data: *mut_struct_B2 };
    129 
    130 // mutually recursive structs with padding
    131 type mut_struct_A3 = struct { padding: u16, data: *mut_struct_A4 },
    132 	mut_struct_A4 = struct { padding: u16, data: mut_struct_A3 };
    133 type mut_struct_B4 = struct { padding: u16, data: mut_struct_B3 }, // reverse
    134 	mut_struct_B3 = struct { padding: u16, data: *mut_struct_B4 };
    135 
    136 // mutually recursive indirect structs
    137 type mut_pstruct_A1 = *struct { data: mut_pstruct_A2 },
    138 	mut_pstruct_A2 = struct { data: mut_pstruct_A1 };
    139 type mut_pstruct_B2 = struct { data: mut_pstruct_B1 }, // reverse
    140 	mut_pstruct_B1 = *struct { data: mut_pstruct_B2 };
    141 
    142 // mutually recursive tagged unions
    143 type mut_tagged_A1 = (*mut_tagged_A2 | u8), mut_tagged_A2 = (mut_tagged_A1 | u8);
    144 type mut_tagged_B2 = (mut_tagged_B1 | u8), mut_tagged_B1 = (*mut_tagged_B2 | u8); // reverse
    145 
    146 // mutually recursive tagged unions with repeated members
    147 type mut_tagged_A3 = (*mut_tagged_A4 | u8 | *mut_tagged_A4),
    148 	mut_tagged_A4 = (mut_tagged_A3 | u8 | mut_tagged_A3 | mut_tagged_A3);
    149 type mut_tagged_B4 = (mut_tagged_B3 | u8 | mut_tagged_B3 | mut_tagged_B3), // reverse
    150 	mut_tagged_B3 = (*mut_tagged_B4 | u8 | *mut_tagged_A4);
    151 
    152 // mutually recursive indirect tagged unions
    153 type mut_ptagged_A1 = *(mut_ptagged_A2 | u8), mut_ptagged_A2 = (mut_ptagged_A1 | u8);
    154 type mut_ptagged_B2 = (mut_ptagged_B1 | u8), mut_ptagged_B1 = *(mut_ptagged_B2 | u8); // reverse
    155 
    156 // mutually recursive tuples
    157 type mut_tuple_A1 = (*mut_tuple_A2, u8), mut_tuple_A2 = (mut_tuple_A1, u8);
    158 type mut_tuple_B2 = (mut_tuple_B1, u8), mut_tuple_B1 = (*mut_tuple_B2, u8); // reverse
    159 
    160 // mutually recursive indirect tuples
    161 type mut_ptuple_A1 = *(mut_ptuple_A2, u8), mut_ptuple_A2 = (mut_ptuple_A1, u8);
    162 type mut_ptuple_B2 = (mut_ptuple_B1, u8), mut_ptuple_B1 = *(mut_ptuple_B2, u8); // reverse
    163 
    164 // type with a type dimension dependency
    165 type arri8_A = [size(arrintptr_A)]u8, arrintptr_A = [8]*int;
    166 type arrintptr_B = [8]*int, arri8_B = [size(arrintptr_B)]u8; // reverse
    167 
    168 type arri8_al_A = [align(arrintptr_al_A)]u8, arrintptr_al_A = [8]*int;
    169 type arrintptr_al_B = [8]*int, arri8_al_B = [align(arrintptr_al_B)]u8; // reverse
    170 
    171 // mutually recursive types with a dimension dependency
    172 type arru8_A = [size(arru8ptr_A)]u8, arru8ptr_A = [8]*arru8_A;
    173 type arru8ptr_B = [8]*arru8_B, arru8_B = [size(arru8ptr_B)]u8; // reverse
    174 
    175 type arru8_al_A = [align(arru8ptr_al_A)]u8, arru8ptr_al_A = [8]*arru8_al_A;
    176 type arru8ptr_al_B = [8]*arru8_al_B, arru8_al_B = [align(arru8ptr_al_B)]u8; // reverse
    177 
    178 // unwrapped aliases to tagged unions
    179 type unwrap_A1 = ([32]u8 | void | str),
    180 	unwrap_A2 = (i64 | ...unwrap_A1),
    181 	unwrap_alias_A1 = unwrap_A2,
    182 	unwrap_alias_A2 = unwrap_alias_A1,
    183 	unwrap_alias_A3 = ...unwrap_alias_A2;
    184 type unwrap_alias_B3 = ...unwrap_alias_B2, // reverse
    185 	unwrap_alias_B2 = unwrap_alias_B1,
    186 	unwrap_alias_B1 = unwrap_B2,
    187 	unwrap_B2 = (i64 | ...unwrap_B1),
    188 	unwrap_B1 = ([32]u8 | void | str);
    189 
    190 fn sz() void = {
    191 	// size
    192 	static assert(size(mut_struct_A3) == 2 * size(*void));
    193 	static assert(size(mut_struct_B3) == 2 * size(*void));
    194 
    195 	static assert(size(mut_tagged_A1) == 2 * size(*void));
    196 	static assert(size(mut_tagged_B1) == 2 * size(*void));
    197 
    198 	static assert(size(mut_tagged_A3) == 2 * size(*void));
    199 	static assert(size(mut_tagged_B3) == 2 * size(*void));
    200 
    201 	static assert(size(mut_tagged_A4) == 3 * size(*void));
    202 	static assert(size(mut_tagged_B4) == 3 * size(*void));
    203 
    204 	static assert(size(mut_tuple_A1) == 2 * size(*void));
    205 	static assert(size(mut_tuple_B1) == 2 * size(*void));
    206 
    207 	static assert(size(arru8_A) == 8 * size(*void));
    208 	static assert(size(arru8_B) == 8 * size(*void));
    209 
    210 	static assert(size(arru8ptr_A) == 8 * size(*void));
    211 	static assert(size(arru8ptr_B) == 8 * size(*void));
    212 
    213 	static assert(size(unwrap_A1) == size(unwrap_alias_A3));
    214 	static assert(size(unwrap_B1) == size(unwrap_alias_B3));
    215 
    216 	//align
    217 	static assert(align(mut_struct_A3) == align(*void));
    218 	static assert(align(mut_struct_B3) == align(*void));
    219 
    220 	static assert(align(mut_tagged_A1) == align(*void));
    221 	static assert(align(mut_tagged_B1) == align(*void));
    222 
    223 	static assert(align(mut_tagged_A3) == align(*void));
    224 	static assert(align(mut_tagged_B3) == align(*void));
    225 
    226 	static assert(align(mut_tagged_A4) == align(*void));
    227 	static assert(align(mut_tagged_B4) == align(*void));
    228 
    229 	static assert(align(mut_tuple_A1) == align(*void));
    230 	static assert(align(mut_tuple_B1) == align(*void));
    231 
    232 	static assert(align(arru8_A) == align(u8));
    233 	static assert(align(arru8_B) == align(u8));
    234 
    235 	static assert(align(arru8ptr_A) == align(*void));
    236 	static assert(align(arru8ptr_B) == align(*void));
    237 
    238 	static assert(align(unwrap_A1) == align(unwrap_alias_A3));
    239 	static assert(align(unwrap_B1) == align(unwrap_alias_B3));
    240 };
    241 
    242 fn reject() void = {
    243 	let failures = [
    244 		"type a = b; type b = a;",
    245 		"type a = [20]a;",
    246 		"type a = unknown;",
    247 		"def x: int = 6; type a = x;",
    248 		"type a = int; type a = str;",
    249 		"def a: int = b; def b: int = a;",
    250 		"def x: size = size(t); type t = [x]int;",
    251 		"def a: int = 12; type t = (int |(...a | a));",
    252 		"type a = (...unknown | int);",
    253 
    254 		// usage of non-type aliases
    255 		"let a: int = 4; type x = a;",
    256 		"let a: int = 4; type x = *a;",
    257 		"let a: int = 4; type x = []a;",
    258 		"let a: int = 4; type x = [3]a;",
    259 		"let a: int = 4; type x = (str, a);",
    260 		"let a: int = 4; type x = (str | a);",
    261 		"let a: int = 4; type x = struct { y: str, z: a};",
    262 		"let a: int = 4; type x = union { y: str, z: a};",
    263 		"let a: int = 4; fn x(y: str, z: a) void = { void; };",
    264 
    265 		// binding not directly in compound expression
    266 		"export fn main() void = let a = 4;",
    267 		"export fn main() void = { if (true) let a = 4; };",
    268 	];
    269 
    270 	for (let i = 0z; i < len(failures); i += 1) {
    271 		assert(compile(failures[i]) as exited != EXIT_SUCCESS);
    272 	};
    273 };
    274 
    275 // Types t_0 to t_9 form a complete directed graph on 10 vertices.
    276 // The edge from t_$i to t_$j is indirect if $i > $j, otherwise it is direct.
    277 // This ensures the generated graph is the maximum possible valid dependency
    278 // graph of 10 hare type aliases.
    279 type t_0 = (        t_1,  t_2,  t_3,  t_4,  t_5,  t_6,  t_7,  t_8,  t_9, );
    280 type t_1 = ( *t_0,        t_2,  t_3,  t_4,  t_5,  t_6,  t_7,  t_8,  t_9, );
    281 type t_2 = ( *t_0, *t_1,        t_3,  t_4,  t_5,  t_6,  t_7,  t_8,  t_9, );
    282 type t_3 = ( *t_0, *t_1, *t_2,        t_4,  t_5,  t_6,  t_7,  t_8,  t_9, );
    283 type t_4 = ( *t_0, *t_1, *t_2, *t_3,        t_5,  t_6,  t_7,  t_8,  t_9, );
    284 type t_5 = ( *t_0, *t_1, *t_2, *t_3, *t_4,        t_6,  t_7,  t_8,  t_9, );
    285 type t_6 = ( *t_0, *t_1, *t_2, *t_3, *t_4, *t_5,        t_7,  t_8,  t_9, );
    286 type t_7 = ( *t_0, *t_1, *t_2, *t_3, *t_4, *t_5, *t_6,        t_8,  t_9, );
    287 type t_8 = ( *t_0, *t_1, *t_2, *t_3, *t_4, *t_5, *t_6, *t_7,        t_9, );
    288 type t_9 = ( *t_0, *t_1, *t_2, *t_3, *t_4, *t_5, *t_6, *t_7, *t_8,       );
    289 
    290 fn complete_graph() void = {
    291 	static assert(size(t_9) == 9 * size(*void));
    292 	static assert(size(t_8) == 17 * size(*void));
    293 	static assert(size(t_7) == 33 * size(*void));
    294 	static assert(size(t_6) == 65 * size(*void));
    295 	static assert(size(t_5) == 129 * size(*void));
    296 	static assert(size(t_4) == 257 * size(*void));
    297 	static assert(size(t_3) == 513 * size(*void));
    298 	static assert(size(t_2) == 1025 * size(*void));
    299 	static assert(size(t_1) == 2049 * size(*void));
    300 	static assert(size(t_0) == 4097 * size(*void));
    301 };
    302 
    303 export fn main() void = {
    304 	constants();
    305 	sz();
    306 	reject();
    307 	complete_graph();
    308 };