hare

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

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:
Dhare/parse/+test.ha | 236-------------------------------------------------------------------------------
Ahare/parse/+test/expr.ha | 20++++++++++++++++++++
Ahare/parse/+test/ident.ha | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ahare/parse/+test/roundtrip.ha | 31+++++++++++++++++++++++++++++++
Ahare/parse/+test/unit.ha | 135+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mscripts/gen-stdlib | 5++++-
Mstdlib.mk | 9++++++---
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'