aboutsummaryrefslogtreecommitdiff
path: root/src/checker.cpp
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-10-07 11:37:43 +0100
committerGinger Bill <bill@gingerbill.org>2017-10-07 11:37:43 +0100
commitdf7a4eda8aaeb134e10a507b21c31637c84781e1 (patch)
tree264b33f3d2821d78c3cdf0dc0fd9f634de27fc06 /src/checker.cpp
parent91cc0b282a7dec026e8608dd16b109470ab1a60b (diff)
Allow for cyclic `import` but disallow cyclic `using import` and `export`
Diffstat (limited to 'src/checker.cpp')
-rw-r--r--src/checker.cpp85
1 files changed, 49 insertions, 36 deletions
diff --git a/src/checker.cpp b/src/checker.cpp
index eeac82b6e..82124cd90 100644
--- a/src/checker.cpp
+++ b/src/checker.cpp
@@ -228,8 +228,8 @@ struct Scope {
Array<Scope *> shared;
Array<AstNode *> delayed_file_decls;
- PtrSet<Scope *> import_succ;
PtrSet<Scope *> imported;
+ PtrSet<Scope *> exported; // NOTE(bhall): Contains `using import` too
bool is_proc;
bool is_global;
bool is_file;
@@ -248,7 +248,6 @@ void scope_reset(Scope *scope) {
map_clear (&scope->elements);
map_clear (&scope->implicit);
array_clear(&scope->shared);
- ptr_set_clear(&scope->import_succ);
ptr_set_clear(&scope->imported);
}
@@ -387,6 +386,7 @@ int import_graph_node_cmp(ImportGraphNode **data, isize i, isize j) {
bool xg = x->scope->is_global;
bool yg = y->scope->is_global;
if (xg != yg) return xg ? -1 : +1;
+ if (xg && yg) return x->file_id < y->file_id ? -1 : +1;
if (x->dep_count < y->dep_count) return -1;
if (x->dep_count > y->dep_count) return +1;
return 0;
@@ -564,11 +564,11 @@ bool decl_info_has_init(DeclInfo *d) {
Scope *create_scope(Scope *parent, gbAllocator allocator) {
Scope *s = gb_alloc_item(allocator, Scope);
s->parent = parent;
- map_init(&s->elements, heap_allocator());
- map_init(&s->implicit, heap_allocator());
- array_init(&s->shared, heap_allocator());
+ map_init(&s->elements, heap_allocator());
+ map_init(&s->implicit, heap_allocator());
+ array_init(&s->shared, heap_allocator());
ptr_set_init(&s->imported, heap_allocator());
- ptr_set_init(&s->import_succ, heap_allocator());
+ ptr_set_init(&s->exported, heap_allocator());
if (parent != nullptr && parent != universal_scope) {
DLIST_APPEND(parent->first_child, parent->last_child, s);
@@ -625,7 +625,6 @@ void destroy_scope(Scope *scope) {
array_free(&scope->shared);
array_free(&scope->delayed_file_decls);
ptr_set_destroy(&scope->imported);
- ptr_set_destroy(&scope->import_succ);
// NOTE(bill): No need to free scope as it "should" be allocated in an arena (except for the global scope)
}
@@ -2305,11 +2304,12 @@ void add_import_dependency_node(Checker *c, AstNode *decl, Map<ImportGraphNode *
n = *found_node;
// TODO(bill): How should the edges be attched for `import`?
- if (id->is_using) {
- }
import_graph_node_set_add(&n->succ, m);
import_graph_node_set_add(&m->pred, n);
ptr_set_add(&m->scope->imported, n->scope);
+ if (id->is_using) {
+ ptr_set_add(&m->scope->exported, n->scope);
+ }
case_end;
@@ -2343,7 +2343,7 @@ void add_import_dependency_node(Checker *c, AstNode *decl, Map<ImportGraphNode *
import_graph_node_set_add(&n->succ, m);
import_graph_node_set_add(&m->pred, n);
- ptr_set_add(&m->scope->imported, n->scope);
+ ptr_set_add(&m->scope->exported, n->scope);
case_end;
case_ast_node(ws, WhenStmt, decl);
@@ -2413,7 +2413,6 @@ Array<ImportGraphNode *> generate_import_dependency_graph(Checker *c) {
return G;
}
-
Array<Scope *> find_import_path(Map<Scope *> *file_scopes, Scope *start, Scope *end, PtrSet<Scope *> *visited = nullptr) {
PtrSet<Scope *> visited_ = {};
bool made_visited = false;
@@ -2438,8 +2437,8 @@ Array<Scope *> find_import_path(Map<Scope *> *file_scopes, Scope *start, Scope *
Scope **found = map_get(file_scopes, key);
if (found) {
Scope *scope = *found;
- for_array(i, scope->imported.entries) {
- Scope *dep = scope->imported.entries[i].ptr;
+ for_array(i, scope->exported.entries) {
+ Scope *dep = scope->exported.entries[i].ptr;
if (dep == end) {
Array<Scope *> path = {};
array_init(&path, heap_allocator());
@@ -2452,6 +2451,17 @@ Array<Scope *> find_import_path(Map<Scope *> *file_scopes, Scope *start, Scope *
return next_path;
}
}
+
+ // NOTE(bill): Disallow importing of the same file
+ for_array(i, scope->imported.entries) {
+ Scope *dep = scope->imported.entries[i].ptr;
+ if (dep == start) {
+ Array<Scope *> path = {};
+ array_init(&path, heap_allocator());
+ array_add(&path, dep);
+ return path;
+ }
+ }
}
return empty_path;
}
@@ -2487,6 +2497,19 @@ 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)) {
+ 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);
+
+ add_entity(c, parent_scope, nullptr, e);
+ }
+
if (id->is_using) {
if (parent_scope->is_global) {
error(id->import_name, "#shared_global_scope imports cannot use using");
@@ -2506,19 +2529,6 @@ void check_add_import_decl(Checker *c, AstNodeImportDecl *id) {
if (ok) map_set(&parent_scope->implicit, hash_entity(e), true);
}
}
- } else {
- String import_name = path_to_entity_name(id->import_name.string, id->fullpath);
- if (is_blank_ident(import_name)) {
- 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);
-
- add_entity(c, parent_scope, nullptr, e);
- }
}
ptr_set_add(&c->checked_files, scope->file);
scope->has_been_imported = true;
@@ -2832,16 +2842,19 @@ void check_import_entities(Checker *c) {
auto path = find_import_path(&c->file_scopes, s, s);
defer (array_free(&path));
- if (path.count > 0) {
- // TODO(bill): This needs better TokenPos finding
- auto const mt = [](Scope *s) -> Token {
- Token token = {};
- token.pos = token_pos(s->file->tokenizer.fullpath, 1, 1);
- token.string = remove_directory_from_path(s->file->tokenizer.fullpath);
- return token;
- };
-
+ // TODO(bill): This needs better TokenPos finding
+ auto const mt = [](Scope *s) -> Token {
+ Token token = {};
+ token.pos = token_pos(s->file->tokenizer.fullpath, 1, 1);
+ token.string = remove_directory_from_path(s->file->tokenizer.fullpath);
+ return token;
+ };
+ if (path.count == 1) {
+ Scope *s = path[0];
+ Token token = mt(s);
+ error(token, "Self importation of `%.*s`", LIT(token.string));
+ } else if (path.count > 0) {
Scope *s = path[path.count-1];
Token token = mt(s);
error(token, "Cyclic importation of `%.*s`", LIT(token.string));
@@ -2884,7 +2897,7 @@ void check_import_entities(Checker *c) {
// for_array(file_index, c->file_order) {
// ImportGraphNode *node = c->file_order[file_index];
// AstFile *f = node->scope->file;
- // gb_printf_err("--- %.*s\n", LIT(f->fullpath));
+ // gb_printf_err("--- %.*s -> %td\n", LIT(f->fullpath), node->succ.entries.count);
// }
for (;;) {