hare

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

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