commit ac9c010cb1c8e009c1a486ed1b2c829bf2a4aa9d
parent 8bed880214d8cd8e019c2cacd047e04c141393ec
Author: Drew DeVault <sir@cmpwn.com>
Date: Wed, 14 Apr 2021 14:11:23 -0400
hare::parse: move tests into subdir
Diffstat:
7 files changed, 257 insertions(+), 240 deletions(-)
diff --git a/hare/parse/+test.ha b/hare/parse/+test.ha
@@ -1,236 +0,0 @@
-use bufio;
-use fmt;
-use hare::ast;
-use hare::lex;
-use hare::unparse;
-use io;
-use io::{mode};
-use strings;
-use strio;
-
-@test fn ident() void = {
- {
- const in = "foo";
- let buf = bufio::fixed(strings::toutf8(in), mode::READ);
- defer io::close(buf);
- let lexer = lex::init(buf, "<test>");
- let ident = ident(&lexer) as ast::ident;
- defer ast::ident_free(ident);
- assert(len(ident) == 1);
- assert(ident[0] == "foo");
- let tok = lex::lex(&lexer) as lex::token;
- assert(tok.0 == lex::ltok::EOF);
- };
-
- {
- const in = "foo::bar";
- let buf = bufio::fixed(strings::toutf8(in), mode::READ);
- defer io::close(buf);
- let lexer = lex::init(buf, "<test>");
- let ident = ident(&lexer) as ast::ident;
- defer ast::ident_free(ident);
- assert(len(ident) == 2);
- assert(ident[0] == "foo" && ident[1] == "bar");
- let tok = lex::lex(&lexer) as lex::token;
- assert(tok.0 == lex::ltok::EOF);
- };
-
- {
- const in = "foo::bar::baz";
- let buf = bufio::fixed(strings::toutf8(in), mode::READ);
- defer io::close(buf);
- let lexer = lex::init(buf, "<test>");
- let ident = ident(&lexer) as ast::ident;
- defer ast::ident_free(ident);
- assert(len(ident) == 3);
- assert(ident[0] == "foo" && ident[1] == "bar"
- && ident[2] == "baz");
- let tok = lex::lex(&lexer) as lex::token;
- assert(tok.0 == lex::ltok::EOF);
- };
-
- {
- const in = "foo::bar;";
- let buf = bufio::fixed(strings::toutf8(in), mode::READ);
- defer io::close(buf);
- let lexer = lex::init(buf, "<test>");
- let ident = ident(&lexer) as ast::ident;
- defer ast::ident_free(ident);
- assert(len(ident) == 2);
- assert(ident[0] == "foo" && ident[1] == "bar");
- let tok = lex::lex(&lexer) as lex::token;
- assert(tok.0 == lex::ltok::SEMICOLON);
- };
-};
-
-@test fn imports() void = {
- {
- const in = "use foo;";
- let buf = bufio::fixed(strings::toutf8(in), mode::READ);
- defer io::close(buf);
- let lexer = lex::init(buf, "<test>");
- let mods = imports(&lexer) as []ast::import;
- defer for (let i = 0z; i < len(mods); i += 1) {
- ast::import_free(mods[i]);
- };
-
- assert(len(mods) == 1);
- assert(mods[0] is ast::import_module);
-
- let mod = mods[0] as ast::import_module;
- assert(len(mod) == 1 && mod[0] == "foo");
- let tok = lex::lex(&lexer) as lex::token;
- assert(tok.0 == lex::ltok::EOF);
- };
-
- {
- const in =
- "use foo;\n"
- "use bar;\n"
- "use baz::bat;\n\n"
- "export fn main() void = void;";
- let buf = bufio::fixed(strings::toutf8(in), mode::READ);
- defer io::close(buf);
- let lexer = lex::init(buf, "<test>");
- let mods = imports(&lexer) as []ast::import;
- defer for (let i = 0z; i < len(mods); i += 1) {
- ast::import_free(mods[i]);
- };
-
- assert(len(mods) == 3);
- let expected: [_][]str = [["foo"], ["bar"], ["baz", "bat"]];
-
- for (let i = 0z; i < len(mods); i += 1) {
- assert(mods[i] is ast::import_module);
- let mod = mods[i] as ast::import_module;
- assert(len(mod) == len(expected[i]));
- for (let j = 0z; j < len(expected[i]); j += 1z) {
- assert(mod[j] == expected[i][j]);
- };
- };
-
- let tok = lex::lex(&lexer) as lex::token;
- assert(tok.0 == lex::ltok::EXPORT);
- };
-
- {
- const in =
- "use foo = bar;\n"
- "use baz = bat;\n"
- "use qux = quux::corge;\n"
- "export fn main() void = void;";
- let buf = bufio::fixed(strings::toutf8(in), mode::READ);
- defer io::close(buf);
- let lexer = lex::init(buf, "<test>");
- let mods = imports(&lexer) as []ast::import;
- defer for (let i = 0z; i < len(mods); i += 1) {
- ast::import_free(mods[i]);
- };
-
- assert(len(mods) == 3);
- let expected: [_](str, []str) = [
- ("foo", ["bar"]),
- ("baz", ["bat"]),
- ("qux", ["quux", "corge"])
- ];
-
- for (let i = 0z; i < len(mods); i += 1) {
- assert(mods[i] is ast::import_alias);
- let mod = mods[i] as ast::import_alias;
- assert(mod.alias == expected[i].0);
- assert(len(mod.ident) == len(expected[i].1));
- for (let j = 0z; j < len(expected[i].1); j += 1z) {
- assert(mod.ident[j] == expected[i].1[j]);
- };
- };
- };
-
- {
- const in =
- "use foo::{bar};\n"
- "use baz::{bat, qux};\n"
- "use quux::corge::{grault, garply,};\n"
- "export fn main() void = void;";
- let buf = bufio::fixed(strings::toutf8(in), mode::READ);
- defer io::close(buf);
- let lexer = lex::init(buf, "<test>");
- let mods = imports(&lexer) as []ast::import;
- defer for (let i = 0z; i < len(mods); i += 1) {
- ast::import_free(mods[i]);
- };
-
- assert(len(mods) == 3);
- let expected: [_]([]str, []str) = [
- (["foo"], ["bar"]),
- (["baz"], ["bat", "qux"]),
- (["quux", "corge"], ["grault", "garply"])
- ];
-
- for (let i = 0z; i < len(mods); i += 1) {
- assert(mods[i] is ast::import_objects);
- let mod = mods[i] as ast::import_objects;
- assert(len(mod.objects) == len(expected[i].1));
- for (let j = 0z; j < len(expected[i].0); j += 1z) {
- assert(mod.objects[j] == expected[i].1[j]);
- };
- assert(len(mod.ident) == len(expected[i].0));
- for (let j = 0z; j < len(expected[i].0); j += 1z) {
- assert(mod.ident[j] == expected[i].0[j]);
- };
- };
- };
-};
-
-fn roundtrip(src: str) void = {
- let buf = bufio::fixed(strings::toutf8(src), mode::READ);
- defer io::close(buf);
- let lexer = lex::init(buf, "<test>");
- let u = ast::subunit {
- imports = [],
- decls: []ast::decl = match (decls(&lexer)) {
- decls: []ast::decl => decls,
- err: error => {
- fmt::errorln(strerror(err));
- abort();
- },
- },
- };
- defer ast::subunit_free(u);
- let out = strio::dynamic();
- unparse::subunit(out, u) as size;
- let unsrc = strio::finish(out);
- defer free(unsrc);
- assert(unsrc == src);
-};
-
-@test fn decls() void = {
- roundtrip("export type foo::bar = *int, baz = const void;\n"
- "type foo = ...bar;\n"
- "type foo = nullable *fn(x: rune, _: int) void;\n"
- "export let @symbol(\"_\") foo::bar: int = void, baz: int = void;\n"
- "def foo::bar: int = void;\n"
- "@symbol(\".f9$oo\") fn foo(bar: int, baz: int...) void;\n"
- "@test fn foo(_: int, ...) void;\n"
- "export fn main() void = void;\n");
-};
-
-@test fn binarithm() void = {
- roundtrip("export fn main() void = void + void * void / void;\n");
-};
-
-@test fn cast() void = {
- roundtrip("export fn main() void = void: int;\n"
- "export fn main() void = void as int;\n"
- "export fn main() void = void is int;\n"
- "export fn main() void = void: int: uint: u16: u8;\n"
- "export fn main() void = void: int as uint: u16 is u8;\n");
-};
-
-@test fn unarithm() void = {
- // TODO: object selectors/addr operator
- roundtrip("export fn main() void = +void;\n"
- "export fn main() void = -void;\n"
- "export fn main() void = *void;\n"
- "export fn main() void = ~void;\n"
- "export fn main() void = !void;\n");
-};
diff --git a/hare/parse/+test/expr.ha b/hare/parse/+test/expr.ha
@@ -0,0 +1,20 @@
+@test fn binarithm() void = {
+ roundtrip("export fn main() void = void + void * void / void;\n");
+};
+
+@test fn cast() void = {
+ roundtrip("export fn main() void = void: int;\n"
+ "export fn main() void = void as int;\n"
+ "export fn main() void = void is int;\n"
+ "export fn main() void = void: int: uint: u16: u8;\n"
+ "export fn main() void = void: int as uint: u16 is u8;\n");
+};
+
+@test fn unarithm() void = {
+ // TODO: object selectors/addr operator
+ roundtrip("export fn main() void = +void;\n"
+ "export fn main() void = -void;\n"
+ "export fn main() void = *void;\n"
+ "export fn main() void = ~void;\n"
+ "export fn main() void = !void;\n");
+};
diff --git a/hare/parse/+test/ident.ha b/hare/parse/+test/ident.ha
@@ -0,0 +1,61 @@
+use bufio;
+use hare::ast;
+use hare::lex;
+use io;
+use io::{mode};
+use strings;
+
+@test fn ident() void = {
+ {
+ const in = "foo";
+ let buf = bufio::fixed(strings::toutf8(in), mode::READ);
+ defer io::close(buf);
+ let lexer = lex::init(buf, "<test>");
+ let ident = ident(&lexer) as ast::ident;
+ defer ast::ident_free(ident);
+ assert(len(ident) == 1);
+ assert(ident[0] == "foo");
+ let tok = lex::lex(&lexer) as lex::token;
+ assert(tok.0 == lex::ltok::EOF);
+ };
+
+ {
+ const in = "foo::bar";
+ let buf = bufio::fixed(strings::toutf8(in), mode::READ);
+ defer io::close(buf);
+ let lexer = lex::init(buf, "<test>");
+ let ident = ident(&lexer) as ast::ident;
+ defer ast::ident_free(ident);
+ assert(len(ident) == 2);
+ assert(ident[0] == "foo" && ident[1] == "bar");
+ let tok = lex::lex(&lexer) as lex::token;
+ assert(tok.0 == lex::ltok::EOF);
+ };
+
+ {
+ const in = "foo::bar::baz";
+ let buf = bufio::fixed(strings::toutf8(in), mode::READ);
+ defer io::close(buf);
+ let lexer = lex::init(buf, "<test>");
+ let ident = ident(&lexer) as ast::ident;
+ defer ast::ident_free(ident);
+ assert(len(ident) == 3);
+ assert(ident[0] == "foo" && ident[1] == "bar"
+ && ident[2] == "baz");
+ let tok = lex::lex(&lexer) as lex::token;
+ assert(tok.0 == lex::ltok::EOF);
+ };
+
+ {
+ const in = "foo::bar;";
+ let buf = bufio::fixed(strings::toutf8(in), mode::READ);
+ defer io::close(buf);
+ let lexer = lex::init(buf, "<test>");
+ let ident = ident(&lexer) as ast::ident;
+ defer ast::ident_free(ident);
+ assert(len(ident) == 2);
+ assert(ident[0] == "foo" && ident[1] == "bar");
+ let tok = lex::lex(&lexer) as lex::token;
+ assert(tok.0 == lex::ltok::SEMICOLON);
+ };
+};
diff --git a/hare/parse/+test/roundtrip.ha b/hare/parse/+test/roundtrip.ha
@@ -0,0 +1,31 @@
+use bufio;
+use fmt;
+use hare::ast;
+use hare::lex;
+use hare::unparse;
+use io::{mode};
+use io;
+use strings;
+use strio;
+
+fn roundtrip(src: str) void = {
+ let buf = bufio::fixed(strings::toutf8(src), mode::READ);
+ defer io::close(buf);
+ let lexer = lex::init(buf, "<test>");
+ let u = ast::subunit {
+ imports = [],
+ decls: []ast::decl = match (decls(&lexer)) {
+ decls: []ast::decl => decls,
+ err: error => {
+ fmt::errorln(strerror(err));
+ abort();
+ },
+ },
+ };
+ defer ast::subunit_free(u);
+ let out = strio::dynamic();
+ unparse::subunit(out, u) as size;
+ let unsrc = strio::finish(out);
+ defer free(unsrc);
+ assert(unsrc == src);
+};
diff --git a/hare/parse/+test/unit.ha b/hare/parse/+test/unit.ha
@@ -0,0 +1,135 @@
+use bufio;
+use hare::ast;
+use hare::lex;
+use io::{mode};
+use io;
+use strings;
+
+@test fn imports() void = {
+ {
+ const in = "use foo;";
+ let buf = bufio::fixed(strings::toutf8(in), mode::READ);
+ defer io::close(buf);
+ let lexer = lex::init(buf, "<test>");
+ let mods = imports(&lexer) as []ast::import;
+ defer for (let i = 0z; i < len(mods); i += 1) {
+ ast::import_free(mods[i]);
+ };
+
+ assert(len(mods) == 1);
+ assert(mods[0] is ast::import_module);
+
+ let mod = mods[0] as ast::import_module;
+ assert(len(mod) == 1 && mod[0] == "foo");
+ let tok = lex::lex(&lexer) as lex::token;
+ assert(tok.0 == lex::ltok::EOF);
+ };
+
+ {
+ const in =
+ "use foo;\n"
+ "use bar;\n"
+ "use baz::bat;\n\n"
+ "export fn main() void = void;";
+ let buf = bufio::fixed(strings::toutf8(in), mode::READ);
+ defer io::close(buf);
+ let lexer = lex::init(buf, "<test>");
+ let mods = imports(&lexer) as []ast::import;
+ defer for (let i = 0z; i < len(mods); i += 1) {
+ ast::import_free(mods[i]);
+ };
+
+ assert(len(mods) == 3);
+ let expected: [_][]str = [["foo"], ["bar"], ["baz", "bat"]];
+
+ for (let i = 0z; i < len(mods); i += 1) {
+ assert(mods[i] is ast::import_module);
+ let mod = mods[i] as ast::import_module;
+ assert(len(mod) == len(expected[i]));
+ for (let j = 0z; j < len(expected[i]); j += 1z) {
+ assert(mod[j] == expected[i][j]);
+ };
+ };
+
+ let tok = lex::lex(&lexer) as lex::token;
+ assert(tok.0 == lex::ltok::EXPORT);
+ };
+
+ {
+ const in =
+ "use foo = bar;\n"
+ "use baz = bat;\n"
+ "use qux = quux::corge;\n"
+ "export fn main() void = void;";
+ let buf = bufio::fixed(strings::toutf8(in), mode::READ);
+ defer io::close(buf);
+ let lexer = lex::init(buf, "<test>");
+ let mods = imports(&lexer) as []ast::import;
+ defer for (let i = 0z; i < len(mods); i += 1) {
+ ast::import_free(mods[i]);
+ };
+
+ assert(len(mods) == 3);
+ let expected: [_](str, []str) = [
+ ("foo", ["bar"]),
+ ("baz", ["bat"]),
+ ("qux", ["quux", "corge"])
+ ];
+
+ for (let i = 0z; i < len(mods); i += 1) {
+ assert(mods[i] is ast::import_alias);
+ let mod = mods[i] as ast::import_alias;
+ assert(mod.alias == expected[i].0);
+ assert(len(mod.ident) == len(expected[i].1));
+ for (let j = 0z; j < len(expected[i].1); j += 1z) {
+ assert(mod.ident[j] == expected[i].1[j]);
+ };
+ };
+ };
+
+ {
+ const in =
+ "use foo::{bar};\n"
+ "use baz::{bat, qux};\n"
+ "use quux::corge::{grault, garply,};\n"
+ "export fn main() void = void;";
+ let buf = bufio::fixed(strings::toutf8(in), mode::READ);
+ defer io::close(buf);
+ let lexer = lex::init(buf, "<test>");
+ let mods = imports(&lexer) as []ast::import;
+ defer for (let i = 0z; i < len(mods); i += 1) {
+ ast::import_free(mods[i]);
+ };
+
+ assert(len(mods) == 3);
+ let expected: [_]([]str, []str) = [
+ (["foo"], ["bar"]),
+ (["baz"], ["bat", "qux"]),
+ (["quux", "corge"], ["grault", "garply"])
+ ];
+
+ for (let i = 0z; i < len(mods); i += 1) {
+ assert(mods[i] is ast::import_objects);
+ let mod = mods[i] as ast::import_objects;
+ assert(len(mod.objects) == len(expected[i].1));
+ for (let j = 0z; j < len(expected[i].0); j += 1z) {
+ assert(mod.objects[j] == expected[i].1[j]);
+ };
+ assert(len(mod.ident) == len(expected[i].0));
+ for (let j = 0z; j < len(expected[i].0); j += 1z) {
+ assert(mod.ident[j] == expected[i].0[j]);
+ };
+ };
+ };
+};
+
+@test fn decls() void = {
+ roundtrip("export type foo::bar = *int, baz = const void;\n"
+ "type foo = ...bar;\n"
+ "type foo = nullable *fn(x: rune, _: int) void;\n"
+ "export let @symbol(\"_\") foo::bar: int = void, baz: int = void;\n"
+ "def foo::bar: int = void;\n"
+ "@symbol(\".f9$oo\") fn foo(bar: int, baz: int...) void;\n"
+ "@test fn foo(_: int, ...) void;\n"
+ "export fn main() void = void;\n");
+};
diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib
@@ -372,7 +372,10 @@ hare_parse() {
gen_ssa hare::parse hare::ast hare::lex hare::unparse fmt
else
gensrcs_hare_parse \
- +test.ha
+ +test/expr.ha \
+ +test/ident.ha \
+ +test/roundtrip.ha \
+ +test/unit.ha
gen_ssa hare::parse bufio fmt hare::ast hare::lex hare::unparse io \
strings strio fmt
fi
diff --git a/stdlib.mk b/stdlib.mk
@@ -477,7 +477,7 @@ stdlib_hare_lex_srcs= \
$(STDLIB)/hare/lex/token.ha \
$(STDLIB)/hare/lex/lex.ha
-$(HARECACHE)/hare/lex/hare_lex.ssa: $(stdlib_hare_lex_srcs) $(stdlib_rt) $(stdlib_io) $(stdlib_bufio) $(stdlib_strings) $(stdlib_types) $(stdlib_fmt) $(stdlib_sort)
+$(HARECACHE)/hare/lex/hare_lex.ssa: $(stdlib_hare_lex_srcs) $(stdlib_rt) $(stdlib_io) $(stdlib_bufio) $(stdlib_strings) $(stdlib_types) $(stdlib_fmt) $(stdlib_sort) $(stdlib_strio)
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/hare/lex
@HARECACHE=$(HARECACHE) $(HAREC) $(HAREFLAGS) -o $@ -Nhare::lex \
@@ -1324,7 +1324,7 @@ testlib_hare_lex_srcs= \
$(STDLIB)/hare/lex/lex.ha \
$(STDLIB)/hare/lex/+test.ha
-$(TESTCACHE)/hare/lex/hare_lex.ssa: $(testlib_hare_lex_srcs) $(testlib_rt) $(testlib_io) $(testlib_bufio) $(testlib_strings) $(testlib_types) $(testlib_fmt) $(testlib_sort)
+$(TESTCACHE)/hare/lex/hare_lex.ssa: $(testlib_hare_lex_srcs) $(testlib_rt) $(testlib_io) $(testlib_bufio) $(testlib_strings) $(testlib_types) $(testlib_fmt) $(testlib_sort) $(testlib_strio)
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/hare/lex
@HARECACHE=$(TESTCACHE) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nhare::lex \
@@ -1354,7 +1354,10 @@ testlib_hare_parse_srcs= \
$(STDLIB)/hare/parse/types.ha \
$(STDLIB)/hare/parse/unit.ha \
$(STDLIB)/hare/parse/util.ha \
- $(STDLIB)/hare/parse/+test.ha
+ $(STDLIB)/hare/parse/+test/expr.ha \
+ $(STDLIB)/hare/parse/+test/ident.ha \
+ $(STDLIB)/hare/parse/+test/roundtrip.ha \
+ $(STDLIB)/hare/parse/+test/unit.ha
$(TESTCACHE)/hare/parse/hare_parse.ssa: $(testlib_hare_parse_srcs) $(testlib_rt) $(testlib_bufio) $(testlib_fmt) $(testlib_hare_ast) $(testlib_hare_lex) $(testlib_hare_unparse) $(testlib_io) $(testlib_strings) $(testlib_strio) $(testlib_fmt)
@printf 'HAREC \t$@\n'