aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2018-05-26 23:12:55 +0100
committergingerBill <bill@gingerbill.org>2018-05-26 23:12:55 +0100
commitc067b90403ab8493daa0bf5867b2bd92319feea5 (patch)
treef8d8162cc7d0e937c925ed8b07831ffc0e9c75de /src
parent5b6770f3d297c0639bdbe8b1b029616c16669165 (diff)
Add basic package support (no IR support yet)
Diffstat (limited to 'src')
-rw-r--r--src/build_settings.cpp115
-rw-r--r--src/check_decl.cpp4
-rw-r--r--src/check_expr.cpp13
-rw-r--r--src/check_stmt.cpp5
-rw-r--r--src/checker.cpp755
-rw-r--r--src/checker.hpp28
-rw-r--r--src/common.cpp20
-rw-r--r--src/entity.cpp16
-rw-r--r--src/main.cpp29
-rw-r--r--src/parser.cpp203
-rw-r--r--src/parser.hpp18
-rw-r--r--src/string.cpp7
-rw-r--r--src/tokenizer.cpp5
13 files changed, 552 insertions, 666 deletions
diff --git a/src/build_settings.cpp b/src/build_settings.cpp
index c58eb9ed8..13776dedb 100644
--- a/src/build_settings.cpp
+++ b/src/build_settings.cpp
@@ -1,3 +1,38 @@
+enum TargetOsKind {
+ TargetOs_Invalid,
+
+ TargetOs_windows,
+ TargetOs_osx,
+ TargetOs_linux,
+ TargetOs_essence,
+
+ TargetOs_COUNT,
+};
+
+enum TargetArchKind {
+ TargetArch_Invalid,
+
+ TargetArch_amd64,
+ TargetArch_x64,
+
+ TargetArch_COUNT,
+};
+
+String target_os_names[TargetOs_COUNT] = {
+ str_lit(""),
+ str_lit("windows"),
+ str_lit("osx"),
+ str_lit("linux"),
+ str_lit("essence"),
+};
+
+String target_arch_names[TargetArch_COUNT] = {
+ str_lit(""),
+ str_lit("amd64"),
+ str_lit("x86"),
+};
+
+
// This stores the information for the specify architecture of this build
struct BuildContext {
// Constants
@@ -15,6 +50,9 @@ struct BuildContext {
String command;
+ TargetOsKind target_os;
+ TargetArchKind target_arch;
+
String out_filepath;
String resource_filepath;
bool has_resource;
@@ -37,6 +75,72 @@ struct BuildContext {
gb_global BuildContext build_context = {0};
+TargetOsKind get_target_os_from_string(String str) {
+ for (isize i = 0; i < TargetOs_COUNT; i++) {
+ if (target_os_names[i] == str) {
+ return cast(TargetOsKind)i;
+ }
+ }
+ return TargetOs_Invalid;
+}
+
+TargetArchKind get_target_arch_from_string(String str) {
+ for (isize i = 0; i < TargetArch_COUNT; i++) {
+ if (target_os_names[i] == str) {
+ return cast(TargetArchKind)i;
+ }
+ }
+ return TargetArch_Invalid;
+}
+
+bool is_excluded_target_filename(String name) {
+ String const ext = str_lit(".odin");
+ GB_ASSERT(string_ends_with(name, ext));
+ name = substring(name, 0, name.len-ext.len);
+
+ String str1 = {};
+ String str2 = {};
+ isize n = 0;
+
+ str1 = name;
+ n = str1.len;
+ for (isize i = str1.len-1; i >= 0 && str1[i] != '_'; i--) {
+ n -= 1;
+ }
+ str1 = substring(str1, n, str1.len);
+
+ str2 = str1;
+ n = str2.len;
+ for (isize i = str2.len-1; i >= 0 && str2[i] != '_'; i--) {
+ n -= 1;
+ }
+ str2 = substring(str2, n, str2.len);
+
+ if (str1 == name) {
+ return false;
+ }
+
+
+ TargetOsKind os1 = get_target_os_from_string(str1);
+ TargetArchKind arch1 = get_target_arch_from_string(str1);
+ TargetOsKind os2 = get_target_os_from_string(str2);
+ TargetArchKind arch2 = get_target_arch_from_string(str2);
+
+ if (arch1 != TargetArch_Invalid && os2 != TargetOs_Invalid) {
+ return arch1 != build_context.target_arch || os2 != build_context.target_os;
+ } else if (arch1 != TargetArch_Invalid && os1 != TargetOs_Invalid) {
+ return arch2 != build_context.target_arch || os1 != build_context.target_os;
+ } else if (os1 != TargetOs_Invalid) {
+ return os1 != build_context.target_os;
+ } else if (arch1 != TargetArch_Invalid) {
+ return arch1 != build_context.target_arch;
+ }
+
+ return false;
+}
+
+
+
struct LibraryCollections {
String name;
String path;
@@ -327,11 +431,14 @@ void init_build_context(void) {
bc->ODIN_ROOT = odin_root_dir();
#if defined(GB_SYSTEM_WINDOWS)
- bc->ODIN_OS = str_lit("windows");
+ bc->ODIN_OS = str_lit("windows");
+ bc->target_os = TargetOs_windows;
#elif defined(GB_SYSTEM_OSX)
- bc->ODIN_OS = str_lit("osx");
+ bc->ODIN_OS = str_lit("osx");
+ bc->target_os = TargetOs_osx;
#else
- bc->ODIN_OS = str_lit("linux");
+ bc->ODIN_OS = str_lit("linux");
+ bc->target_os = TargetOs_linux;
#endif
if (cross_compile_target.len) {
@@ -340,8 +447,10 @@ void init_build_context(void) {
#if defined(GB_ARCH_64_BIT)
bc->ODIN_ARCH = str_lit("amd64");
+ bc->target_arch = TargetArch_amd64;
#else
bc->ODIN_ARCH = str_lit("x86");
+ bc->target_arch = TargetArch_x86;
#endif
{
diff --git a/src/check_decl.cpp b/src/check_decl.cpp
index f63aecf67..ff4fc6184 100644
--- a/src/check_decl.cpp
+++ b/src/check_decl.cpp
@@ -535,7 +535,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
e->deprecated_message = ac.deprecated_message;
ac.link_name = handle_link_name(c, e->token, ac.link_name, ac.link_prefix);
- if (d->scope->file != nullptr && e->token.string == "main") {
+ if (d->scope->package != nullptr && e->token.string == "main") {
if (pt->param_count != 0 ||
pt->result_count != 0) {
gbString str = type_to_string(proc_type);
@@ -583,7 +583,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
GB_ASSERT(pl->body->kind == AstNode_BlockStmt);
if (!pt->is_polymorphic) {
- check_procedure_later(c, c->curr_ast_file, e->token, d, proc_type, pl->body, pl->tags);
+ check_procedure_later(c, c->curr_ast_package, e->token, d, proc_type, pl->body, pl->tags);
}
} else if (!is_foreign) {
if (e->Procedure.is_export) {
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index ab9a42e6f..34337ce0e 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -109,7 +109,7 @@ void error_operand_no_value(Operand *o) {
void check_scope_decls(Checker *c, Array<AstNode *> nodes, isize reserve_size) {
Scope *s = c->context.scope;
- GB_ASSERT(s->file == nullptr);
+ GB_ASSERT(s->package == nullptr);
check_collect_entities(c, nodes);
@@ -342,17 +342,18 @@ bool find_or_generate_polymorphic_procedure(Checker *c, Entity *base_entity, Typ
// NOTE(bill): Set the scope afterwards as this is not real overloading
entity->scope = scope->parent;
- AstFile *file = nullptr;
+ AstPackage *package = nullptr;
{
Scope *s = entity->scope;
- while (s != nullptr && s->file == nullptr) {
- file = s->file;
+ while (s != nullptr && s->package == nullptr) {
+ package = s->package;
s = s->parent;
}
}
ProcedureInfo proc_info = {};
- proc_info.file = file;
+ // proc_info.file = file;
+ proc_info.package = package;
proc_info.token = token;
proc_info.decl = d;
proc_info.type = final_proc_type;
@@ -5362,7 +5363,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
return kind;
}
- check_procedure_later(c, c->curr_ast_file, empty_token, decl, type, pl->body, pl->tags);
+ check_procedure_later(c, c->curr_ast_package, empty_token, decl, type, pl->body, pl->tags);
}
check_close_scope(c);
diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp
index 54226e565..c0e885664 100644
--- a/src/check_stmt.cpp
+++ b/src/check_stmt.cpp
@@ -627,7 +627,10 @@ void check_switch_stmt(Checker *c, AstNode *node, u32 mod_flags) {
Token token = {};
token.pos = ast_node_token(ss->body).pos;
token.string = str_lit("true");
- x.expr = ast_ident(c->curr_ast_file, token);
+
+ x.expr = gb_alloc_item(c->allocator, AstNode);
+ x.expr->kind = AstNode_Ident;
+ x.expr->Ident.token = token;
}
// NOTE(bill): Check for multiple defaults
diff --git a/src/checker.cpp b/src/checker.cpp
index 0a3c09109..429468c08 100644
--- a/src/checker.cpp
+++ b/src/checker.cpp
@@ -122,9 +122,9 @@ void import_graph_node_set_remove(ImportGraphNodeSet *s, ImportGraphNode *n) {
ImportGraphNode *import_graph_node_create(gbAllocator a, Scope *scope) {
ImportGraphNode *n = gb_alloc_item(a, ImportGraphNode);
- n->scope = scope;
- n->path = scope->file->tokenizer.fullpath;
- n->file_id = scope->file->id;
+ n->scope = scope;
+ n->path = scope->package->fullpath;
+ n->package_id = scope->package->id;
return n;
}
@@ -145,7 +145,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 (xg && yg) return x->package_id < y->package_id ? +1 : -1;
if (x->dep_count < y->dep_count) return -1;
if (x->dep_count > y->dep_count) return +1;
return 0;
@@ -222,31 +222,61 @@ Scope *create_scope(Scope *parent, gbAllocator allocator) {
ptr_set_init(&s->imported, heap_allocator());
ptr_set_init(&s->exported, heap_allocator());
+ s->delayed_imports.allocator = heap_allocator();
+ s->delayed_asserts.allocator = heap_allocator();
+
if (parent != nullptr && parent != universal_scope) {
DLIST_APPEND(parent->first_child, parent->last_child, s);
}
return s;
}
-Scope *create_scope_from_file(Checker *c, AstFile *f) {
- GB_ASSERT(f != nullptr);
+// Scope *create_scope_from_file(Checker *c, AstFile *f) {
+// GB_ASSERT(f != nullptr);
- Scope *s = create_scope(c->global_scope, c->allocator);
+// Scope *s = create_scope(c->global_scope, c->allocator);
+
+
+// s->file = f;
+// f->scope = s;
+// s->is_file = true;
+
+// if (f->tokenizer.fullpath == c->parser->init_fullpath) {
+// s->is_init = true;
+// } else {
+// s->is_init = f->package->kind == ImportedPackage_Init;
+// }
+
+// s->is_global = f->is_global_scope;
+// if (s->is_global) array_add(&c->global_scope->shared, s);
+
+
+// if (s->is_init || s->is_global) {
+// s->has_been_imported = true;
+// }
+
+// return s;
+// }
- array_init(&s->delayed_file_decls, heap_allocator());
+Scope *create_scope_from_package(Checker *c, AstPackage *p) {
+ GB_ASSERT(p != nullptr);
- s->file = f;
- f->scope = s;
- s->is_file = true;
+ Scope *s = create_scope(c->global_scope, c->allocator);
+
+ s->is_package = true;
+ s->package = p;
+ p->scope = s;
- if (f->tokenizer.fullpath == c->parser->init_fullpath) {
+ if (p->fullpath == c->parser->init_fullpath) {
s->is_init = true;
} else {
- s->is_init = f->file_kind == ImportedFile_Init;
+ s->is_init = p->kind == ImportedPackage_Init;
}
- s->is_global = f->is_global_scope;
- if (s->is_global) array_add(&c->global_scope->shared, s);
+ s->is_global = p->kind == ImportedPackage_Runtime;
+ if (s->is_global) {
+ array_add(&c->global_scope->shared, s);
+ }
if (s->is_init || s->is_global) {
@@ -274,7 +304,7 @@ void destroy_scope(Scope *scope) {
map_destroy(&scope->elements);
array_free(&scope->shared);
- array_free(&scope->delayed_file_decls);
+ array_free(&scope->delayed_imports);
array_free(&scope->delayed_asserts);
ptr_set_destroy(&scope->implicit);
ptr_set_destroy(&scope->imported);
@@ -330,7 +360,7 @@ Entity *current_scope_lookup_entity(Scope *s, String name) {
if (found) {
Entity *e = *found;
if (e->kind == Entity_Variable &&
- !e->scope->is_file &&
+ !e->scope->is_package &&
!e->scope->is_global) {
continue;
}
@@ -348,7 +378,7 @@ Entity *current_scope_lookup_entity(Scope *s, String name) {
void scope_lookup_parent_entity(Scope *scope, String name, Scope **scope_, Entity **entity_) {
bool gone_thru_proc = false;
- bool gone_thru_file = false;
+ bool gone_thru_package = false;
HashKey key = hash_string(name);
for (Scope *s = scope; s != nullptr; s = s->parent) {
Entity **found = map_get(&s->elements, key);
@@ -360,7 +390,7 @@ void scope_lookup_parent_entity(Scope *scope, String name, Scope **scope_, Entit
continue;
}
if (e->kind == Entity_Variable &&
- !e->scope->is_file &&
+ !e->scope->is_package &&
!e->scope->is_global) {
continue;
}
@@ -381,7 +411,7 @@ void scope_lookup_parent_entity(Scope *scope, String name, Scope **scope_, Entit
if (found) {
Entity *e = *found;
if (e->kind == Entity_Variable &&
- !e->scope->is_file &&
+ !e->scope->is_package &&
!e->scope->is_global) {
continue;
}
@@ -393,7 +423,7 @@ void scope_lookup_parent_entity(Scope *scope, String name, Scope **scope_, Entit
if ((e->kind == Entity_ImportName ||
e->kind == Entity_LibraryName)
- && gone_thru_file) {
+ && gone_thru_package) {
continue;
}
@@ -404,8 +434,8 @@ void scope_lookup_parent_entity(Scope *scope, String name, Scope **scope_, Entit
}
}
- if (s->is_file) {
- gone_thru_file = true;
+ if (s->is_package) {
+ gone_thru_package = true;
}
}
@@ -607,6 +637,7 @@ void init_checker_info(CheckerInfo *i) {
array_init(&i->type_info_types, a);
map_init(&i->type_info_map, a);
map_init(&i->files, a);
+ map_init(&i->packages, a);
array_init(&i->variable_init_order, a);
}
@@ -621,6 +652,7 @@ void destroy_checker_info(CheckerInfo *i) {
array_free(&i->type_info_types);
map_destroy(&i->type_info_map);
map_destroy(&i->files);
+ map_destroy(&i->packages);
array_free(&i->variable_init_order);
}
@@ -640,11 +672,7 @@ void init_checker(Checker *c, Parser *parser) {
// NOTE(bill): Is this big enough or too small?
isize item_size = gb_max3(gb_size_of(Entity), gb_size_of(Type), gb_size_of(Scope));
- isize total_token_count = 0;
- for_array(i, c->parser->files) {
- AstFile *f = c->parser->files[i];
- total_token_count += f->tokens.count;
- }
+ isize total_token_count = c->parser->total_token_count;
isize arena_size = 2 * item_size * total_token_count;
gb_arena_init_from_allocator(&c->tmp_arena, a, arena_size);
gb_arena_init_from_allocator(&c->arena, a, arena_size);
@@ -654,12 +682,15 @@ void init_checker(Checker *c, Parser *parser) {
// c->allocator = gb_arena_allocator(&c->arena);
c->tmp_allocator = gb_arena_allocator(&c->tmp_arena);
+ GB_ASSERT(universal_scope != nullptr);
c->global_scope = create_scope(universal_scope, c->allocator);
- map_init(&c->file_scopes, heap_allocator());
- ptr_set_init(&c->checked_files, heap_allocator());
+ GB_ASSERT(scope_lookup_entity(c->global_scope, str_lit("ODIN_OS")) != nullptr);
+
- array_init(&c->file_order, heap_allocator(), 0, c->parser->files.count);
+ map_init(&c->package_scopes, heap_allocator());
+
+ array_init(&c->package_order, heap_allocator(), 0, c->parser->packages.count);
// Init context
c->context.scope = c->global_scope;
@@ -678,9 +709,8 @@ void destroy_checker(Checker *c) {
gb_arena_free(&c->tmp_arena);
- map_destroy(&c->file_scopes);
- ptr_set_destroy(&c->checked_files);
- array_free(&c->file_order);
+ map_destroy(&c->package_scopes);
+ array_free(&c->package_order);
destroy_checker_type_path(c->context.type_path);
}
@@ -1110,9 +1140,9 @@ void check_procedure_later(Checker *c, ProcedureInfo info) {
array_add(&c->procs, info);
}
-void check_procedure_later(Checker *c, AstFile *file, Token token, DeclInfo *decl, Type *type, AstNode *body, u64 tags) {
+void check_procedure_later(Checker *c, AstPackage *package, Token token, DeclInfo *decl, Type *type, AstNode *body, u64 tags) {
ProcedureInfo info = {};
- info.file = file;
+ info.package = package;
info.token = token;
info.decl = decl;
info.type = type;
@@ -1137,14 +1167,14 @@ Type *const curr_procedure_type(Checker *c) {
return nullptr;
}
-void add_curr_ast_file(Checker *c, AstFile *file) {
- if (file != nullptr) {
+void add_curr_ast_package(Checker *c, AstPackage *package) {
+ if (package != nullptr) {
TokenPos zero_pos = {};
global_error_collector.prev = zero_pos;
- c->curr_ast_file = file;
- c->context.decl = file->decl_info;
- c->context.scope = file->scope;
- c->context.file_scope = file->scope;
+ c->curr_ast_package = package;
+ c->context.decl = package->decl_info;
+ c->context.scope = package->scope;
+ c->context.package_scope = package->scope;
}
}
@@ -1928,7 +1958,7 @@ void check_collect_value_decl(Checker *c, AstNode *decl) {
vd->been_handled = true;
if (vd->is_mutable) {
- if (!c->context.scope->is_file) {
+ if (!c->context.scope->is_package) {
// NOTE(bill): local scope -> handle later and in order
return;
}
@@ -2109,7 +2139,6 @@ void check_add_foreign_block_decl(Checker *c, AstNode *decl) {
check_decl_attributes(c, fb->attributes, foreign_block_decl_attribute, nullptr);
- c->context.collect_delayed_decls = true;
check_collect_entities(c, fb->decls);
c->context = prev_context;
}
@@ -2135,31 +2164,17 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes) {
case_end;
case_ast_node(id, ImportDecl, decl);
- if (!c->context.scope->is_file) {
+ if (!c->context.scope->is_package) {
error(decl, "import declarations are only allowed in the file scope");
// NOTE(bill): _Should_ be caught by the parser
// TODO(bill): Better error handling if it isn't
continue;
}
- if (c->context.collect_delayed_decls) {
- check_add_import_decl(c, id);
- }
- case_end;
-
- case_ast_node(ed, ExportDecl, decl);
- if (!c->context.scope->is_file) {
- error(decl, "export declarations are only allowed in the file scope");
- // NOTE(bill): _Should_ be caught by the parser
- // TODO(bill): Better error handling if it isn't
- continue;
- }
- if (c->context.collect_delayed_decls) {
- check_add_export_decl(c, ed);
- }
+ array_add(&c->context.scope->delayed_imports, decl);
case_end;
case_ast_node(fl, ForeignImportDecl, decl);
- if (!c->context.scope->is_file) {
+ if (!c->context.scope->is_package) {
error(decl, "%.*s declarations are only allowed in the file scope", LIT(fl->token.string));
// NOTE(bill): _Should_ be caught by the parser
// TODO(bill): Better error handling if it isn't
@@ -2172,8 +2187,20 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes) {
check_add_foreign_block_decl(c, decl);
case_end;
+
+ case_ast_node(ce, CallExpr, decl);
+ if (c->context.scope->is_package &&
+ ce->proc->kind == AstNode_BasicDirective &&
+ ce->proc->BasicDirective.name == "assert") {
+ array_add(&c->context.scope->delayed_asserts, decl);
+ } else {
+ goto error_case;
+ }
+ case_end;
+
+ error_case:
default:
- if (c->context.scope->is_file) {
+ if (c->context.scope->is_package) {
error(decl, "Only declarations are allowed at file scope");
}
break;
@@ -2182,7 +2209,7 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes) {
// NOTE(bill): 'when' stmts need to be handled after the other as the condition may refer to something
// declared after this stmt in source
- if (!c->context.scope->is_file || c->context.collect_delayed_decls) {
+ if (!c->context.scope->is_package) {
for_array(i, nodes) {
AstNode *node = nodes[i];
switch (node->kind) {
@@ -2214,8 +2241,8 @@ void check_all_global_entities(Checker *c) {
}
- AstFile *file = d->scope->file;
- add_curr_ast_file(c, file);
+ AstPackage *package = d->scope->package;
+ add_curr_ast_package(c, package);
if (e->token.string == "main") {
if (e->kind != Entity_Procedure) {
@@ -2229,6 +2256,7 @@ void check_all_global_entities(Checker *c) {
}
}
+
CheckerContext prev_context = c->context;
c->context.decl = d;
c->context.scope = d->scope;
@@ -2311,19 +2339,20 @@ String path_to_entity_name(String name, String fullpath) {
+#if 1
void add_import_dependency_node(Checker *c, AstNode *decl, Map<ImportGraphNode *> *M) {
- Scope *parent_file_scope = decl->file->scope;
+ Scope *parent_package_scope = decl->file->package->scope;
switch (decl->kind) {
case_ast_node(id, ImportDecl, decl);
String path = id->fullpath;
HashKey key = hash_string(path);
- Scope **found = map_get(&c->file_scopes, key);
+ Scope **found = map_get(&c->package_scopes, key);
if (found == nullptr) {
- for_array(scope_index, c->file_scopes.entries) {
- Scope *scope = c->file_scopes.entries[scope_index].value;
- gb_printf_err("%.*s\n", LIT(scope->file->tokenizer.fullpath));
+ for_array(scope_index, c->package_scopes.entries) {
+ Scope *scope = c->package_scopes.entries[scope_index].value;
+ gb_printf_err("%.*s\n", LIT(scope->package->fullpath));
}
Token token = ast_node_token(decl);
gb_printf_err("%.*s(%td:%td)\n", LIT(token.pos.file), token.pos.line, token.pos.column);
@@ -2332,7 +2361,7 @@ void add_import_dependency_node(Checker *c, AstNode *decl, Map<ImportGraphNode *
Scope *scope = *found;
GB_ASSERT(scope != nullptr);
- id->file = scope->file;
+ id->package = scope->package;
ImportGraphNode **found_node = nullptr;
ImportGraphNode *m = nullptr;
@@ -2342,7 +2371,7 @@ void add_import_dependency_node(Checker *c, AstNode *decl, Map<ImportGraphNode *
GB_ASSERT(found_node != nullptr);
m = *found_node;
- found_node = map_get(M, hash_pointer(parent_file_scope));
+ found_node = map_get(M, hash_pointer(parent_package_scope));
GB_ASSERT(found_node != nullptr);
n = *found_node;
@@ -2356,39 +2385,39 @@ void add_import_dependency_node(Checker *c, AstNode *decl, Map<ImportGraphNode *
case_end;
- case_ast_node(ed, ExportDecl, decl);
- String path = ed->fullpath;
- HashKey key = hash_string(path);
- Scope **found = map_get(&c->file_scopes, key);
- if (found == nullptr) {
- for_array(scope_index, c->file_scopes.entries) {
- Scope *scope = c->file_scopes.entries[scope_index].value;
- gb_printf_err("%.*s\n", LIT(scope->file->tokenizer.fullpath));
- }
- Token token = ast_node_token(decl);
- gb_printf_err("%.*s(%td:%td)\n", LIT(token.pos.file), token.pos.line, token.pos.column);
- GB_PANIC("Unable to find scope for file: %.*s", LIT(path));
- }
- Scope *scope = *found;
- GB_ASSERT(scope != nullptr);
- ed->file = scope->file;
-
- ImportGraphNode **found_node = nullptr;
- ImportGraphNode *m = nullptr;
- ImportGraphNode *n = nullptr;
-
- found_node = map_get(M, hash_pointer(scope));
- GB_ASSERT(found_node != nullptr);
- m = *found_node;
-
- found_node = map_get(M, hash_pointer(parent_file_scope));
- GB_ASSERT(found_node != nullptr);
- n = *found_node;
-
- import_graph_node_set_add(&n->succ, m);
- import_graph_node_set_add(&m->pred, n);
- ptr_set_add(&m->scope->exported, n->scope);
- case_end;
+ // case_ast_node(ed, ExportDecl, decl);
+ // String path = ed->fullpath;
+ // HashKey key = hash_string(path);
+ // Scope **found = map_get(&c->file_scopes, key);
+ // if (found == nullptr) {
+ // for_array(scope_index, c->file_scopes.entries) {
+ // Scope *scope = c->file_scopes.entries[scope_index].value;
+ // gb_printf_err("%.*s\n", LIT(scope->file->tokenizer.fullpath));
+ // }
+ // Token token = ast_node_token(decl);
+ // gb_printf_err("%.*s(%td:%td)\n", LIT(token.pos.file), token.pos.line, token.pos.column);
+ // GB_PANIC("Unable to find scope for file: %.*s", LIT(path));
+ // }
+ // Scope *scope = *found;
+ // GB_ASSERT(scope != nullptr);
+ // ed->file = scope->file;
+
+ // ImportGraphNode **found_node = nullptr;
+ // ImportGraphNode *m = nullptr;
+ // ImportGraphNode *n = nullptr;
+
+ // found_node = map_get(M, hash_pointer(scope));
+ // GB_ASSERT(found_node != nullptr);
+ // m = *found_node;
+
+ // found_node = map_get(M, hash_pointer(parent_package_scope));
+ // GB_ASSERT(found_node != nullptr);
+ // n = *found_node;
+
+ // import_graph_node_set_add(&n->succ, m);
+ // import_graph_node_set_add(&m->pred, n);
+ // ptr_set_add(&m->scope->exported, n->scope);
+ // case_end;
case_ast_node(ws, WhenStmt, decl);
if (ws->body != nullptr) {
@@ -2417,7 +2446,6 @@ void add_import_dependency_node(Checker *c, AstNode *decl, Map<ImportGraphNode *
}
}
-
Array<ImportGraphNode *> generate_import_dependency_graph(Checker *c) {
gbAllocator a = heap_allocator();
@@ -2425,19 +2453,22 @@ Array<ImportGraphNode *> generate_import_dependency_graph(Checker *c) {
map_init(&M, a);
defer (map_destroy(&M));
- for_array(i, c->parser->files) {
- Scope *scope = c->parser->files[i]->scope;
+ for_array(i, c->parser->packages) {
+ Scope *scope = c->parser->packages[i]->scope;
ImportGraphNode *n = import_graph_node_create(heap_allocator(), scope);
map_set(&M, hash_pointer(scope), n);
}
// Calculate edges for graph M
- for_array(i, c->parser->files) {
- AstFile *f = c->parser->files[i];
- for_array(j, f->decls) {
- AstNode *decl = f->decls[j];
- add_import_dependency_node(c, decl, &M);
+ for_array(i, c->parser->packages) {
+ AstPackage *p = c->parser->packages[i];
+ for_array(j, p->files.entries) {
+ AstFile *f = p->files.entries[j].value;
+ for_array(k, f->decls) {
+ AstNode *decl = f->decls[k];
+ add_import_dependency_node(c, decl, &M);
+ }
}
}
@@ -2472,66 +2503,68 @@ Array<ImportPathItem> find_import_path(Checker *c, Scope *start, Scope *end, Ptr
ptr_set_add(visited, start);
- String path = start->file->tokenizer.fullpath;
+ String path = start->package->fullpath;
HashKey key = hash_string(path);
- Scope **found = map_get(&c->file_scopes, key);
- if (found) {
- AstFile *f = (*found)->file;
- GB_ASSERT(f != nullptr);
-
- for_array(i, f->imports_and_exports) {
- Scope *s = nullptr;
- AstNode *decl = f->imports_and_exports[i];
- if (decl->kind == AstNode_ExportDecl) {
- s = decl->ExportDecl.file->scope;
- } else if (decl->kind == AstNode_ImportDecl) {
- if (!decl->ImportDecl.is_using) {
- // continue;
- }
- s = decl->ImportDecl.file->scope;
- } else {
- continue;
- }
- GB_ASSERT(s != nullptr);
-
- ImportPathItem item = {s, decl};
- if (s == end) {
- auto path = array_make<ImportPathItem>(heap_allocator());
- array_add(&path, item);
- return path;
- }
- auto next_path = find_import_path(c, s, end, visited);
- if (next_path.count > 0) {
- array_add(&next_path, item);
- return next_path;
- }
- }
- }
+ Scope **found = map_get(&c->package_scopes, key);
+ // if (found) {
+ // AstPackage *p = (*found)->package;
+ // GB_ASSERT(p != nullptr);
+
+ // for_array(i, f->imports_and_exports) {
+ // Scope *s = nullptr;
+ // AstNode *decl = f->imports_and_exports[i];
+ // /* if (decl->kind == AstNode_ExportDecl) {
+ // s = decl->ExportDecl.file->scope;
+ // } else */
+ // if (decl->kind == AstNode_ImportDecl) {
+ // if (!decl->ImportDecl.is_using) {
+ // // continue;
+ // }
+ // s = decl->ImportDecl.package->scope;
+ // } else {
+ // continue;
+ // }
+ // GB_ASSERT(s != nullptr);
+
+ // ImportPathItem item = {s, decl};
+ // if (s == end) {
+ // auto path = array_make<ImportPathItem>(heap_allocator());
+ // array_add(&path, item);
+ // return path;
+ // }
+ // auto next_path = find_import_path(c, s, end, visited);
+ // if (next_path.count > 0) {
+ // array_add(&next_path, item);
+ // return next_path;
+ // }
+ // }
+ // }
return empty_path;
}
-
+#endif
void check_add_import_decl(Checker *c, AstNodeImportDecl *id) {
if (id->been_handled) return;
id->been_handled = true;
Scope *parent_scope = c->context.scope;
- GB_ASSERT(parent_scope->is_file);
+ GB_ASSERT(parent_scope->is_package);
Token token = id->relpath;
HashKey key = hash_string(id->fullpath);
- Scope **found = map_get(&c->file_scopes, key);
+ Scope **found = map_get(&c->package_scopes, key);
if (found == nullptr) {
- for_array(scope_index, c->file_scopes.entries) {
- Scope *scope = c->file_scopes.entries[scope_index].value;
- gb_printf_err("%.*s\n", LIT(scope->file->tokenizer.fullpath));
+ for_array(scope_index, c->package_scopes.entries) {
+ Scope *scope = c->package_scopes.entries[scope_index].value;
+ gb_printf_err("%.*s\n", LIT(scope->package->fullpath));
}
gb_printf_err("%.*s(%td:%td)\n", LIT(token.pos.file), token.pos.line, token.pos.column);
- GB_PANIC("Unable to find scope for file: %.*s", LIT(id->fullpath));
+ GB_PANIC("Unable to find scope for package: %.*s", LIT(id->fullpath));
}
Scope *scope = *found;
+ GB_ASSERT(scope->is_package && scope->package != nullptr);
if (scope->is_global) {
- error(token, "Importing a #shared_global_scope is disallowed and unnecessary");
+ error(token, "Importing a runtime package is disallowed and unnecessary");
return;
}
@@ -2543,12 +2576,15 @@ void check_add_import_decl(Checker *c, AstNodeImportDecl *id) {
if (id->using_in_list.count == 0) {
- String import_name = path_to_entity_name(id->import_name.string, id->fullpath);
+ String import_name = id->import_name.string;
+ if (import_name.len == 0) {
+ import_name = scope->package->name;
+ }
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));
+ error(token, "Import 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);
@@ -2563,12 +2599,13 @@ void check_add_import_decl(Checker *c, AstNodeImportDecl *id) {
if (id->is_using) {
if (parent_scope->is_global) {
- error(id->import_name, "#shared_global_scope imports cannot use using");
+ error(id->import_name, "runtime package imports cannot use using");
return;
}
// 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);
@@ -2583,7 +2620,9 @@ void check_add_import_decl(Checker *c, AstNodeImportDecl *id) {
}
continue;
}
- if (e->scope == parent_scope) 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) {
@@ -2610,95 +2649,11 @@ void check_add_import_decl(Checker *c, AstNodeImportDecl *id) {
}
}
}
- ptr_set_add(&c->checked_files, scope->file);
- scope->has_been_imported = true;
-}
-
-void check_add_export_decl(Checker *c, AstNodeExportDecl *ed) {
- if (ed->been_handled) return;
- ed->been_handled = true;
-
- Scope *parent_scope = c->context.scope;
- GB_ASSERT(parent_scope->is_file);
-
- Token token = ed->relpath;
- HashKey key = hash_string(ed->fullpath);
- Scope **found = map_get(&c->file_scopes, key);
- if (found == nullptr) {
- for_array(scope_index, c->file_scopes.entries) {
- Scope *scope = c->file_scopes.entries[scope_index].value;
- gb_printf_err("%.*s\n", LIT(scope->file->tokenizer.fullpath));
- }
- gb_printf_err("%.*s(%td:%td)\n", LIT(token.pos.file), token.pos.line, token.pos.column);
- GB_PANIC("Unable to find scope for file: %.*s", LIT(ed->fullpath));
- }
- Scope *scope = *found;
-
- if (scope->is_global) {
- error(token, "Exporting a #shared_global_scope is disallowed and unnecessary");
- return;
- }
-
- if (parent_scope->is_global) {
- error(ed->token, "'export' cannot be used on #shared_global_scope");
- return;
- }
-
- if (ptr_set_exists(&parent_scope->imported, scope)) {
- // error(token, "Multiple import of the same file within this scope");
- } else {
- ptr_set_add(&parent_scope->imported, scope);
- }
-
- 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_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;
- String name = e->token.string;
- if (e->scope == parent_scope) continue;
- DeclInfo *d = e->decl_info;
- // NOTE(bill): The enum #export must be evaluated before use
- if (d != nullptr && d->init_expr != nullptr) {
- AstNode *expr = unparen_expr(d->init_expr);
- if (expr->kind == AstNode_EnumType && expr->EnumType.is_export) {
- check_entity_decl(c, e, d, nullptr);
- }
- }
-
- if (is_entity_kind_exported(e->kind)) {
- add_entity(c, parent_scope, e->identifier, e);
- }
- }
- }
-
- ptr_set_add(&c->checked_files, scope->file);
scope->has_been_imported = true;
}
+
void check_add_foreign_import_decl(Checker *c, AstNode *decl) {
ast_node(fl, ForeignImportDecl, decl);
@@ -2706,7 +2661,7 @@ void check_add_foreign_import_decl(Checker *c, AstNode *decl) {
fl->been_handled = true;
Scope *parent_scope = c->context.scope;
- GB_ASSERT(parent_scope->is_file);
+ GB_ASSERT(parent_scope->is_package);
String fullpath = fl->fullpath;
String library_name = path_to_entity_name(fl->library_name.string, fullpath);
@@ -2743,206 +2698,6 @@ void check_add_foreign_import_decl(Checker *c, AstNode *decl) {
}
-bool collect_checked_files_from_import_decl_list(Checker *c, Array<AstNode *> decls) {
- bool new_files = false;
- for_array(i, decls) {
- AstNode *decl = decls[i];
- switch (decl->kind) {
- case_ast_node(id, ImportDecl, decl);
- HashKey key = hash_string(id->fullpath);
- Scope **found = map_get(&c->file_scopes, key);
- if (found == nullptr) continue;
- Scope *s = *found;
- if (!ptr_set_exists(&c->checked_files, s->file)) {
- new_files = true;
- ptr_set_add(&c->checked_files, s->file);
- }
- case_end;
-
- case_ast_node(ed, ExportDecl, decl);
- HashKey key = hash_string(ed->fullpath);
- Scope **found = map_get(&c->file_scopes, key);
- if (found == nullptr) continue;
- Scope *s = *found;
- if (!ptr_set_exists(&c->checked_files, s->file)) {
- new_files = true;
- ptr_set_add(&c->checked_files, s->file);
- }
- case_end;
- }
- }
- return new_files;
-}
-
-
-bool collect_checked_files_from_when_stmt(Checker *c, AstNodeWhenStmt *ws) {
- Operand operand = {Addressing_Invalid};
- if (!ws->is_cond_determined) {
- check_expr(c, &operand, ws->cond);
- if (operand.mode != Addressing_Invalid && !is_type_boolean(operand.type)) {
- error(ws->cond, "Non-boolean condition in 'when' statement");
- }
- if (operand.mode != Addressing_Constant) {
- error(ws->cond, "Non-constant condition in 'when' statement");
- }
-
- ws->is_cond_determined = true;
- ws->determined_cond = operand.value.kind == ExactValue_Bool && operand.value.value_bool;
- }
-
- if (ws->body == nullptr || ws->body->kind != AstNode_BlockStmt) {
- error(ws->cond, "Invalid body for 'when' statement");
- } else {
- if (ws->determined_cond) {
- return collect_checked_files_from_import_decl_list(c, ws->body->BlockStmt.stmts);
- } else if (ws->else_stmt) {
- switch (ws->else_stmt->kind) {
- case AstNode_BlockStmt:
- return collect_checked_files_from_import_decl_list(c, ws->else_stmt->BlockStmt.stmts);
- case AstNode_WhenStmt:
- return collect_checked_files_from_when_stmt(c, &ws->else_stmt->WhenStmt);
- default:
- error(ws->else_stmt, "Invalid 'else' statement in 'when' statement");
- break;
- }
- }
- }
-
- return false;
-}
-
-void check_delayed_file_import_entity(Checker *c, AstNode *decl) {
- Scope *parent_scope = c->context.scope;
- GB_ASSERT(parent_scope->is_file);
-
- switch (decl->kind) {
- case_ast_node(ws, WhenStmt, decl);
- check_collect_entities_from_when_stmt(c, ws);
- case_end;
-
- case_ast_node(id, ImportDecl, decl);
- check_add_import_decl(c, id);
- case_end;
-
- case_ast_node(ed, ExportDecl, decl);
- check_add_export_decl(c, ed);
- case_end;
-
- case_ast_node(fl, ForeignImportDecl, decl);
- check_add_foreign_import_decl(c, decl);
- case_end;
- }
-}
-
-
-// NOTE(bill): Returns true if a new file is present
-bool collect_file_decls(Checker *c, Array<AstNode *> decls);
-bool collect_file_decls_from_when_stmt(Checker *c, AstNodeWhenStmt *ws);
-
-bool collect_file_decls_from_when_stmt(Checker *c, AstNodeWhenStmt *ws) {
- Operand operand = {Addressing_Invalid};
- if (!ws->is_cond_determined) {
- check_expr(c, &operand, ws->cond);
- if (operand.mode != Addressing_Invalid && !is_type_boolean(operand.type)) {
- error(ws->cond, "Non-boolean condition in 'when' statement");
- }
- if (operand.mode != Addressing_Constant) {
- error(ws->cond, "Non-constant condition in 'when' statement");
- }
-
- ws->is_cond_determined = true;
- ws->determined_cond = operand.value.kind == ExactValue_Bool && operand.value.value_bool;
- }
-
- if (ws->body == nullptr || ws->body->kind != AstNode_BlockStmt) {
- error(ws->cond, "Invalid body for 'when' statement");
- } else {
- if (ws->determined_cond) {
- return collect_file_decls(c, ws->body->BlockStmt.stmts);
- } else if (ws->else_stmt) {
- switch (ws->else_stmt->kind) {
- case AstNode_BlockStmt:
- return collect_file_decls(c, ws->else_stmt->BlockStmt.stmts);
- case AstNode_WhenStmt:
- return collect_file_decls_from_when_stmt(c, &ws->else_stmt->WhenStmt);
- default:
- error(ws->else_stmt, "Invalid 'else' statement in 'when' statement");
- break;
- }
- }
- }
-
- return false;
-}
-
-bool collect_file_decls(Checker *c, Array<AstNode *> decls) {
- Scope *parent_scope = c->context.scope;
- GB_ASSERT(parent_scope->is_file);
-
- if (collect_checked_files_from_import_decl_list(c, decls)) {
- return true;
- }
-
- for_array(i, decls) {
- AstNode *decl = decls[i];
- switch (decl->kind) {
- case_ast_node(vd, ValueDecl, decl);
- check_collect_value_decl(c, decl);
- case_end;
-
- case_ast_node(id, ImportDecl, decl);
- check_add_import_decl(c, id);
- case_end;
-
- case_ast_node(ed, ExportDecl, decl);
- check_add_export_decl(c, ed);
- case_end;
-
- case_ast_node(fl, ForeignImportDecl, decl);
- check_add_foreign_import_decl(c, decl);
- case_end;
-
- case_ast_node(fb, ForeignBlockDecl, decl);
- check_add_foreign_block_decl(c, decl);
- case_end;
-
- case_ast_node(ws, WhenStmt, decl);
- if (!ws->is_cond_determined) {
- if (collect_checked_files_from_when_stmt(c, ws)) {
- return true;
- }
-
- CheckerContext prev_context = c->context;
- defer (c->context = prev_context);
- c->context.collect_delayed_decls = true;
-
- if (collect_file_decls_from_when_stmt(c, ws)) {
- return true;
- }
- } else {
-
- CheckerContext prev_context = c->context;
- defer (c->context = prev_context);
- c->context.collect_delayed_decls = true;
-
- if (collect_file_decls_from_when_stmt(c, ws)) {
- return true;
- }
- }
- case_end;
-
- case_ast_node(ce, CallExpr, decl);
- if (ce->proc->kind == AstNode_BasicDirective &&
- ce->proc->BasicDirective.name == "assert") {
- Operand o = {};
- check_expr(c, &o, decl);
- }
- case_end;
- }
- }
-
- return false;
-}
void check_import_entities(Checker *c) {
Array<ImportGraphNode *> dep_graph = generate_import_dependency_graph(c);
@@ -2960,6 +2715,7 @@ void check_import_entities(Checker *c) {
ptr_set_init(&emitted, heap_allocator());
defer (ptr_set_destroy(&emitted));
+
while (pq.queue.count > 0) {
ImportGraphNode *n = priority_queue_pop(&pq);
@@ -2976,7 +2732,8 @@ void check_import_entities(Checker *c) {
// TODO(bill): This needs better TokenPos finding
auto const fn = [](ImportPathItem item) -> String {
Scope *s = item.scope;
- return remove_directory_from_path(s->file->tokenizer.fullpath);
+ // return remove_directory_from_path(s->package->fullpath);
+ return s->package->name;
};
if (path.count == 1) {
@@ -3014,63 +2771,36 @@ void check_import_entities(Checker *c) {
}
ptr_set_add(&emitted, s);
- array_add(&c->file_order, n);
+ array_add(&c->package_order, n);
}
- for_array(file_index, c->parser->files) {
- AstFile *f = c->parser->files[file_index];
- Scope *s = f->scope;
- if (s->is_init || s->is_global) {
- ptr_set_add(&c->checked_files, f);
- }
- }
-
- // for_array(file_index, c->file_order) {
- // ImportGraphNode *node = c->file_order[file_index];
- // AstFile *f = node->scope->file;
- // gb_printf_err("--- %.*s -> %td\n", LIT(f->fullpath), node->succ.entries.count);
- // }
-
- for (;;) {
- bool new_files = false;
- for_array(file_index, c->file_order) {
- ImportGraphNode *node = c->file_order[file_index];
- AstFile *f = node->scope->file;
+ for_array(i, c->package_order) {
+ ImportGraphNode *node = c->package_order[i];
+ GB_ASSERT(node->scope->is_package);
+ AstPackage *p = node->scope->package;
- if (!ptr_set_exists(&c->checked_files, f)) {
- continue;
- }
-
- CheckerContext prev_context = c->context;
- defer (c->context = prev_context);
- add_curr_ast_file(c, f);
+ CheckerContext prev_context = c->context;
+ defer (c->context = prev_context);
+ add_curr_ast_package(c, p);
- new_files |= collect_checked_files_from_import_decl_list(c, f->decls);
+ for_array(i, p->files.entries) {
+ AstFile *f = p->files.entries[i].value;
+ check_collect_entities(c, f->decls);
}
- if (new_files) break;
- }
-
- for (isize file_index = 0; file_index < c->file_order.count; file_index += 1) {
- ImportGraphNode *node = c->file_order[file_index];
- AstFile *f = node->scope->file;
- if (!ptr_set_exists(&c->checked_files, f)) {
- continue;
+ for_array(j, node->scope->delayed_imports) {
+ ast_node(id, ImportDecl, node->scope->delayed_imports[j]);
+ check_add_import_decl(c, id);
}
- CheckerContext prev_context = c->context;
- defer (c->context = prev_context);
- c->context.collect_delayed_decls = true;
- add_curr_ast_file(c, f);
-
- bool new_files = collect_file_decls(c, f->decls);
- if (new_files) {
- // TODO(bill): Only start from the lowest new file
- file_index = -1;
- continue;
+ for_array(j, node->scope->delayed_asserts) {
+ AstNode *expr = node->scope->delayed_asserts[j];
+ Operand o = {};
+ check_expr(c, &o, expr);
}
}
+
// gb_printf_err("End here!\n");
// gb_exit(1);
}
@@ -3230,13 +2960,13 @@ void check_parsed_files(Checker *c) {
add_type_info_type(c, t_invalid);
// Map full filepaths to Scopes
- for_array(i, c->parser->files) {
- AstFile *f = c->parser->files[i];
- Scope *scope = create_scope_from_file(c, f);
- f->decl_info = make_decl_info(c->allocator, f->scope, c->context.decl);
- HashKey key = hash_string(f->tokenizer.fullpath);
- map_set(&c->file_scopes, key, scope);
- map_set(&c->info.files, key, f);
+ for_array(i, c->parser->packages) {
+ AstPackage *p = c->parser->packages[i];
+ Scope *scope = create_scope_from_package(c, p);
+ p->decl_info = make_decl_info(c->allocator, p->scope, c->context.decl);
+ HashKey key = hash_string(p->fullpath);
+ map_set(&c->package_scopes, key, scope);
+ map_set(&c->info.packages, key, p);
if (scope->is_init) {
c->info.init_scope = scope;
@@ -3245,11 +2975,14 @@ void check_parsed_files(Checker *c) {
TIME_SECTION("collect entities");
// Collect Entities
- for_array(i, c->parser->files) {
- AstFile *f = c->parser->files[i];
+ for_array(i, c->parser->packages) {
+ AstPackage *p = c->parser->packages[i];
CheckerContext prev_context = c->context;
- add_curr_ast_file(c, f);
- check_collect_entities(c, f->decls);
+ add_curr_ast_package(c, p);
+ for_array(j, p->files.entries) {
+ AstFile *f = p->files.entries[j].value;
+ check_collect_entities(c, f->decls);
+ }
c->context = prev_context;
}
@@ -3279,7 +3012,7 @@ void check_parsed_files(Checker *c) {
GB_ASSERT_MSG(pt->is_poly_specialized, "%.*s", LIT(name));
}
- add_curr_ast_file(c, pi->file);
+ add_curr_ast_package(c, pi->package);
bool bounds_check = (pi->tags & ProcTag_bounds_check) != 0;
bool no_bounds_check = (pi->tags & ProcTag_no_bounds_check) != 0;
@@ -3353,12 +3086,14 @@ void check_parsed_files(Checker *c) {
Entity *e = current_scope_lookup_entity(s, str_lit("main"));
if (e == nullptr) {
Token token = {};
- if (s->file->tokens.count > 0) {
- token = s->file->tokens[0];
- } else {
- token.pos.file = s->file->tokenizer.fullpath;
- token.pos.line = 1;
- token.pos.column = 1;
+ token.pos.file = s->package->fullpath;
+ token.pos.line = 1;
+ token.pos.column = 1;
+ if (s->package->files.entries.count > 0) {
+ AstFile *f = s->package->files.entries[0].value;
+ if (f->tokens.count > 0) {
+ token = f->tokens[0];
+ }
}
error(token, "Undefined entry point procedure 'main'");
diff --git a/src/checker.hpp b/src/checker.hpp
index 6b931fa62..337cb3b04 100644
--- a/src/checker.hpp
+++ b/src/checker.hpp
@@ -194,7 +194,8 @@ struct DeclInfo {
// ProcedureInfo stores the information needed for checking a procedure
struct ProcedureInfo {
- AstFile * file;
+ // AstFile * file;
+ AstPackage * package;
Token token;
DeclInfo * decl;
Type * type; // Type_Procedure
@@ -204,6 +205,7 @@ struct ProcedureInfo {
};
+
struct Scope {
AstNode * node;
Scope * parent;
@@ -214,17 +216,18 @@ struct Scope {
PtrSet<Entity *> implicit;
Array<Scope *> shared;
- Array<AstNode *> delayed_file_decls;
Array<AstNode *> delayed_asserts;
+ Array<AstNode *> delayed_imports;
PtrSet<Scope *> imported;
PtrSet<Scope *> exported; // NOTE(bhall): Contains 'using import' too
bool is_proc;
bool is_global;
- bool is_file;
+ bool is_package;
bool is_init;
bool is_struct;
bool has_been_imported; // This is only applicable to file scopes
- AstFile * file;
+
+ AstPackage * package;
};
@@ -250,7 +253,7 @@ typedef PtrSet<ImportGraphNode *> ImportGraphNodeSet;
struct ImportGraphNode {
Scope * scope;
String path;
- isize file_id;
+ isize package_id;
ImportGraphNodeSet pred;
ImportGraphNodeSet succ;
isize index; // Index in array/queue
@@ -268,7 +271,7 @@ struct ForeignContext {
typedef Array<Entity *> CheckerTypePath;
struct CheckerContext {
- Scope * file_scope;
+ Scope * package_scope;
Scope * scope;
DeclInfo * decl;
u32 stmt_state_flags;
@@ -282,7 +285,6 @@ struct CheckerContext {
CheckerTypePath *type_path;
isize type_level; // TODO(bill): Actually handle correctly
- bool collect_delayed_decls;
bool allow_polymorphic_types;
bool no_polymorphic_errors;
bool in_polymorphic_specialization;
@@ -295,6 +297,7 @@ struct CheckerInfo {
Map<TypeAndValue> types; // Key: AstNode * | Expression -> Type (and value)
Map<ExprInfo> untyped; // Key: AstNode * | Expression -> ExprInfo
Map<AstFile *> files; // Key: String (full path)
+ Map<AstPackage *> packages; // Key: String (full path)
Map<Entity *> foreigns; // Key: String
Array<Entity *> definitions;
Array<Entity *> entities;
@@ -318,12 +321,12 @@ struct Checker {
CheckerInfo info;
gbMutex mutex;
- AstFile * curr_ast_file;
+ AstPackage * curr_ast_package;
Scope * global_scope;
// NOTE(bill): Procedures to check
Array<ProcedureInfo> procs;
- Map<Scope *> file_scopes; // Key: String (fullpath)
- Array<ImportGraphNode *> file_order;
+ Map<Scope *> package_scopes; // Key: String (fullpath)
+ Array<ImportGraphNode *> package_order;
gbAllocator allocator;
gbArena arena;
@@ -334,9 +337,6 @@ struct Checker {
Array<Type *> proc_stack;
bool done_preload;
-
- PtrSet<AstFile *> checked_files;
-
};
@@ -382,7 +382,7 @@ void add_entity_and_decl_info(Checker *c, AstNode *identifier, Entity *e, D
void add_type_info_type (Checker *c, Type *t);
void check_add_import_decl(Checker *c, AstNodeImportDecl *id);
-void check_add_export_decl(Checker *c, AstNodeExportDecl *ed);
+// void check_add_export_decl(Checker *c, AstNodeExportDecl *ed);
void check_add_foreign_import_decl(Checker *c, AstNode *decl);
diff --git a/src/common.cpp b/src/common.cpp
index 194f1e386..15412f108 100644
--- a/src/common.cpp
+++ b/src/common.cpp
@@ -748,6 +748,8 @@ enum ReadDirectoryError {
ReadDirectory_None,
ReadDirectory_InvalidPath,
+ ReadDirectory_NotExists,
+ ReadDirectory_Permission,
ReadDirectory_NotDir,
ReadDirectory_EOF,
ReadDirectory_Unknown,
@@ -760,6 +762,8 @@ enum ReadDirectoryError {
ReadDirectoryError read_directory(String path, Array<FileInfo> *fi) {
GB_ASSERT(fi != nullptr);
+ gbAllocator a = heap_allocator();
+
while (path.len > 0) {
Rune end = path[path.len-1];
if (end == '/') {
@@ -774,11 +778,25 @@ ReadDirectoryError read_directory(String path, Array<FileInfo> *fi) {
if (path.len == 0) {
return ReadDirectory_InvalidPath;
}
+ {
+ char *c_str = alloc_cstring(a, path);
+ defer (gb_free(a, c_str));
+
+ gbFile f = {};
+ gbFileError file_err = gb_file_open(&f, c_str);
+ defer (gb_file_close(&f));
+
+ switch (file_err) {
+ case gbFileError_Invalid: return ReadDirectory_InvalidPath;
+ case gbFileError_NotExists: return ReadDirectory_NotExists;
+ // case gbFileError_Permission: return ReadDirectory_Permission;
+ }
+ }
+
if (!path_is_directory(path)) {
return ReadDirectory_NotDir;
}
- gbAllocator a = heap_allocator();
char *new_path = gb_alloc_array(a, char, path.len+3);
defer (gb_free(a, new_path));
diff --git a/src/entity.cpp b/src/entity.cpp
index 182df8c05..d7f7dc2df 100644
--- a/src/entity.cpp
+++ b/src/entity.cpp
@@ -6,6 +6,7 @@ struct DeclInfo;
#define ENTITY_KINDS \
ENTITY_KIND(Invalid) \
+ ENTITY_KIND(Package) \
ENTITY_KIND(Constant) \
ENTITY_KIND(Variable) \
ENTITY_KIND(TypeName) \
@@ -86,6 +87,12 @@ struct Entity {
union {
struct {
+ String fullpath;
+ String name;
+ Scope *scope;
+ // Array<Entity *> imports; // Entity_Package
+ } Package;
+ struct {
ExactValue value;
} Constant;
struct {
@@ -189,6 +196,15 @@ Entity *alloc_entity(EntityKind kind, Scope *scope, Token token, Type *type) {
return entity;
}
+Entity *alloc_entity_package(Scope *scope, Type *type, String fullpath, String name) {
+ Token token = empty_token;
+ token.string = name;
+ Entity *entity = alloc_entity(Entity_Package, scope, token, type);
+ entity->Package.fullpath = fullpath;
+ entity->Package.name = name;
+ return entity;
+}
+
Entity *alloc_entity_variable(Scope *scope, Token token, Type *type, bool is_immutable, EntityState state = EntityState_Unresolved) {
Entity *entity = alloc_entity(Entity_Variable, scope, token, type);
entity->Variable.is_immutable = is_immutable;
diff --git a/src/main.cpp b/src/main.cpp
index 3d56d73b9..9b08fda1f 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -12,9 +12,9 @@
#include "checker.hpp"
#include "parser.cpp"
-#if 0
#include "docs.cpp"
#include "checker.cpp"
+#if 0
#include "ir.cpp"
#include "ir_opt.cpp"
#include "ir_print.cpp"
@@ -574,16 +574,22 @@ bool parse_build_flags(Array<String> args) {
}
void show_timings(Checker *c, Timings *t) {
- Parser *p = c->parser;
- isize lines = p->total_line_count;
- isize tokens = p->total_token_count;
- isize files = p->files.count;
+ Parser *p = c->parser;
+ isize lines = p->total_line_count;
+ isize tokens = p->total_token_count;
+ isize files = 0;
+ isize packages = p->packages.count;
+ for_array(i, p->packages) {
+ files += p->packages[i]->files.entries.count;
+ }
+
{
timings_print_all(t);
gb_printf("\n");
- gb_printf("Total Lines - %td\n", lines);
- gb_printf("Total Tokens - %td\n", tokens);
- gb_printf("Total Files - %td\n", files);
+ gb_printf("Total Lines - %td\n", lines);
+ gb_printf("Total Tokens - %td\n", tokens);
+ gb_printf("Total Files - %td\n", files);
+ gb_printf("Total Packages - %td\n", packages);
gb_printf("\n");
}
{
@@ -774,9 +780,8 @@ int main(int arg_count, char **arg_ptr) {
print_usage_line(0, "%s 32-bit is not yet supported", args[0]);
return 1;
}
-#if 0
+
init_universal_scope();
-#endif
// TODO(bill): prevent compiling without a linker
timings_start_section(&timings, str_lit("parse files"));
@@ -791,9 +796,8 @@ int main(int arg_count, char **arg_ptr) {
return 1;
}
-#if 0
if (build_context.generate_docs) {
- generate_documentation(&parser);
+ // generate_documentation(&parser);
return 0;
}
@@ -807,6 +811,7 @@ int main(int arg_count, char **arg_ptr) {
check_parsed_files(&checker);
+#if 0
if (build_context.no_output_files) {
if (build_context.show_timings) {
show_timings(&checker, &timings);
diff --git a/src/parser.cpp b/src/parser.cpp
index 4321ec3f3..7e3a79613 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -61,7 +61,7 @@ Token ast_node_token(AstNode *node) {
case AstNode_ValueDecl: return ast_node_token(node->ValueDecl.names[0]);
case AstNode_ImportDecl: return node->ImportDecl.token;
- case AstNode_ExportDecl: return node->ExportDecl.token;
+ // case AstNode_ExportDecl: return node->ExportDecl.token;
case AstNode_ForeignImportDecl: return node->ForeignImportDecl.token;
case AstNode_ForeignBlockDecl: return node->ForeignBlockDecl.token;
@@ -1002,15 +1002,15 @@ AstNode *ast_import_decl(AstFile *f, Token token, bool is_using, Token relpath,
return result;
}
-AstNode *ast_export_decl(AstFile *f, Token token, Token relpath,
- CommentGroup docs, CommentGroup comment) {
- AstNode *result = make_ast_node(f, AstNode_ExportDecl);
- result->ExportDecl.token = token;
- result->ExportDecl.relpath = relpath;
- result->ExportDecl.docs = docs;
- result->ExportDecl.comment = comment;
- return result;
-}
+// AstNode *ast_export_decl(AstFile *f, Token token, Token relpath,
+// CommentGroup docs, CommentGroup comment) {
+// AstNode *result = make_ast_node(f, AstNode_ExportDecl);
+// result->ExportDecl.token = token;
+// result->ExportDecl.relpath = relpath;
+// result->ExportDecl.docs = docs;
+// result->ExportDecl.comment = comment;
+// return result;
+// }
AstNode *ast_foreign_import_decl(AstFile *f, Token token, Token filepath, Token library_name,
CommentGroup docs, CommentGroup comment) {
@@ -1309,7 +1309,7 @@ bool is_semicolon_optional_for_node(AstFile *f, AstNode *s) {
return s->ProcLit.body != nullptr;
case AstNode_ImportDecl:
- case AstNode_ExportDecl:
+ // case AstNode_ExportDecl:
case AstNode_ForeignImportDecl:
return true;
@@ -3477,21 +3477,21 @@ AstNode *parse_import_decl(AstFile *f, ImportDeclKind kind) {
return s;
}
-AstNode *parse_export_decl(AstFile *f) {
- CommentGroup docs = f->lead_comment;
- Token token = expect_token(f, Token_export);
- Token file_path = expect_token_after(f, Token_String, "export");
- AstNode *s = nullptr;
- if (f->curr_proc != nullptr) {
- syntax_error(token, "You cannot use 'export' within a procedure. This must be done at the file scope");
- s = ast_bad_decl(f, token, file_path);
- } else {
- s = ast_export_decl(f, token, file_path, docs, f->line_comment);
- array_add(&f->imports_and_exports, s);
- }
- expect_semicolon(f, s);
- return s;
-}
+// AstNode *parse_export_decl(AstFile *f) {
+// CommentGroup docs = f->lead_comment;
+// Token token = expect_token(f, Token_export);
+// Token file_path = expect_token_after(f, Token_String, "export");
+// AstNode *s = nullptr;
+// if (f->curr_proc != nullptr) {
+// syntax_error(token, "You cannot use 'export' within a procedure. This must be done at the file scope");
+// s = ast_bad_decl(f, token, file_path);
+// } else {
+// s = ast_export_decl(f, token, file_path, docs, f->line_comment);
+// array_add(&f->imports_and_exports, s);
+// }
+// expect_semicolon(f, s);
+// return s;
+// }
AstNode *parse_foreign_decl(AstFile *f) {
CommentGroup docs = f->lead_comment;
@@ -3584,8 +3584,8 @@ AstNode *parse_stmt(AstFile *f) {
case Token_import:
return parse_import_decl(f, ImportDecl_Standard);
- case Token_export:
- return parse_export_decl(f);
+ // case Token_export:
+ // return parse_export_decl(f);
case Token_if: return parse_if_stmt(f);
@@ -3632,13 +3632,13 @@ AstNode *parse_stmt(AstFile *f) {
import_decl->ImportDecl.using_in_list = list;
}
return import_decl;
- } else if (f->curr_token.kind == Token_export) {
+ } /* 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;
- }
+ } */
AstNode *expr = parse_expr(f, true);
expect_semicolon(f, expr);
@@ -3883,9 +3883,9 @@ void destroy_ast_file(AstFile *f) {
bool init_parser(Parser *p) {
GB_ASSERT(p != nullptr);
- map_init(&p->packages, heap_allocator());
+ map_init(&p->imported_files, heap_allocator());
+ array_init(&p->packages, heap_allocator());
array_init(&p->imports, heap_allocator());
- array_init(&p->files, heap_allocator());
gb_mutex_init(&p->file_add_mutex);
gb_mutex_init(&p->file_decl_mutex);
return true;
@@ -3894,22 +3894,27 @@ bool init_parser(Parser *p) {
void destroy_parser(Parser *p) {
GB_ASSERT(p != nullptr);
// TODO(bill): Fix memory leak
- for_array(i, p->files) {
- destroy_ast_file(p->files[i]);
+ for_array(i, p->packages) {
+ AstPackage *package = p->packages[i];
+ for_array(j, package->files.entries) {
+ destroy_ast_file(package->files.entries[j].value);
+ }
+ map_destroy(&package->files);
}
#if 0
for_array(i, p->imports) {
// gb_free(heap_allocator(), p->imports[i].text);
}
#endif
- array_free(&p->files);
+ array_free(&p->packages);
array_free(&p->imports);
+ map_destroy(&p->imported_files);
gb_mutex_destroy(&p->file_add_mutex);
gb_mutex_destroy(&p->file_decl_mutex);
}
// NOTE(bill): Returns true if it's added
-bool try_add_import_path(Parser *p, String path, String rel_path, TokenPos pos) {
+bool try_add_import_path(Parser *p, String path, String rel_path, TokenPos pos, ImportedPackageKind kind = ImportedPackage_Normal) {
if (build_context.generate_docs) {
return false;
}
@@ -3917,22 +3922,20 @@ bool try_add_import_path(Parser *p, String path, String rel_path, TokenPos pos)
path = string_trim_whitespace(path);
rel_path = string_trim_whitespace(rel_path);
- for_array(i, p->imports) {
- String import = p->imports[i].path;
- if (import == path) {
- return false;
- }
+ HashKey key = hash_string(path);
+ if (map_get(&p->imported_files, key) != nullptr) {
+ return false;
}
+ map_set(&p->imported_files, key, true);
ImportedPackage item = {};
- item.kind = ImportedPackage_Normal;
+ item.kind = kind;
item.path = path;
item.rel_path = rel_path;
item.pos = pos;
item.index = p->imports.count;
array_add(&p->imports, item);
-
return true;
}
@@ -4054,34 +4057,12 @@ bool determine_path_from_string(Parser *p, AstNode *node, String base_dir, Strin
}
-void parse_setup_file_decls(Parser *p, AstFile *f, String base_dir, Array<AstNode *> decls);
-
-void parse_setup_file_when_stmt(Parser *p, AstFile *f, String base_dir, AstNodeWhenStmt *ws) {
- if (ws->body != nullptr) {
- auto stmts = ws->body->BlockStmt.stmts;
- parse_setup_file_decls(p, f, base_dir, stmts);
- }
-
- if (ws->else_stmt != nullptr) {
- switch (ws->else_stmt->kind) {
- case AstNode_BlockStmt: {
- auto stmts = ws->else_stmt->BlockStmt.stmts;
- parse_setup_file_decls(p, f, base_dir, stmts);
- } break;
- case AstNode_WhenStmt:
- parse_setup_file_when_stmt(p, f, base_dir, &ws->else_stmt->WhenStmt);
- break;
- }
- }
-}
-
void parse_setup_file_decls(Parser *p, AstFile *f, String base_dir, Array<AstNode *> decls) {
for_array(i, decls) {
AstNode *node = decls[i];
if (!is_ast_node_decl(node) &&
node->kind != AstNode_BadStmt &&
- node->kind != AstNode_EmptyStmt &&
- node->kind != AstNode_WhenStmt) {
+ node->kind != AstNode_EmptyStmt) {
// NOTE(bill): Sanity check
if (node->kind == AstNode_ExprStmt) {
@@ -4108,7 +4089,7 @@ void parse_setup_file_decls(Parser *p, AstFile *f, String base_dir, Array<AstNod
id->fullpath = import_path;
try_add_import_path(p, import_path, original_string, ast_node_token(node).pos);
- } else if (node->kind == AstNode_ExportDecl) {
+ } /* else if (node->kind == AstNode_ExportDecl) {
ast_node(ed, ExportDecl, node);
String original_string = ed->relpath.string;
@@ -4123,7 +4104,7 @@ void parse_setup_file_decls(Parser *p, AstFile *f, String base_dir, Array<AstNod
ed->fullpath = export_path;
try_add_import_path(p, export_path, original_string, ast_node_token(node).pos);
- } else if (node->kind == AstNode_ForeignImportDecl) {
+ } */else if (node->kind == AstNode_ForeignImportDecl) {
ast_node(fl, ForeignImportDecl, node);
String file_str = fl->filepath.string;
@@ -4140,9 +4121,6 @@ void parse_setup_file_decls(Parser *p, AstFile *f, String base_dir, Array<AstNod
fl->fullpath = foreign_path;
}
- } else if (node->kind == AstNode_WhenStmt) {
- ast_node(ws, WhenStmt, node);
- parse_setup_file_when_stmt(p, f, base_dir, ws);
}
}
}
@@ -4241,7 +4219,6 @@ skip:
// file->id = imported_package.index;
HashKey key = hash_string(fi->fullpath);
map_set(&package->files, key, file);
- array_add(&p->files, file);
if (package->name.len == 0) {
package->name = file->package_name;
@@ -4262,41 +4239,47 @@ ParseFileError parse_import(Parser *p, ImportedPackage imported_package) {
String import_rel_path = imported_package.rel_path;
TokenPos pos = imported_package.pos;
- HashKey path_key = hash_string(import_path);
- if (map_get(&p->packages, path_key) != nullptr) {
- return ParseFile_None;
- }
-
-
Array<FileInfo> list = {};
ReadDirectoryError rd_err = read_directory(import_path, &list);
defer (array_free(&list));
- if (rd_err != ReadDirectory_EOF && rd_err != ReadDirectory_None && pos.line != 0) {
- gb_printf_err("%.*s(%td:%td) ", LIT(pos.file), pos.line, pos.column);
+ if (list.count == 1) {
+ GB_ASSERT(import_path != list[0].fullpath);
}
- switch (rd_err) {
- case ReadDirectory_InvalidPath:
- gb_printf_err("Invalid path: %.*s\n", LIT(import_rel_path));
- gb_mutex_lock(&global_error_collector.mutex);
- global_error_collector.count++;
- gb_mutex_unlock(&global_error_collector.mutex);
- return ParseFile_InvalidFile;
- case ReadDirectory_NotDir:
- gb_printf_err("Expected a directory for a package, got a file: %.*s\n", LIT(import_rel_path));
- gb_mutex_lock(&global_error_collector.mutex);
- global_error_collector.count++;
- gb_mutex_unlock(&global_error_collector.mutex);
- return ParseFile_InvalidFile;
- case ReadDirectory_Unknown:
- gb_printf_err("Unknown error whilst reading directory");
+ if (rd_err != ReadDirectory_EOF && rd_err != ReadDirectory_None) {
+ if (pos.line != 0) {
+ gb_printf_err("%.*s(%td:%td) ", LIT(pos.file), pos.line, pos.column);
+ }
gb_mutex_lock(&global_error_collector.mutex);
+ defer (gb_mutex_unlock(&global_error_collector.mutex));
global_error_collector.count++;
- gb_mutex_unlock(&global_error_collector.mutex);
- return ParseFile_InvalidFile;
- case ReadDirectory_EOF:
- break;
+
+
+ switch (rd_err) {
+ case ReadDirectory_InvalidPath:
+ gb_printf_err("Invalid path: %.*s\n", LIT(import_rel_path));
+ return ParseFile_InvalidFile;
+
+ case ReadDirectory_NotExists:
+ gb_printf_err("Path does not exist: %.*s\n", LIT(import_rel_path));
+ return ParseFile_NotFound;
+
+ case ReadDirectory_NotDir:
+ gb_printf_err("Expected a directory for a package, got a file: %.*s\n", LIT(import_rel_path));
+ return ParseFile_InvalidFile;
+
+ case ReadDirectory_Unknown:
+ gb_printf_err("Unknown error whilst reading path %.*s\n", LIT(import_rel_path));
+ return ParseFile_InvalidFile;
+ case ReadDirectory_Permission:
+ gb_printf_err("Unknown error whilst reading path %.*s\n", LIT(import_rel_path));
+ return ParseFile_InvalidFile;
+
+ case ReadDirectory_EOF:
+ gb_printf_err("Unknown error whilst reading path %.*s\n", LIT(import_rel_path));
+ return ParseFile_InvalidFile;
+ }
}
AstPackage *package = gb_alloc_item(heap_allocator(), AstPackage);
@@ -4307,7 +4290,12 @@ ParseFileError parse_import(Parser *p, ImportedPackage imported_package) {
// TODO(bill): Fix concurrency
for_array(i, list) {
FileInfo *fi = &list[i];
- if (string_ends_with(fi->name, str_lit(".odin"))) {
+ String name = fi->name;
+ String const ext = str_lit(".odin");
+ if (string_ends_with(name, ext)) {
+ if (is_excluded_target_filename(name)) {
+ continue;
+ }
ParseFileError err = parse_imported_file(p, package, fi, pos);
if (err != ParseFile_None) {
return err;
@@ -4315,6 +4303,10 @@ ParseFileError parse_import(Parser *p, ImportedPackage imported_package) {
}
}
+ package->id = p->packages.count+1;
+ array_add(&p->packages, package);
+
+
return ParseFile_None;
}
@@ -4342,25 +4334,24 @@ ParseFileError parse_packages(Parser *p, String init_filename) {
TokenPos init_pos = {};
ImportedPackage init_imported_package = {ImportedPackage_Init, init_fullpath, init_fullpath, init_pos};
- isize shared_file_count = 0;
+ isize shared_package_count = 0;
if (!build_context.generate_docs) {
String s = get_fullpath_core(heap_allocator(), str_lit("runtime"));
- ImportedPackage runtime_package = {ImportedPackage_Runtime, s, s, init_pos};
- array_add(&p->imports, runtime_package);
- shared_file_count++;
+ try_add_import_path(p, s, s, init_pos, ImportedPackage_Runtime);
+ shared_package_count++;
}
array_add(&p->imports, init_imported_package);
p->init_fullpath = init_fullpath;
// IMPORTANT TODO(bill): Figure out why this doesn't work on *nix sometimes
-#if defined(GB_SYSTEM_WINDOWS)
+#if 0 && defined(GB_SYSTEM_WINDOWS)
isize thread_count = gb_max(build_context.thread_count, 1);
if (thread_count > 1) {
isize volatile curr_import_index = 0;
// NOTE(bill): Make sure that these are in parsed in this order
- for (isize i = 0; i < shared_file_count; i++) {
+ for (isize i = 0; i < shared_package_count; i++) {
ParseFileError err = parse_import(p, p->imports[i]);
if (err != ParseFile_None) {
return err;
diff --git a/src/parser.hpp b/src/parser.hpp
index d99562d2e..f1547847f 100644
--- a/src/parser.hpp
+++ b/src/parser.hpp
@@ -67,8 +67,8 @@ struct AstFile {
AstNode * curr_proc;
isize scope_level;
- Scope * scope; // NOTE(bill): Created in checker
- DeclInfo * decl_info; // NOTE(bill): Created in checker
+ // Scope * scope; // NOTE(bill): Created in checker
+ // DeclInfo * decl_info; // NOTE(bill): Created in checker
CommentGroup lead_comment; // Comment (block) before the decl
@@ -84,17 +84,21 @@ struct AstFile {
struct AstPackage {
+ isize id;
ImportedPackageKind kind;
String name;
String fullpath;
Map<AstFile *> files; // Key: String (names)
+
+ Scope * scope; // NOTE(bill): Created in checker
+ DeclInfo *decl_info; // NOTE(bill): Created in checker
};
struct Parser {
String init_fullpath;
- Map<AstPackage *> packages; // Key: String (fullpath)
- Array<AstFile *> files;
+ Map<bool> imported_files; // Key: String (fullpath)
+ Array<AstPackage *> packages;
Array<ImportedPackage> imports;
isize total_token_count;
isize total_line_count;
@@ -351,7 +355,7 @@ AST_NODE_KIND(_DeclBegin, "", struct {}) \
bool been_handled; \
}) \
AST_NODE_KIND(ImportDecl, "import declaration", struct { \
- AstFile *file; \
+ AstPackage *package; \
Token token; \
Token relpath; \
String fullpath; \
@@ -362,7 +366,7 @@ AST_NODE_KIND(_DeclBegin, "", struct {}) \
bool is_using; \
bool been_handled; \
}) \
- AST_NODE_KIND(ExportDecl, "export declaration", struct { \
+ /* AST_NODE_KIND(ExportDecl, "export declaration", struct { \
AstFile *file; \
Token token; \
Token relpath; \
@@ -371,7 +375,7 @@ AST_NODE_KIND(_DeclBegin, "", struct {}) \
CommentGroup docs; \
CommentGroup comment; \
bool been_handled; \
- }) \
+ }) */ \
AST_NODE_KIND(ForeignImportDecl, "foreign import declaration", struct { \
Token token; \
Token filepath; \
diff --git a/src/string.cpp b/src/string.cpp
index 16ba3c951..b63de5c76 100644
--- a/src/string.cpp
+++ b/src/string.cpp
@@ -94,6 +94,13 @@ String substring(String const &s, isize lo, isize hi) {
}
+char *alloc_cstring(gbAllocator a, String s) {
+ char *c_str = gb_alloc_array(a, char, s.len+1);
+ gb_memcopy(c_str, s.text, s.len);
+ c_str[s.len] = '\0';
+ return c_str;
+}
+
gb_inline bool str_eq_ignore_case(String const &a, String const &b) {
diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp
index ca8a2ba9f..c89b1ca6d 100644
--- a/src/tokenizer.cpp
+++ b/src/tokenizer.cpp
@@ -448,12 +448,9 @@ void advance_to_next_rune(Tokenizer *t) {
TokenizerInitError init_tokenizer(Tokenizer *t, String fullpath) {
TokenizerInitError err = TokenizerInit_None;
- char *c_str = gb_alloc_array(heap_allocator(), char, fullpath.len+1);
+ char *c_str = alloc_cstring(heap_allocator(), fullpath);
defer (gb_free(heap_allocator(), c_str));
- gb_memcopy(c_str, fullpath.text, fullpath.len);
- c_str[fullpath.len] = '\0';
-
// TODO(bill): Memory map rather than copy contents
gbFileContents fc = gb_file_read_contents(heap_allocator(), true, c_str);
gb_zero_item(t);