hare

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

+test.ha (10283B)


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