unit_test.ha (3421B)
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 io::{mode}; 8 use memio; 9 use strings; 10 use types; 11 12 fn import_eq(i1: ast::import, i2: ast::import) bool = { 13 if (!ast::ident_eq(i1.ident, i2.ident)) { 14 return false; 15 }; 16 17 let (o1, o2) = match (i1.bindings) { 18 case void => 19 return i2.bindings is void; 20 case let s1: ast::import_alias => 21 match (i2.bindings) { 22 case let s2: ast::import_alias => 23 return s1 == s2; 24 case => 25 return false; 26 }; 27 case let o1: ast::import_members => 28 yield match (i2.bindings) { 29 case let o2: ast::import_members => 30 if (len(o1) != len(o2)) { 31 return false; 32 }; 33 yield (o1, o2); 34 case => 35 return false; 36 }; 37 case ast::import_wildcard => 38 return i2.bindings is ast::import_wildcard; 39 }; 40 for (let i = 0z; i < len(o1); i += 1) { 41 if (o1[i] != o2[i]) { 42 return false; 43 }; 44 }; 45 return true; 46 }; 47 48 type import_tuple = (ast::ident, (void | ast::import_alias | 49 ast::import_members | ast::import_wildcard)); 50 51 fn tup_to_import(tup: import_tuple) ast::import = ast::import { 52 ident = tup.0, 53 bindings = tup.1, 54 ... 55 }; 56 57 @test fn imports() void = { 58 const in = 59 "use foo;\n" 60 "use bar;\n" 61 "use baz::bat;\n\n" 62 63 "use foo = bar;\n" 64 "use baz = bat;\n" 65 "use qux = quux::corge;\n" 66 67 "use foo::*;" 68 "use foo::bar::quux::*;" 69 70 "use foo::{bar};\n" 71 "use foo::{bar,};\n" 72 "use baz::{bat, qux};\n" 73 "use quux::corge::{grault, garply,};\n" 74 75 "export fn main() void = void;"; 76 let buf = memio::fixed(strings::toutf8(in)); 77 let sc = bufio::newscanner(&buf); 78 defer bufio::finish(&sc); 79 let lexer = lex::init(&sc, "<test>"); 80 let mods = imports(&lexer)!; 81 defer ast::imports_finish(mods); 82 83 let expected: [_]import_tuple = [ 84 (["foo"], void), 85 (["bar"], void), 86 (["baz", "bat"], void), 87 (["bar"], "foo"), 88 (["bat"], "baz"), 89 (["quux", "corge"], "qux"), 90 (["foo"], ast::import_wildcard), 91 (["foo", "bar", "quux"], ast::import_wildcard), 92 (["foo"], ["bar"]), 93 (["foo"], ["bar"]), 94 (["baz"], ["bat", "qux"]), 95 (["quux", "corge"], ["grault", "garply"]), 96 ]; 97 98 assert(len(mods) == len(expected)); 99 for (let i = 0z; i < len(mods); i += 1) { 100 assert(import_eq(mods[i], tup_to_import(expected[i]))); 101 }; 102 103 let tok = lex::lex(&lexer) as lex::token; 104 assert(tok.0 == lex::ltok::EXPORT); 105 }; 106 107 @test fn decls() void = { 108 roundtrip("export type foo::bar = *int, baz = const void;\n\n" 109 "type foo = ...bar;\n\n" 110 "type foo = nullable *fn(x: rune, int) void;\n\n" 111 "export let @symbol(\"_\") foo::bar: int = void, baz: int = void, bat = void;\n\n" 112 "def foo::bar: int = void;\n\n" 113 "def foo::bar = void;\n\n" 114 "@symbol(\".f9$oo\") fn foo(bar: int, baz: int...) void;\n\n" 115 "@test fn foo(int, ...) void;\n\n" 116 "@test fn foo(...) void;\n\n" 117 "fn foo(bar) void;\n\n" 118 "fn foo(bar::baz) void;\n\n" 119 "export fn main() void = void;\n\n" 120 "fn long(\n" 121 "\tfirst: *const void,\n" 122 "\tsecond: (void | rune | str),\n" 123 "\tthird: size...\n" 124 ") nullable *const void;\n\n" 125 "static abort();\n\n" 126 "static assert(true);\n"); 127 }; 128 129 @test fn docs() void = { 130 roundtrip("// According to all known laws of aviation, there is no\n" 131 "// way that a bee should be able to fly. Its wings are too\n" 132 "// small to get its fat little body off the ground. The bee,\n" 133 "// of course, flies anyway, because bees don't care what\n" 134 "// humans think is impossible.\n" 135 "export fn main() void = void;\n"); 136 };