aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2017-12-17 11:17:54 +0000
committergingerBill <bill@gingerbill.org>2017-12-17 11:17:54 +0000
commit0d665c637f164bb077b9d63bb947690affede6dd (patch)
treee34473bf59800ab5f1b2d5c8d33652679748494a /src
parent1b6a14ac39165d848cf5e4fd970d2dc2992fc439 (diff)
`using in` importation statements
Diffstat (limited to 'src')
-rw-r--r--src/checker.cpp120
-rw-r--r--src/parser.cpp21
2 files changed, 109 insertions, 32 deletions
diff --git a/src/checker.cpp b/src/checker.cpp
index 873851509..d8ada0bfc 100644
--- a/src/checker.cpp
+++ b/src/checker.cpp
@@ -2642,21 +2642,24 @@ void check_add_import_decl(Checker *c, AstNodeImportDecl *id) {
ptr_set_add(&parent_scope->imported, scope);
}
- String import_name = path_to_entity_name(id->import_name.string, id->fullpath);
- if (is_blank_ident(import_name)) {
- if (id->is_using) {
- // TODO(bill): Should this be a warning?
+
+ if (id->using_in_list.count == 0) {
+ String import_name = path_to_entity_name(id->import_name.string, id->fullpath);
+ if (is_blank_ident(import_name)) {
+ if (id->is_using) {
+ // TODO(bill): Should this be a warning?
+ } else {
+ error(token, "File name, %.*s, cannot be use as an import name as it is not a valid identifier", LIT(id->import_name.string));
+ }
} else {
- error(token, "File name, %.*s, cannot be use as an import name as it is not a valid identifier", LIT(id->import_name.string));
- }
- } else {
- GB_ASSERT(id->import_name.pos.line != 0);
- id->import_name.string = import_name;
- Entity *e = make_entity_import_name(c->allocator, parent_scope, id->import_name, t_invalid,
- id->fullpath, id->import_name.string,
- scope);
+ GB_ASSERT(id->import_name.pos.line != 0);
+ id->import_name.string = import_name;
+ Entity *e = make_entity_import_name(c->allocator, parent_scope, id->import_name, t_invalid,
+ id->fullpath, id->import_name.string,
+ scope);
- add_entity(c, parent_scope, nullptr, e);
+ add_entity(c, parent_scope, nullptr, e);
+ }
}
if (id->is_using) {
@@ -2664,21 +2667,48 @@ void check_add_import_decl(Checker *c, AstNodeImportDecl *id) {
error(id->import_name, "#shared_global_scope imports cannot use using");
return;
}
- // NOTE(bill): Add imported entities to this file's scope
- for_array(elem_index, scope->elements.entries) {
- Entity *e = scope->elements.entries[elem_index].value;
- if (e->scope == parent_scope) continue;
- if (e->token.string == "get_proc_address") {
- // gb_printf_err("%.*s %.*s get_proc_address\n", LIT(scope->file->fullpath), LIT(parent_scope->file->fullpath));
+ // NOTE(bill): Add imported entities to this file's scope
+ if (id->using_in_list.count > 0) {
+ for_array(list_index, id->using_in_list) {
+ AstNode *node = id->using_in_list[list_index];
+ ast_node(ident, Ident, node);
+ String name = ident->token.string;
+
+ Entity *e = scope_lookup_entity(scope, name);
+ if (e == nullptr) {
+ if (is_blank_ident(name)) {
+ error(node, "'_' cannot be used as a value");
+ } else {
+ error(node, "Undeclared name in this importation: '%.*s'", LIT(name));
+ }
+ continue;
+ }
+ if (e->scope == parent_scope) continue;
+
+ bool implicit_is_found = ptr_set_exists(&scope->implicit, e);
+ if (is_entity_exported(e) && !implicit_is_found) {
+ Entity *prev = scope_lookup_entity(parent_scope, e->token.string);
+ // if (prev) gb_printf_err("%.*s\n", LIT(prev->token.string));
+ bool ok = add_entity(c, parent_scope, e->identifier, e);
+ if (ok) ptr_set_add(&parent_scope->implicit, e);
+ } else {
+ error(node, "'%.*s' is exported from this scope", LIT(name));
+ continue;
+ }
}
-
- bool implicit_is_found = ptr_set_exists(&scope->implicit, e);
- if (is_entity_exported(e) && !implicit_is_found) {
- Entity *prev = scope_lookup_entity(parent_scope, e->token.string);
- // if (prev) gb_printf_err("%.*s\n", LIT(prev->token.string));
- bool ok = add_entity(c, parent_scope, e->identifier, e);
- if (ok) ptr_set_add(&parent_scope->implicit, e);
+ } else {
+ for_array(elem_index, scope->elements.entries) {
+ Entity *e = scope->elements.entries[elem_index].value;
+ if (e->scope == parent_scope) continue;
+
+ bool implicit_is_found = ptr_set_exists(&scope->implicit, e);
+ if (is_entity_exported(e) && !implicit_is_found) {
+ Entity *prev = scope_lookup_entity(parent_scope, e->token.string);
+ // if (prev) gb_printf_err("%.*s\n", LIT(prev->token.string));
+ bool ok = add_entity(c, parent_scope, e->identifier, e);
+ if (ok) ptr_set_add(&parent_scope->implicit, e);
+ }
}
}
}
@@ -2722,13 +2752,39 @@ void check_add_export_decl(Checker *c, AstNodeExportDecl *ed) {
ptr_set_add(&parent_scope->imported, scope);
}
- // NOTE(bill): Add imported entities to this file's scope
- for_array(elem_index, scope->elements.entries) {
- Entity *e = scope->elements.entries[elem_index].value;
- if (e->scope == parent_scope) continue;
+ if (ed->using_in_list.count > 0) {
+ for_array(list_index, ed->using_in_list) {
+ AstNode *node = ed->using_in_list[list_index];
+ ast_node(ident, Ident, node);
+ String name = ident->token.string;
+
+ Entity *e = scope_lookup_entity(scope, name);
+ if (e == nullptr) {
+ if (is_blank_ident(name)) {
+ error(node, "'_' cannot be used as a value");
+ } else {
+ error(node, "Undeclared name in this importation: '%.*s'", LIT(name));
+ }
+ continue;
+ }
+ if (e->scope == parent_scope) continue;
- if (is_entity_kind_exported(e->kind)) {
- add_entity(c, parent_scope, e->identifier, e);
+ if (is_entity_exported(e)) {
+ add_entity(c, parent_scope, e->identifier, e);
+ } else {
+ error(node, "'%.*s' is exported from this scope", LIT(name));
+ continue;
+ }
+ }
+ } else {
+ // NOTE(bill): Add imported entities to this file's scope
+ for_array(elem_index, scope->elements.entries) {
+ Entity *e = scope->elements.entries[elem_index].value;
+ if (e->scope == parent_scope) continue;
+
+ if (is_entity_kind_exported(e->kind)) {
+ add_entity(c, parent_scope, e->identifier, e);
+ }
}
}
diff --git a/src/parser.cpp b/src/parser.cpp
index 23b99a2ba..8c96b1fb2 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -362,6 +362,7 @@ AST_NODE_KIND(_DeclBegin, "", i32) \
Token import_name; \
bool is_using; \
bool been_handled; \
+ Array<AstNode *> using_in_list; \
CommentGroup docs; \
CommentGroup comment; \
}) \
@@ -371,6 +372,7 @@ AST_NODE_KIND(_DeclBegin, "", i32) \
Token relpath; \
String fullpath; \
bool been_handled; \
+ Array<AstNode *> using_in_list; \
CommentGroup docs; \
CommentGroup comment; \
}) \
@@ -4518,6 +4520,25 @@ AstNode *parse_stmt(AstFile *f) {
return ast_bad_stmt(f, token, f->curr_token);
}
+ if (f->curr_token.kind == Token_in) {
+ Token in_token = expect_token(f, Token_in);
+ if (f->curr_token.kind == Token_import) {
+ AstNode *import_decl = parse_import_decl(f, true);
+ if (import_decl->kind == AstNode_ImportDecl) {
+ import_decl->ImportDecl.using_in_list = list;
+ }
+ return import_decl;
+ } else if (f->curr_token.kind == Token_export) {
+ AstNode *export_decl = parse_export_decl(f);
+ if (export_decl->kind == AstNode_ExportDecl) {
+ export_decl->ExportDecl.using_in_list = list;
+ }
+ return export_decl;
+ }
+ syntax_error(token, "Illegal use of 'using' statement");
+ return ast_bad_stmt(f, token, f->curr_token);
+ }
+
if (f->curr_token.kind != Token_Colon) {
expect_semicolon(f, list[list.count-1]);
return ast_using_stmt(f, token, list);