harec

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 3c083f52bc45cf51e3bdf943585ac8ce412ec3d6
parent 9caae7b9fa389ea58025c9f55513b63e6661b2ea
Author: Armin Weigl <tb46305@gmail.com>
Date:   Tue, 23 Feb 2021 17:21:26 +0100

Implement imports

Fixes hare#9

Diffstat:
Msrc/check.c | 30+++++++++++++++++++++++++-----
Msrc/parse.c | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Atests/24-imports.ha | 10++++++++++
Mtests/configure | 3++-
4 files changed, 91 insertions(+), 10 deletions(-)

diff --git a/src/check.c b/src/check.c @@ -2584,13 +2584,13 @@ load_import(struct ast_imports *import, obj; obj = obj->next) { scope_insert(scope, obj->otype, &obj->ident, &obj->name, obj->type, obj->value); - if (obj->ident.ns && obj->ident.ns->ns) { + if (obj->name.ns && obj->name.ns->ns) { struct identifier ns = { - .name = obj->ident.ns->name, + .name = obj->name.ns->name, .ns = NULL }; struct identifier name = { - .name = obj->ident.name, + .name = obj->name.name, .ns = &ns, }; scope_insert(scope, obj->otype, &obj->ident, @@ -2599,9 +2599,29 @@ load_import(struct ast_imports *import, } break; case AST_IMPORT_ALIAS: - assert(0); // TODO + for (struct scope_object *obj = mod->objects; + obj; obj = obj->next) { + struct identifier name = { + .name = obj->name.name, + .ns = import->alias, + }; + scope_insert(scope, obj->otype, &obj->ident, + &name, obj->type, obj->value); + } + break; case AST_IMPORT_MEMBERS: - assert(0); // TODO + for (struct ast_imports *member = import->members; + member; member = member->next) { + struct identifier name = { + .name = member->ident.name, + .ns = &import->ident, + }; + const struct scope_object *obj = scope_lookup(mod, &name); + name.ns = NULL; + scope_insert(scope, obj->otype, &obj->ident, + &name, obj->type, obj->value); + } + break; } } diff --git a/src/parse.c b/src/parse.c @@ -139,24 +139,74 @@ parse_identifier(struct lexer *lexer, struct identifier *ident, bool trailing) } static void +parse_name_list(struct lexer *lexer, struct ast_imports *name) +{ + trenter(TR_PARSE, "name_list"); + bool more = true; + struct ast_imports **next = &name->next; + while (more) { + struct token tok = {0}; + want(lexer, T_NAME, &tok); + name->ident.name = strdup(tok.name); + token_finish(&tok); + + switch (lex(lexer, &tok)) { + case T_COMMA: + switch (lex(lexer, &tok)) { + case T_RBRACE: + more = false; + break; + default: + unlex(lexer, &tok); + name = xcalloc(1, sizeof(struct ast_imports)); + *next = name; + next = &name->next; + } + break; + case T_RBRACE: + more = false; + break; + default: + synassert(false, &tok, T_RBRACE, T_COMMA, T_EOF); + break; + } + } + trleave(TR_PARSE, NULL); +} + +static void parse_import(struct lexer *lexer, struct ast_imports *imports) { trenter(TR_PARSE, "import"); struct identifier ident = {0}; - parse_identifier(lexer, &ident, false); + bool trailing_colon = parse_identifier(lexer, &ident, true); struct token tok = {0}; switch (lex(lexer, &tok)) { case T_EQUAL: - assert(0); // TODO + synassert(!trailing_colon, &tok, T_NAME, T_EOF); + imports->mode = AST_IMPORT_ALIAS; + imports->alias = xcalloc(1, sizeof(struct identifier)); + *imports->alias = ident; + parse_identifier(lexer, &imports->ident, false); + want(lexer, T_SEMICOLON, &tok); + break; case T_LBRACE: - assert(0); // TODO + synassert(trailing_colon, &tok, T_DOUBLE_COLON, T_EOF); + imports->mode = AST_IMPORT_MEMBERS; + imports->ident = ident; + imports->members = xcalloc(1, sizeof(struct ast_imports)); + parse_name_list(lexer, imports->members); + want(lexer, T_SEMICOLON, &tok); + break; case T_SEMICOLON: + synassert(!trailing_colon, &tok, T_NAME, T_EOF); imports->mode = AST_IMPORT_IDENTIFIER; imports->ident = ident; break; default: - synassert(false, &tok, T_EQUAL, T_LBRACE, T_SEMICOLON, T_EOF); + synassert(!trailing_colon, &tok, T_EQUAL, T_SEMICOLON, T_EOF); + synassert(trailing_colon, &tok, T_NAME, T_LBRACE, T_EOF); break; } diff --git a/tests/24-imports.ha b/tests/24-imports.ha @@ -0,0 +1,10 @@ +use rt; +use test = rt; +use rt::{malloc, free_}; + +export fn main() void = { + assert(&rt::malloc == &test::malloc); + assert(&rt::malloc == &malloc); + assert(&rt::free_ == &test::free_); + assert(&rt::free_ == &free_); +}; diff --git a/tests/configure b/tests/configure @@ -26,7 +26,8 @@ tests() { 20-if \ 21-tuples \ 22-delete \ - 23-errors + 23-errors \ + 24-imports do cat <<EOF tests/$t: libhart.a tests/$t.ha