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