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