hare

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

unit.ha (4476B)


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