hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

+test.ha (10313B)


      1 // License: MPL-2.0
      2 // (c) 2022 Alexey Yerin <yyp@disroot.org>
      3 // (c) 2021 Bor Grošelj Simić <bor.groseljsimic@telemach.net>
      4 // (c) 2021 Drew DeVault <sir@cmpwn.com>
      5 // (c) 2021 Ember Sawady <ecs@d2evs.net>
      6 // (c) 2022 Sebastian <sebastian@sebsite.pw>
      7 use errors;
      8 use fmt;
      9 use hare::ast;
     10 use hare::lex;
     11 use hare::parse;
     12 use io;
     13 use memio;
     14 use strings;
     15 
     16 fn parse_type(in: str) ast::_type = {
     17 	let buf = memio::fixed(strings::toutf8(in));
     18 	let lex = lex::init(&buf, "<test>");
     19 	defer lex::finish(&lex);
     20 	return parse::_type(&lex)!;
     21 };
     22 
     23 @test fn store() void = {
     24 	let st = store(x86_64, null, null);
     25 	defer store_free(st);
     26 
     27 	let atype = parse_type("int");
     28 	defer ast::type_finish(atype);
     29 	let htype = lookup(st, &atype)!;
     30 	assert(htype.repr as builtin == builtin::INT);
     31 	assert(htype.sz == x86_64._int && htype._align == x86_64._int);
     32 
     33 	let type2 = lookup(st, &atype)!;
     34 	assert(htype == type2, "types should be singletons");
     35 
     36 	let atype = parse_type("*int");
     37 	defer ast::type_finish(atype);
     38 	let htype = lookup(st, &atype)!;
     39 	assert(htype.sz == x86_64._pointer && htype._align == x86_64._pointer);
     40 	let htype = htype.repr as pointer;
     41 	assert(htype.referent.repr as builtin == builtin::INT);
     42 };
     43 
     44 fn resolve(
     45 	rstate: nullable *void,
     46 	store: *typestore,
     47 	expr: const *ast::expr,
     48 ) (size | deferred | error) = {
     49 	let expr = expr.expr as ast::constant_expr;
     50 	let n = expr as ast::number_constant;
     51 	let ival = n.value as i64;
     52 	assert(ival >= 0);
     53 	return ival: size;
     54 };
     55 
     56 @test fn structs() void = {
     57 	let st = store(x86_64, &resolve, null);
     58 	defer store_free(st);
     59 
     60 	// Basic struct
     61 	let atype = parse_type("struct { x: int, y: int }");
     62 	defer ast::type_finish(atype);
     63 	let htype = lookup(st, &atype)!;
     64 	assert(htype.sz == 8);
     65 	assert(htype._align == 4);
     66 	let stype = htype.repr as _struct;
     67 	assert(stype.kind == struct_union::STRUCT);
     68 	assert(len(stype.fields) == 2);
     69 
     70 	let x = stype.fields[0];
     71 	assert(x.name == "x");
     72 	assert(x.offs == 0);
     73 	assert(x._type.repr as builtin == builtin::INT);
     74 
     75 	let y = stype.fields[1];
     76 	assert(y.name == "y");
     77 	assert(y.offs == 4);
     78 	assert(y._type.repr as builtin == builtin::INT);
     79 
     80 	// Basic union
     81 	let atype = parse_type("union { x: int, y: int }");
     82 	defer ast::type_finish(atype);
     83 	let htype = lookup(st, &atype)!;
     84 	assert(htype.sz == 4);
     85 	assert(htype._align == 4);
     86 	let stype = htype.repr as _struct;
     87 	assert(stype.kind == struct_union::UNION);
     88 	assert(len(stype.fields) == 2);
     89 
     90 	let x = stype.fields[0];
     91 	assert(x.name == "x");
     92 	assert(x.offs == 0);
     93 	assert(x._type.repr as builtin == builtin::INT);
     94 
     95 	let y = stype.fields[1];
     96 	assert(y.name == "y");
     97 	assert(y.offs == 0);
     98 	assert(y._type.repr as builtin == builtin::INT);
     99 
    100 	// Padding
    101 	let atype = parse_type("struct { w: u8, x: u32, y: u8, z: u64 }");
    102 	defer ast::type_finish(atype);
    103 	let htype = lookup(st, &atype)!;
    104 	assert(htype.sz == 24);
    105 	assert(htype._align == 8);
    106 	let stype = htype.repr as _struct;
    107 	assert(stype.kind == struct_union::STRUCT);
    108 
    109 	let w = stype.fields[0];
    110 	assert(w.offs == 0);
    111 	let x = stype.fields[1];
    112 	assert(x.offs == 4);
    113 	let y = stype.fields[2];
    114 	assert(y.offs == 8);
    115 	let z = stype.fields[3];
    116 	assert(z.offs == 16);
    117 
    118 	let atype = parse_type("struct { x: u8, y: size, z: u8 }");
    119 	defer ast::type_finish(atype);
    120 	let htype = lookup(st, &atype)!;
    121 	assert(htype.sz == 24);
    122 
    123 	// Sort order
    124 	let atype = parse_type("struct { z: u8, y: u8, x: u8, q: u8 }");
    125 	defer ast::type_finish(atype);
    126 	let htype = lookup(st, &atype)!;
    127 	let stype = htype.repr as _struct;
    128 	assert(stype.fields[0].name == "q");
    129 	assert(stype.fields[1].name == "x");
    130 	assert(stype.fields[2].name == "y");
    131 	assert(stype.fields[3].name == "z");
    132 
    133 	// Embedded struct
    134 	let atype = parse_type("struct {
    135 		x: int,
    136 		y: int,
    137 		struct {
    138 			z: int,
    139 			q: int,
    140 		},
    141 		p: int,
    142 	}");
    143 	defer ast::type_finish(atype);
    144 	let htype = lookup(st, &atype)!;
    145 	assert(htype.sz == 20);
    146 	assert(htype._align == 4);
    147 	let stype = htype.repr as _struct;
    148 	assert(stype.fields[0].name == "p");
    149 	assert(stype.fields[0].offs == 16);
    150 	assert(stype.fields[1].name == "q");
    151 	assert(stype.fields[1].offs == 12);
    152 	assert(stype.fields[2].name == "x");
    153 	assert(stype.fields[2].offs == 0);
    154 	assert(stype.fields[3].name == "y");
    155 	assert(stype.fields[3].offs == 4);
    156 	assert(stype.fields[4].name == "z");
    157 	assert(stype.fields[4].offs == 8);
    158 
    159 	// Embedded union
    160 	let atype = parse_type("struct {
    161 		x: int,
    162 		y: int,
    163 		union {
    164 			z: int,
    165 			q: int,
    166 		},
    167 		p: int,
    168 	}");
    169 	defer ast::type_finish(atype);
    170 	let htype = lookup(st, &atype)!;
    171 	assert(htype.sz == 16);
    172 	assert(htype._align == 4);
    173 	let stype = htype.repr as _struct;
    174 	assert(stype.fields[0].name == "p");
    175 	assert(stype.fields[0].offs == 12);
    176 	assert(stype.fields[1].name == "q");
    177 	assert(stype.fields[1].offs == 8);
    178 	assert(stype.fields[2].name == "x");
    179 	assert(stype.fields[2].offs == 0);
    180 	assert(stype.fields[3].name == "y");
    181 	assert(stype.fields[3].offs == 4);
    182 	assert(stype.fields[4].name == "z");
    183 	assert(stype.fields[4].offs == 8);
    184 
    185 	// Embedded (struct) alias
    186 	// TODO
    187 
    188 	// Embedded (union) alias
    189 	// TODO
    190 
    191 	// Explicit offsets
    192 	let atype = parse_type("struct {
    193 		@offset(8)  x: int,
    194 		@offset(16) y: int,
    195 		@offset(32) z: int,
    196 	}");
    197 	defer ast::type_finish(atype);
    198 	let htype = lookup(st, &atype)!;
    199 	assert(htype.sz == 36);
    200 	assert(htype._align == 4);
    201 	let stype = htype.repr as _struct;
    202 	assert(stype.fields[0].name == "x");
    203 	assert(stype.fields[0].offs == 8);
    204 	assert(stype.fields[1].name == "y");
    205 	assert(stype.fields[1].offs == 16);
    206 	assert(stype.fields[2].name == "z");
    207 	assert(stype.fields[2].offs == 32);
    208 };
    209 
    210 @test fn tuples() void = {
    211 	let st = store(x86_64, &resolve, null);
    212 	defer store_free(st);
    213 
    214 	// Basic case
    215 	let atype = parse_type("(int, int)");
    216 	defer ast::type_finish(atype);
    217 	let htype = lookup(st, &atype)!;
    218 	assert(htype.sz == 8);
    219 	assert(htype._align == 4);
    220 	let tup = htype.repr as tuple;
    221 	assert(len(tup) == 2);
    222 
    223 	assert(tup[0].offs == 0);
    224 	assert(tup[0]._type.repr as builtin == builtin::INT);
    225 	assert(tup[1].offs == 4);
    226 	assert(tup[1]._type.repr as builtin == builtin::INT);
    227 
    228 	// Padding
    229 	let atype = parse_type("(i8, i32, i8, i64)");
    230 	defer ast::type_finish(atype);
    231 	let htype = lookup(st, &atype)!;
    232 	assert(htype.sz == 24);
    233 	assert(htype._align == 8);
    234 
    235 	let tup = htype.repr as tuple;
    236 	assert(tup[0].offs == 0);
    237 	assert(tup[1].offs == 4);
    238 	assert(tup[2].offs == 8);
    239 	assert(tup[3].offs == 16);
    240 };
    241 
    242 @test fn lists() void = {
    243 	let st = store(x86_64, &resolve, null);
    244 	defer store_free(st);
    245 
    246 	// Slice
    247 	let atype = parse_type("[]int");
    248 	defer ast::type_finish(atype);
    249 	let htype = lookup(st, &atype)!;
    250 	assert(htype.sz == 24);
    251 	assert(htype._align == 8);
    252 	let slice = htype.repr as slice;
    253 	assert(slice.repr as builtin == builtin::INT);
    254 
    255 	// Normal array
    256 	let atype = parse_type("[5]i32");
    257 	defer ast::type_finish(atype);
    258 	let htype = lookup(st, &atype)!;
    259 	assert(htype.sz == 4 * 5);
    260 	assert(htype._align == 4);
    261 	let arr = htype.repr as array;
    262 	assert(arr.member.repr as builtin == builtin::I32);
    263 	assert(arr.length == 5);
    264 
    265 	// Unbounded array
    266 	let atype = parse_type("[*]i32");
    267 	defer ast::type_finish(atype);
    268 	let htype = lookup(st, &atype)!;
    269 	assert(htype.sz == SIZE_UNDEFINED);
    270 	assert(htype._align == 4);
    271 	let arr = htype.repr as array;
    272 	assert(arr.member.repr as builtin == builtin::I32);
    273 	assert(arr.length == SIZE_UNDEFINED);
    274 
    275 	// Contextual array (equivalent to unbounded at this compilation stage)
    276 	let atype = parse_type("[_]i32");
    277 	defer ast::type_finish(atype);
    278 	let htype = lookup(st, &atype)!;
    279 	assert(htype.sz == SIZE_UNDEFINED);
    280 	assert(htype._align == 4);
    281 	let arr = htype.repr as array;
    282 	assert(arr.member.repr as builtin == builtin::I32);
    283 	assert(arr.length == SIZE_UNDEFINED);
    284 };
    285 
    286 @test fn funcs() void = {
    287 	let st = store(x86_64, &resolve, null);
    288 	defer store_free(st);
    289 
    290 	let atype = parse_type("@noreturn fn() void");
    291 	defer ast::type_finish(atype);
    292 	let htype = lookup(st, &atype)!;
    293 	assert(htype.sz == SIZE_UNDEFINED);
    294 	assert(htype._align == SIZE_UNDEFINED);
    295 	let f = htype.repr as func;
    296 	assert(f.result.repr as builtin == builtin::VOID);
    297 	assert(f.variadism  == variadism::NONE);
    298 	assert(f.flags == func_flag::NORETURN);
    299 	assert(len(f.params) == 0);
    300 
    301 	let atype = parse_type("fn(foo: int, bar: str...) int");
    302 	defer ast::type_finish(atype);
    303 	let htype = lookup(st, &atype)!;
    304 	assert(htype.sz == SIZE_UNDEFINED);
    305 	assert(htype._align == SIZE_UNDEFINED);
    306 	let f = htype.repr as func;
    307 	assert(f.result.repr as builtin == builtin::INT);
    308 	assert(f.variadism  == variadism::HARE);
    309 	assert(f.flags == 0);
    310 	assert(len(f.params) == 2);
    311 	assert(f.params[0].repr as builtin == builtin::INT);
    312 	assert(f.params[1].repr as builtin == builtin::STR);
    313 };
    314 
    315 @test fn tagged() void = {
    316 	let st = store(x86_64, &resolve, null);
    317 	defer store_free(st);
    318 
    319 	let atype = parse_type("(int | int | void)");
    320 	defer ast::type_finish(atype);
    321 	let htype = lookup(st, &atype)!;
    322 	assert(htype.sz == st.arch._int * 2);
    323 	assert(htype._align == st.arch._int);
    324 	let t = htype.repr as tagged;
    325 	assert(len(t) == 2);
    326 	assert(t[0].repr as builtin == builtin::INT);
    327 	assert(t[1].repr as builtin == builtin::VOID);
    328 
    329 	let atype = parse_type("(int | (int | str | void))");
    330 	defer ast::type_finish(atype);
    331 	let htype = lookup(st, &atype)!;
    332 	assert(htype.sz == 32);
    333 	assert(htype._align == 8);
    334 	let t = htype.repr as tagged;
    335 	assert(len(t) == 3);
    336 	assert(t[0].repr as builtin == builtin::STR);
    337 	assert(t[1].repr as builtin == builtin::INT);
    338 	assert(t[2].repr as builtin == builtin::VOID);
    339 };
    340 
    341 @test fn alias() void = {
    342 	let st = store(x86_64, &resolve, null);
    343 	defer store_free(st);
    344 
    345 	const of = lookup_builtin(st, ast::builtin_type::U64);
    346 	const al = newalias(st, ["myalias"], of);
    347 	assert(al.sz == 8);
    348 	assert(al._align == 8);
    349 	assert(al.flags == 0);
    350 	assert((al.repr as alias).secondary == of);
    351 
    352 	const atype = parse_type("myalias");
    353 	defer ast::type_finish(atype);
    354 	const htype = lookup(st, &atype)!;
    355 	assert(htype == al);
    356 };
    357 
    358 @test fn forwardref() void = {
    359 	let st = store(x86_64, &resolve, null);
    360 	defer store_free(st);
    361 
    362 	const atype = parse_type("myalias");
    363 	defer ast::type_finish(atype);
    364 	const htype = lookup(st, &atype)!;
    365 	assert((htype.repr as alias).secondary == null);
    366 
    367 	const of = lookup_builtin(st, ast::builtin_type::U64);
    368 	const al = newalias(st, ["myalias"], of);
    369 	assert(htype.sz == 8);
    370 	assert(htype._align == 8);
    371 	assert(htype.flags == 0);
    372 	assert((htype.repr as alias).secondary == of);
    373 };