hare

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

+test.ha (4376B)


      1 // SPDX-License-Identifier: MPL-2.0
      2 // (c) Hare authors <https://harelang.org>
      3 
      4 use bufio;
      5 use hare::ast;
      6 use hare::lex;
      7 use hare::parse;
      8 use hare::types;
      9 use io;
     10 use memio;
     11 use strings;
     12 
     13 fn parse_expr(src: str) *ast::expr = {
     14 	let stream = memio::fixed(strings::toutf8(src));
     15 	let sc = bufio::newscanner(&stream);
     16 	defer bufio::finish(&sc);
     17 	let lexer = lex::init(&sc, "<test>");
     18 	return alloc(parse::expr(&lexer)!);
     19 };
     20 
     21 fn mktestctx() context = context {
     22 	store = types::store(types::x86_64, null, null),
     23 	scope = alloc(scope { ... }),
     24 	...
     25 };
     26 
     27 fn freetestctx(ctx: *context) void = {
     28 	// TODO: Some of this should be in -test
     29 	types::store_free(ctx.store);
     30 };
     31 
     32 @test fn access() void = {
     33 	// TODO: Test error cases, more access types
     34 	const ctx = mktestctx();
     35 	defer freetestctx(&ctx);
     36 	const object = scope_insert(&ctx, object {
     37 		kind = object_kind::BIND,
     38 		ident = ["hello"],
     39 		name = ["hello"],
     40 		_type = &types::builtin_u32,
     41 		...
     42 	});
     43 	const aexpr = parse_expr("hello");
     44 	defer ast::expr_finish(aexpr);
     45 	const expr = process_access(&ctx, aexpr)!;
     46 	const access = expr.expr as access;
     47 	const ao = access as access_object;
     48 	assert(ao == object);
     49 	assert(expr.result == &types::builtin_u32);
     50 };
     51 
     52 @test fn compound() void = {
     53 	const ctx = mktestctx();
     54 	defer freetestctx(&ctx);
     55 	const aexpr = parse_expr("{ void; void; void; }");
     56 	defer ast::expr_finish(aexpr);
     57 	const expr = process_compound(&ctx, aexpr)!;
     58 	assert(expr.result.repr as types::builtin == types::builtin::VOID);
     59 	const compound = expr.expr as compound;
     60 	assert(len(compound) == 3);
     61 
     62 	const aexpr = parse_expr("{ return; }");
     63 	defer ast::expr_finish(aexpr);
     64 	const expr = process_compound(&ctx, aexpr)!;
     65 	assert(expr.terminates);
     66 
     67 	// TODO: test yields
     68 };
     69 
     70 @test fn constant() void = {
     71 	const ctx = mktestctx();
     72 	defer freetestctx(&ctx);
     73 	const aexpr = parse_expr("void");
     74 	defer ast::expr_finish(aexpr);
     75 	const expr = process_constant(&ctx, aexpr)!;
     76 	assert(expr.result.repr as types::builtin == types::builtin::VOID);
     77 	const constexpr = expr.expr as constant;
     78 	assert(constexpr is void);
     79 
     80 	const aexpr = parse_expr("true");
     81 	defer ast::expr_finish(aexpr);
     82 	const expr = process_constant(&ctx, aexpr)!;
     83 	assert(expr.result.repr as types::builtin == types::builtin::BOOL);
     84 	const constexpr = expr.expr as constant;
     85 	assert(constexpr as bool == true);
     86 
     87 	const aexpr = parse_expr("false");
     88 	defer ast::expr_finish(aexpr);
     89 	const expr = process_constant(&ctx, aexpr)!;
     90 	assert(expr.result.repr as types::builtin == types::builtin::BOOL);
     91 	const constexpr = expr.expr as constant;
     92 	assert(constexpr as bool == false);
     93 
     94 	const aexpr = parse_expr("null");
     95 	defer ast::expr_finish(aexpr);
     96 	const expr = process_constant(&ctx, aexpr)!;
     97 	assert(expr.result.repr as types::builtin == types::builtin::NULL);
     98 	assert(expr.expr is constant);
     99 
    100 	const cases: [_](str, types::builtin, constant) = [
    101 		("1234", types::builtin::INT, 1234),
    102 		("1234u", types::builtin::UINT, 1234u),
    103 		("\"hello world\"", types::builtin::STR, "hello world"),
    104 		("'!'", types::builtin::RUNE, '!'),
    105 		("13.37", types::builtin::F64, 13.37f64),
    106 	];
    107 	for (let i = 0z; i < len(cases); i += 1) {
    108 		const _case = cases[i];
    109 		const aexpr = parse_expr(_case.0);
    110 		defer ast::expr_finish(aexpr);
    111 		const expr = process_constant(&ctx, aexpr)!;
    112 		assert(expr.result.repr as types::builtin == _case.1);
    113 		const constexpr = expr.expr as constant;
    114 		match (_case.2) {
    115 		case let s: str =>
    116 			assert(constexpr as str == s);
    117 		case let r: rune =>
    118 			assert(constexpr as rune == r);
    119 		case let i: i64 =>
    120 			assert(constexpr as i64 == i);
    121 		case let u: u64 =>
    122 			assert(constexpr as u64 == u);
    123 		case let f: f64 =>
    124 			assert(constexpr as f64 == f);
    125 		case void =>
    126 			abort();
    127 		};
    128 	};
    129 };
    130 
    131 @test fn _return() void = {
    132 	const ctx = mktestctx();
    133 	defer freetestctx(&ctx);
    134 	const aexpr = parse_expr("return;");
    135 	defer ast::expr_finish(aexpr);
    136 	const ret_expr = process_return(&ctx, aexpr)!;
    137 	assert(ret_expr.terminates);
    138 	assert(ret_expr.result.repr as types::builtin == types::builtin::VOID);
    139 	const rval = ret_expr.expr as _return;
    140 	assert(rval == null);
    141 
    142 	const aexpr = parse_expr("return 10;");
    143 	defer ast::expr_finish(aexpr);
    144 	const ret_expr = process_return(&ctx, aexpr)!;
    145 	assert(ret_expr.terminates);
    146 	assert(ret_expr.result.repr as types::builtin == types::builtin::VOID);
    147 	const rval = ret_expr.expr as _return;
    148 	assert((rval as *expr).expr is constant);
    149 };