hare

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

commit b75132a5ba95f1206a4a9abae8a31ef31358ac4d
parent 10c5e27f2f64f11a50bf994a18428ea8f9ea88a2
Author: Eyal Sawady <ecs@d2evs.net>
Date:   Wed, 24 Mar 2021 01:30:02 -0400

hare::parse: implement decls parsing

Diffstat:
Mhare/parse/+test.ha | 25+++++++++++++++++++++++++
Ahare/parse/decl.ha | 191+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ahare/parse/expr.ha | 10++++++++++
Ahare/parse/ident.ha | 34++++++++++++++++++++++++++++++++++
Ahare/parse/import.ha | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dhare/parse/parse.ha | 96-------------------------------------------------------------------------------
Ahare/parse/type.ha | 256+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ahare/parse/unit.ha | 11+++++++++++
Mhare/parse/util.ha | 3+++
Mscripts/gen-stdlib | 13++++++++++---
Mstdlib.mk | 24+++++++++++++++++-------
11 files changed, 621 insertions(+), 106 deletions(-)

diff --git a/hare/parse/+test.ha b/hare/parse/+test.ha @@ -2,8 +2,10 @@ use bufio; use fmt; use hare::ast; use hare::lex; +use hare::unparse; use io::{mode}; use strings; +use strio; @test fn ident() void = { { @@ -165,3 +167,26 @@ use strings; }; }; }; + +@test fn decls() void = { + const in = "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"; + let buf = bufio::fixed(strings::to_utf8(in), mode::READ); + let lexer = lex::init(buf, "<test>"); + let u = ast::subunit { + imports = [], + decls = decls(&lexer) as []ast::decl, + }; + defer ast::subunit_free(u); + let out = strio::dynamic(); + unparse::subunit(out, u) as size; + let s = strio::finish(out); + defer free(s); + assert(s == in); +}; diff --git a/hare/parse/decl.ha b/hare/parse/decl.ha @@ -0,0 +1,191 @@ +use ascii; +use hare::lex; +use hare::lex::{btoken}; +use hare::ast; +use strings; + +fn attr_symbol(lexer: *lex::lexer) (str | error) = { + want_btoken(lexer, btoken::LPAREN)?; + let s: (str, lex::location) = match (lex::lex(lexer)?) { + io::EOF => return syntaxerr(mkloc(lexer), + "Expected string, got EOF"), + t: (lex::token, lex::location) => match (t.0) { + l: lex::literal => match (l) { + s: str => (s, t.1), + * => return syntaxerr(t.1, + "Expected string, got <something else>"), + }, + * => return syntaxerr(t.1, + "Expected string, got <something else>"), + }, + }; + let d = strings::iter(s.0); + match (strings::next(&d)) { + void => void, + r: rune => synassert(s.1, + ascii::isalpha(r) || r == '.' || r == '_', + "Invalid symbol")?, + }; + for (true) match (strings::next(&d)) { + void => break, + r: rune => synassert(s.1, + ascii::isalnum(r) || r == '$' || r == '.' || r == '_', + "Invalid symbol")?, + }; + want_btoken(lexer, btoken::RPAREN)?; + return s.0; +}; + +fn decl_global( + lexer: *lex::lexer, + tok: btoken +) ([]ast::decl_global | error) = { + let decl: []ast::decl_global = []; + for (true) { + let symbol = if (tok == btoken::CONST || tok == btoken::LET) { + match (try_btoken(lexer, btoken::ATTR_SYMBOL)?) { + void => "", + lex::btoken => attr_symbol(lexer)?, + }; + } else ""; + let ident = ident(lexer)?; + want_btoken(lexer, btoken::COLON)?; + let _type = _type(lexer)?; + if (tok == btoken::CONST) { + _type.flags |= ast::type_flags::CONST; + }; + want_btoken(lexer, btoken::EQUAL)?; + let init = expr(lexer)?; + let btok = try_btoken(lexer, btoken::COMMA)?; + append(decl, ast::decl_global { + is_const = tok == btoken::DEF, + symbol = symbol, + ident = ident, + _type = _type, + init = init, + }); + match (btok) { + void => break, + * => void, + }; + }; + return decl; +}; + +fn decl_type(lexer: *lex::lexer) ([]ast::decl_type | error) = { + let decl: []ast::decl_type = []; + for (true) { + let ident = ident(lexer)?; + want_btoken(lexer, btoken::EQUAL)?; + let _type = _type(lexer)?; + let btok = try_btoken(lexer, btoken::COMMA)?; + append(decl, ast::decl_type { + ident = ident, + _type = _type, + }); + match (btok) { + void => break, + * => void, + }; + }; + return decl; +}; + +fn decl_func(lexer: *lex::lexer) (ast::decl_func | error) = { + let attr = ast::fndecl_attrs::NONE, noreturn = false, sym = ""; + let attrs = [ + btoken::ATTR_FINI, btoken::ATTR_INIT, btoken::ATTR_TEST, + btoken::ATTR_NORETURN, btoken::ATTR_SYMBOL + ]; + for (true) match (try_btoken(lexer, attrs...)?) { + void => break, + b: lex::btoken => switch (b) { + btoken::ATTR_FINI => attr = ast::fndecl_attrs::FINI, + btoken::ATTR_INIT => attr = ast::fndecl_attrs::INIT, + btoken::ATTR_TEST => attr = ast::fndecl_attrs::TEST, + btoken::ATTR_NORETURN => noreturn = true, + btoken::ATTR_SYMBOL => sym = attr_symbol(lexer)?, + * => abort("unreachable"), + }, + }; + + want_btoken(lexer, btoken::FN)?; + let ident_loc = mkloc(lexer); + let ident = ident(lexer)?; + let proto_loc = mkloc(lexer); + let prototype = prototype(lexer)?; + if (noreturn) { + prototype.attrs |= ast::func_attrs::NORETURN; + }; + + let tok = want_btoken(lexer, btoken::EQUAL, btoken::SEMICOLON)?; + let body = switch (tok) { + btoken::EQUAL => { + synassert(ident_loc, len(ident) == 1, + "Expected name, found identifier")?; + const params = prototype.params; + for (let i = 0z; i < len(params); i += 1) { + synassert(params[i].loc, + len(params[i].name) > 0, + "Expected parameter name in function declaration")?; + }; + expr(lexer)?; + }, + // We don't care about the location + btoken::SEMICOLON => lex::unlex(lexer, (tok, proto_loc)), + }; + + return ast::decl_func { + symbol = sym, + ident = ident, + prototype = ast::_type { + loc = proto_loc, + flags = ast::type_flags::CONST, + _type = prototype, + }, + body = body, + attrs = attr, + }; +}; + +// Parses the declarations for a sub-unit +export fn decls(lexer: *lex::lexer) ([]ast::decl | error) = { + let decls: []ast::decl = []; + for (true) { + let exported = match (try_btoken(lexer, btoken::EXPORT)?) { + void => false, + lex::btoken => true, + }; + let tok = match(lex::lex(lexer)?) { + io::EOF => return syntaxerr(mkloc(lexer), + "Expected declaration, found EOF"), + t: (lex::token, lex::location) => t, + }; + let btok = match (tok.0) { + b: lex::btoken => b, + // TODO: Use fmt+lex::tokstr here: + * => return syntaxerr(mkloc(lexer), + "Expected declaration, found <something else>"), + }; + let decl = switch (btok) { + btoken::CONST, btoken::LET, btoken::DEF => + decl_global(lexer, btok)?, + btoken::TYPE => decl_type(lexer)?, + * => { + lex::unlex(lexer, tok); + decl_func(lexer)?; + }, + }; + append(decls, ast::decl { + exported = exported, + loc = mkloc(lexer), + decl = decl, + }); + want_btoken(lexer, btoken::SEMICOLON)?; + match (lex::lex(lexer)?) { + io::EOF => break, + t: (lex::token, lex::location) => lex::unlex(lexer, t), + }; + }; + return decls; +}; diff --git a/hare/parse/expr.ha b/hare/parse/expr.ha @@ -0,0 +1,10 @@ +use hare::ast; +use hare::lex; +use hare::lex::{btoken}; + +// Parses an expression +// TODO: Actually implement this +export fn expr(lexer: *lex::lexer) (ast::expr | error) = { + want_btoken(lexer, btoken::VOID)?; + return void; +}; diff --git a/hare/parse/ident.ha b/hare/parse/ident.ha @@ -0,0 +1,34 @@ +use hare::ast; +use hare::lex; +use hare::lex::{btoken}; + +fn ident_trailing(lexer: *lex::lexer) ((ast::ident, bool) | error) = { + let ident: []str = []; + let z = 0z; + for (true) { + let name = match (try_name(lexer)?) { + n: lex::name => n, + void => return (ident: ast::ident, true), + }; + append(ident, name: str); + z += len(name); + match (try_btoken(lexer, btoken::DOUBLE_COLON)?) { + void => break, + * => void, // Grab the next ident + }; + z += 1; + }; + if (z > ast::IDENT_MAX) { + ast::ident_free(ident: ast::ident); + return syntaxerr(mkloc(lexer), + "Identifier exceeds maximum length"); + }; + return (ident: ast::ident, false); +}; + +// Parses a single identifier, i.e. foo::bar::baz +export fn ident(lexer: *lex::lexer) (ast::ident | error) = { + let ident = ident_trailing(lexer)?; + synassert(mkloc(lexer), !ident.1, "Unexpected trailing :: in ident")?; + return ident.0; +}; diff --git a/hare/parse/import.ha b/hare/parse/import.ha @@ -0,0 +1,64 @@ +use hare::ast; +use hare::lex; +use hare::lex::{btoken}; + +fn name_list(lexer: *lex::lexer) ([]str | error) = { + let names: []str = []; + for (true) { + append(names, want_name(lexer)?: str); + switch (want_btoken(lexer, btoken::COMMA, btoken::RBRACE)?) { + btoken::COMMA => match (try_btoken(lexer, btoken::RBRACE)?) { + void => void, + * => return names, + }, + btoken::RBRACE => return names, + * => abort(), // Unreachable + }; + }; + abort(); +}; + +// Parses the import list for a sub-unit +export fn imports(lexer: *lex::lexer) ([]ast::import | error) = { + let imports: []ast::import = []; + for (true) { + match (try_btoken(lexer, btoken::USE)?) { + void => break, + * => void, + }; + + let name = ident_trailing(lexer)?; + + switch (want_btoken(lexer, btoken::SEMICOLON, btoken::LBRACE, + btoken::EQUAL)?) { + btoken::SEMICOLON => { + synassert(mkloc(lexer), !name.1, + "Unexpected trailing :: in ident")?; + append(imports, name.0: ast::import_module); + }, + btoken::LBRACE => { + synassert(mkloc(lexer), name.1, + "Expected trailing :: in ident")?; + let objects = name_list(lexer)?; + append(imports, ast::import_objects { + ident = name.0, + objects = objects, + }); + want_btoken(lexer, btoken::SEMICOLON)?; + }, + btoken::EQUAL => { + synassert(mkloc(lexer), + len(name.0) == 1 && !name.1, + "Expected name, not ident")?; + let ident = ident(lexer)?; + append(imports, ast::import_alias { + ident = ident, + alias = name.0[0], + }); + want_btoken(lexer, btoken::SEMICOLON)?; + }, + * => abort(), // Unreachable + }; + }; + return imports; +}; diff --git a/hare/parse/parse.ha b/hare/parse/parse.ha @@ -1,96 +0,0 @@ -use hare::ast; -use hare::lex; -use hare::lex::{btoken}; -use slice; - -fn ident_trailing(lexer: *lex::lexer) ((ast::ident, bool) | error) = { - let ident: []str = []; - let z = 0z; - for (true) { - let name = match (try_name(lexer)?) { - n: lex::name => n, - void => return (ident: ast::ident, true), - }; - append(ident, name: str); - z += len(name); - match (try_btoken(lexer, btoken::DOUBLE_COLON)?) { - void => break, - * => void, // Grab the next ident - }; - z += 1; - }; - if (z > ast::IDENT_MAX) { - ast::ident_free(ident: ast::ident); - return syntaxerr(mkloc(lexer), - "Identifier exceeds maximum length"); - }; - return (ident: ast::ident, false); -}; - -// Parses a single identifier, i.e. foo::bar::baz -export fn ident(lexer: *lex::lexer) (ast::ident | error) = { - let ident = ident_trailing(lexer)?; - synassert(mkloc(lexer), !ident.1, "Unexpected trailing :: in ident")?; - return ident.0; -}; - -fn parse_name_list(lexer: *lex::lexer) ([]str | error) = { - let names: []str = []; - for (true) { - append(names, want_name(lexer)?: str); - switch (want_btoken(lexer, btoken::COMMA, btoken::RBRACE)?) { - btoken::COMMA => match (try_btoken(lexer, btoken::RBRACE)?) { - void => void, - * => return names, - }, - btoken::RBRACE => return names, - * => abort(), // Unreachable - }; - }; - abort(); -}; - -// Parses the import list for a sub-unit -export fn imports(lexer: *lex::lexer) ([]ast::import | error) = { - let imports: []ast::import = []; - for (true) { - match (try_btoken(lexer, btoken::USE)?) { - void => break, - * => void, - }; - - let name = ident_trailing(lexer)?; - - switch (want_btoken(lexer, btoken::SEMICOLON, btoken::LBRACE, - btoken::EQUAL)?) { - btoken::SEMICOLON => { - synassert(mkloc(lexer), !name.1, - "Unexpected trailing :: in ident")?; - append(imports, name.0: ast::import_module); - }, - btoken::LBRACE => { - synassert(mkloc(lexer), name.1, - "Expected trailing :: in ident")?; - let objects = parse_name_list(lexer)?; - append(imports, ast::import_objects { - ident = name.0, - objects = objects, - }); - want_btoken(lexer, btoken::SEMICOLON)?; - }, - btoken::EQUAL => { - synassert(mkloc(lexer), - len(name.0) == 1 && !name.1, - "Expected name, not ident")?; - let ident = ident(lexer)?; - append(imports, ast::import_alias { - ident = ident, - alias = name.0[0], - }); - want_btoken(lexer, btoken::SEMICOLON)?; - }, - * => abort(), // Unreachable - }; - }; - return imports; -}; diff --git a/hare/parse/type.ha b/hare/parse/type.ha @@ -0,0 +1,256 @@ +use hare::ast; +use hare::ast::{builtin_type}; +use hare::lex; +use hare::lex::{btoken}; + +fn prototype(lexer: *lex::lexer) (ast::func_type | error) = { + let variadism = ast::variadism::NONE; + let params: []ast::func_param = []; + want_btoken(lexer, btoken::LPAREN)?; + for (try_btoken(lexer, btoken::RPAREN)? is void) { + let loc = mkloc(lexer); + match (try_btoken(lexer, btoken::ELLIPSIS)?) { + void => void, + lex::btoken => { + synassert(loc, len(params) > 0, + "Expected at least one non-variadic parameter for C-style variadism")?; + variadism = ast::variadism::C; + try_btoken(lexer, btoken::COMMA)?; + want_btoken(lexer, btoken::RPAREN)?; + break; + }, + }; + let name = match (try_btoken(lexer, btoken::UNDERSCORE)?) { + void => want_name(lexer)?: str, + lex::btoken => "", + }; + want_btoken(lexer, btoken::COLON); + append(params, ast::func_param { + loc = loc, + name = name, + _type = alloc(_type(lexer)?), + }); + match (try_btoken(lexer, btoken::ELLIPSIS)?) { + void => void, + lex::btoken => { + variadism = ast::variadism::HARE; + try_btoken(lexer, btoken::COMMA)?; + want_btoken(lexer, btoken::RPAREN)?; + break; + }, + }; + match (try_btoken(lexer, btoken::COMMA)?) { + void => { + want_btoken(lexer, btoken::RPAREN)?; + break; + }, + lex::btoken => void, + }; + }; + let t = _type(lexer)?; + return ast::func_type { + result = alloc(t), + attrs = 0, + variadism = variadism, + params = params, + }; +}; + +fn integer_type( + lexer: *lex::lexer, +) (builtin_type | error) = switch (want_btoken(lexer)?) { + btoken::CHAR => builtin_type::CHAR, + btoken::I16 => builtin_type::I16, + btoken::I32 => builtin_type::I32, + btoken::I64 => builtin_type::I64, + btoken::I64 => builtin_type::I64, + btoken::I8 => builtin_type::I8, + btoken::INT => builtin_type::INT, + btoken::SIZE => builtin_type::SIZE, + btoken::U16 => builtin_type::U16, + btoken::U32 => builtin_type::U32, + btoken::U64 => builtin_type::U64, + btoken::U64 => builtin_type::U64, + btoken::U8 => builtin_type::U8, + btoken::UINT => builtin_type::UINT, + btoken::UINTPTR => builtin_type::UINTPTR, + * => syntaxerr(mkloc(lexer), "Expected integer type"), +}; + +fn primitive_type(lexer: *lex::lexer) (ast::_type | error) = { + let t = match (lex::lex(lexer)?) { + io::EOF => return syntaxerr(mkloc(lexer), + "Expected primitive type, got EOF"), + t: (lex::token, lex::location) => t, + }; + let b = match (t.0) { + b: lex::btoken => b, + * => return syntaxerr(mkloc(lexer), + "Expected primitive type, got <something else>"), + }; + let builtin = switch (b) { + btoken::CHAR, btoken::I16, btoken::I32, btoken::I64, + btoken::I64, btoken::I8, btoken::INT, btoken::SIZE, btoken::U16, + btoken::U32, btoken::U64, btoken::U64, btoken::U8, btoken::UINT, + btoken::UINTPTR => { + lex::unlex(lexer, t); + integer_type(lexer)?; + }, + btoken::RUNE => builtin_type::RUNE, + btoken::STR => builtin_type::STR, + btoken::F32 => builtin_type::F32, + btoken::F64 => builtin_type::F64, + btoken::BOOL => builtin_type::BOOL, + btoken::VOID => builtin_type::VOID, + btoken::NULL => builtin_type::NULL, + * => return syntaxerr(mkloc(lexer), "Expected primitive type"), + }; + return ast::_type { + loc = mkloc(lexer), + flags = 0, + _type = builtin, + }; +}; + +fn alias_type(lexer: *lex::lexer) (ast::_type | error) = { + let loc = mkloc(lexer); + let unwrap = match (try_btoken(lexer, btoken::ELLIPSIS)?) { + void => false, + * => true, + }; + return ast::_type { + loc = loc, + flags = 0, + _type = ast::alias_type { + unwrap = unwrap, + ident = ident(lexer)?, + }, + }; +}; + +fn pointer_type(lexer: *lex::lexer) (ast::_type | error) = { + let loc = mkloc(lexer); + let flags = match (try_btoken(lexer, btoken::NULLABLE)?) { + void => 0: ast::pointer_flags, + * => ast::pointer_flags::NULLABLE, + }; + want_btoken(lexer, btoken::TIMES)?; + return ast::_type { + loc = loc, + flags = 0, + _type = ast::pointer_type { + referent = alloc(_type(lexer)?), + flags = flags, + }, + }; +}; + +fn tagged_type(lexer: *lex::lexer, first: ast::_type) (ast::_type | error) = { + let loc = mkloc(lexer); + let tagged: ast::tagged_type = []; + append(tagged, alloc(first)); + for (try_btoken(lexer, btoken::RPAREN)? is void) { + append(tagged, alloc(_type(lexer)?)); + match (try_btoken(lexer, btoken::BOR)?) { + void => { + want_btoken(lexer, btoken::RPAREN)?; + break; + }, + lex::btoken => void, + }; + }; + return ast::_type { + loc = loc, + flags = 0, + _type = tagged, + }; +}; + +fn tuple_type(lexer: *lex::lexer, first: ast::_type) (ast::_type | error) = { + let loc = mkloc(lexer); + let tuple: ast::tuple_type = []; + append(tuple, alloc(first)); + for (try_btoken(lexer, btoken::RPAREN)? is void) { + append(tuple, alloc(_type(lexer)?)); + match (try_btoken(lexer, btoken::COMMA)?) { + void => { + want_btoken(lexer, btoken::RPAREN)?; + break; + }, + lex::btoken => void, + }; + }; + return ast::_type { + loc = loc, + flags = 0, + _type = tuple, + }; +}; + +fn fn_type(lexer: *lex::lexer) (ast::_type | error) = { + let loc = mkloc(lexer); + let attrs = match (try_btoken(lexer, btoken::ATTR_NORETURN)?) { + void => 0: ast::func_attrs, + * => ast::func_attrs::NORETURN, + }; + want_btoken(lexer, btoken::FN)?; + let proto = prototype(lexer)?; + proto.attrs |= attrs; + return ast::_type { + loc = loc, + flags = ast::type_flags::CONST, + _type = proto, + }; +}; + +// Parses a type +export fn _type(lexer: *lex::lexer) (ast::_type | error) = { + let flags: ast::type_flags = match (try_btoken(lexer, btoken::CONST)?) { + void => 0, + * => ast::type_flags::CONST, + }; + let t = match (lex::lex(lexer)?) { + io::EOF => return syntaxerr(mkloc(lexer), + "Expected type, found EOF"), + t: (lex::token, lex::location) => t, + }; + lex::unlex(lexer, t); + let typ: ast::_type = match (t.0) { + b: lex::btoken => switch (b) { + btoken::CHAR, btoken::I16, btoken::I32, btoken::I64, + btoken::I64, btoken::I8, btoken::INT, btoken::SIZE, + btoken::U16, btoken::U32, btoken::U64, btoken::U64, + btoken::U8, btoken::UINT, btoken::UINTPTR, btoken::RUNE, + btoken::STR, btoken::F32, btoken::F64, btoken::BOOL, + btoken::VOID, btoken::NULL => primitive_type(lexer)?, + btoken::ENUM => abort(), // TODO + btoken::NULLABLE, btoken::TIMES => pointer_type(lexer)?, + btoken::STRUCT, btoken::UNION => abort(), // TODO + btoken::LBRACKET => abort(), // TODO + btoken::LPAREN => { + want_btoken(lexer, btoken::LPAREN)?; + let t = _type(lexer)?; + switch (want_btoken(lexer, btoken::BOR, + btoken::COMMA)?) { + btoken::BOR => tagged_type(lexer, t)?, + btoken::COMMA => tuple_type(lexer, t)?, + * => abort("unreachable"), + }; + }, + btoken::ATTR_NORETURN, btoken::FN => fn_type(lexer)?, + btoken::ELLIPSIS => alias_type(lexer)?, + * => return syntaxerr(mkloc(lexer), "Expected type"), + }, + lex::name => alias_type(lexer)?, + * => return syntaxerr(mkloc(lexer), + "Expected type, found <something>"), + }; + + match (try_btoken(lexer, btoken::LNOT)?) { + void => void, + * => flags |= ast::type_flags::ERROR, + }; + + typ.flags |= flags; + return typ; +}; diff --git a/hare/parse/unit.ha b/hare/parse/unit.ha @@ -0,0 +1,11 @@ +use hare::ast; +use hare::lex; + +export fn subunit(lexer: *lex::lexer) (ast::subunit | error) = { + let i = imports(lexer)?; + let d = decls(lexer)?; + return ast::subunit { + imports = i, + decls = d, + }; +}; diff --git a/hare/parse/util.ha b/hare/parse/util.ha @@ -39,6 +39,9 @@ fn want_btoken( "Expected name, found EOF"), t: (lex::token, lex::location) => match (t.0) { b: lex::btoken => { + if (len(want) == 0) { + return b; + }; for (let i = 0z; i < len(want); i += 1) { if (b == want[i]) { return b; diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib @@ -294,14 +294,19 @@ hare_module() { manifest.ha gen_ssa hare::module \ hare::ast hare::lex hare::parse hare::unparse strio fs io strings hash \ - crypto::sha256 dirs bytes encoding::utf8 ascii fmt time + crypto::sha256 dirs bytes encoding::utf8 ascii fmt time slice } gensrcs_hare_parse() { gen_srcs hare::parse \ + decl.ha \ + expr.ha \ + ident.ha \ + import.ha \ + type.ha \ types.ha \ + unit.ha \ util.ha \ - parse.ha \ $* } @@ -310,11 +315,13 @@ hare_parse() { if [ $testing -eq 0 ] then gensrcs_hare_parse + gen_ssa hare::parse hare::ast hare::lex else gensrcs_hare_parse \ +test.ha + gen_ssa hare::parse bufio fmt hare::ast hare::lex hare::unparse io \ + strings strio fi - gen_ssa hare::parse hare::ast hare::lex slice } hash() { diff --git a/stdlib.mk b/stdlib.mk @@ -383,7 +383,7 @@ stdlib_hare_module_srcs= \ $(STDLIB)/hare/module/scan.ha \ $(STDLIB)/hare/module/manifest.ha -$(HARECACHE)/hare/module/hare_module.ssa: $(stdlib_hare_module_srcs) $(stdlib_rt) $(stdlib_hare_ast) $(stdlib_hare_lex) $(stdlib_hare_parse) $(stdlib_hare_unparse) $(stdlib_strio) $(stdlib_fs) $(stdlib_io) $(stdlib_strings) $(stdlib_hash) $(stdlib_crypto_sha256) $(stdlib_dirs) $(stdlib_bytes) $(stdlib_encoding_utf8) $(stdlib_ascii) $(stdlib_fmt) $(stdlib_time) +$(HARECACHE)/hare/module/hare_module.ssa: $(stdlib_hare_module_srcs) $(stdlib_rt) $(stdlib_hare_ast) $(stdlib_hare_lex) $(stdlib_hare_parse) $(stdlib_hare_unparse) $(stdlib_strio) $(stdlib_fs) $(stdlib_io) $(stdlib_strings) $(stdlib_hash) $(stdlib_crypto_sha256) $(stdlib_dirs) $(stdlib_bytes) $(stdlib_encoding_utf8) $(stdlib_ascii) $(stdlib_fmt) $(stdlib_time) $(stdlib_slice) @printf 'HAREC \t$@\n' @mkdir -p $(HARECACHE)/hare/module @HARECACHE=$(HARECACHE) $(HAREC) $(HAREFLAGS) -o $@ -Nhare::module \ @@ -391,11 +391,16 @@ $(HARECACHE)/hare/module/hare_module.ssa: $(stdlib_hare_module_srcs) $(stdlib_rt # hare::parse stdlib_hare_parse_srcs= \ + $(STDLIB)/hare/parse/decl.ha \ + $(STDLIB)/hare/parse/expr.ha \ + $(STDLIB)/hare/parse/ident.ha \ + $(STDLIB)/hare/parse/import.ha \ + $(STDLIB)/hare/parse/type.ha \ $(STDLIB)/hare/parse/types.ha \ - $(STDLIB)/hare/parse/util.ha \ - $(STDLIB)/hare/parse/parse.ha + $(STDLIB)/hare/parse/unit.ha \ + $(STDLIB)/hare/parse/util.ha -$(HARECACHE)/hare/parse/hare_parse.ssa: $(stdlib_hare_parse_srcs) $(stdlib_rt) $(stdlib_hare_ast) $(stdlib_hare_lex) $(stdlib_slice) +$(HARECACHE)/hare/parse/hare_parse.ssa: $(stdlib_hare_parse_srcs) $(stdlib_rt) $(stdlib_hare_ast) $(stdlib_hare_lex) @printf 'HAREC \t$@\n' @mkdir -p $(HARECACHE)/hare/parse @HARECACHE=$(HARECACHE) $(HAREC) $(HAREFLAGS) -o $@ -Nhare::parse \ @@ -1030,7 +1035,7 @@ testlib_hare_module_srcs= \ $(STDLIB)/hare/module/scan.ha \ $(STDLIB)/hare/module/manifest.ha -$(TESTCACHE)/hare/module/hare_module.ssa: $(testlib_hare_module_srcs) $(testlib_rt) $(testlib_hare_ast) $(testlib_hare_lex) $(testlib_hare_parse) $(testlib_hare_unparse) $(testlib_strio) $(testlib_fs) $(testlib_io) $(testlib_strings) $(testlib_hash) $(testlib_crypto_sha256) $(testlib_dirs) $(testlib_bytes) $(testlib_encoding_utf8) $(testlib_ascii) $(testlib_fmt) $(testlib_time) +$(TESTCACHE)/hare/module/hare_module.ssa: $(testlib_hare_module_srcs) $(testlib_rt) $(testlib_hare_ast) $(testlib_hare_lex) $(testlib_hare_parse) $(testlib_hare_unparse) $(testlib_strio) $(testlib_fs) $(testlib_io) $(testlib_strings) $(testlib_hash) $(testlib_crypto_sha256) $(testlib_dirs) $(testlib_bytes) $(testlib_encoding_utf8) $(testlib_ascii) $(testlib_fmt) $(testlib_time) $(testlib_slice) @printf 'HAREC \t$@\n' @mkdir -p $(TESTCACHE)/hare/module @HARECACHE=$(TESTCACHE) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nhare::module \ @@ -1038,12 +1043,17 @@ $(TESTCACHE)/hare/module/hare_module.ssa: $(testlib_hare_module_srcs) $(testlib_ # hare::parse testlib_hare_parse_srcs= \ + $(STDLIB)/hare/parse/decl.ha \ + $(STDLIB)/hare/parse/expr.ha \ + $(STDLIB)/hare/parse/ident.ha \ + $(STDLIB)/hare/parse/import.ha \ + $(STDLIB)/hare/parse/type.ha \ $(STDLIB)/hare/parse/types.ha \ + $(STDLIB)/hare/parse/unit.ha \ $(STDLIB)/hare/parse/util.ha \ - $(STDLIB)/hare/parse/parse.ha \ $(STDLIB)/hare/parse/+test.ha -$(TESTCACHE)/hare/parse/hare_parse.ssa: $(testlib_hare_parse_srcs) $(testlib_rt) $(testlib_hare_ast) $(testlib_hare_lex) $(testlib_slice) +$(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) @printf 'HAREC \t$@\n' @mkdir -p $(TESTCACHE)/hare/parse @HARECACHE=$(TESTCACHE) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nhare::parse \