|
@@ -242,7 +242,7 @@ Scope *create_scope(Scope *parent, isize init_elements_capacity=DEFAULT_SCOPE_CA
|
|
|
return s;
|
|
|
}
|
|
|
|
|
|
-Scope *create_scope_from_file(CheckerContext *c, AstFile *f) {
|
|
|
+Scope *create_scope_from_file(AstFile *f) {
|
|
|
GB_ASSERT(f != nullptr);
|
|
|
GB_ASSERT(f->pkg != nullptr);
|
|
|
GB_ASSERT(f->pkg->scope != nullptr);
|
|
@@ -870,7 +870,7 @@ void destroy_checker_info(CheckerInfo *i) {
|
|
|
}
|
|
|
|
|
|
CheckerContext make_checker_context(Checker *c) {
|
|
|
- CheckerContext ctx = c->init_ctx;
|
|
|
+ CheckerContext ctx = {};
|
|
|
ctx.checker = c;
|
|
|
ctx.info = &c->info;
|
|
|
ctx.scope = builtin_pkg->scope;
|
|
@@ -883,6 +883,40 @@ CheckerContext make_checker_context(Checker *c) {
|
|
|
return ctx;
|
|
|
}
|
|
|
|
|
|
+void add_curr_ast_file(CheckerContext *ctx, AstFile *file) {
|
|
|
+ if (file != nullptr) {
|
|
|
+ TokenPos zero_pos = {};
|
|
|
+ global_error_collector.prev = zero_pos;
|
|
|
+ ctx->file = file;
|
|
|
+ ctx->decl = file->pkg->decl_info;
|
|
|
+ ctx->scope = file->scope;
|
|
|
+ ctx->pkg = file->pkg;
|
|
|
+ }
|
|
|
+}
|
|
|
+void reset_checker_context(CheckerContext *ctx, AstFile *file) {
|
|
|
+ if (ctx == nullptr) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ auto checker = ctx->checker;
|
|
|
+ auto info = ctx->info;
|
|
|
+ auto type_path = ctx->type_path;
|
|
|
+ auto poly_path = ctx->poly_path;
|
|
|
+ array_clear(type_path);
|
|
|
+ array_clear(poly_path);
|
|
|
+
|
|
|
+ gb_zero_item(ctx);
|
|
|
+ ctx->checker = checker;
|
|
|
+ ctx->info = info;
|
|
|
+ ctx->type_path = type_path;
|
|
|
+ ctx->poly_path = poly_path;
|
|
|
+ ctx->scope = builtin_pkg->scope;
|
|
|
+ ctx->pkg = builtin_pkg;
|
|
|
+
|
|
|
+ add_curr_ast_file(ctx, file);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
void destroy_checker_context(CheckerContext *ctx) {
|
|
|
destroy_checker_type_path(ctx->type_path);
|
|
|
destroy_checker_poly_path(ctx->poly_path);
|
|
@@ -907,7 +941,7 @@ bool init_checker(Checker *c, Parser *parser) {
|
|
|
isize total_token_count = c->parser->total_token_count;
|
|
|
isize arena_size = 2 * item_size * total_token_count;
|
|
|
|
|
|
- c->init_ctx = make_checker_context(c);
|
|
|
+ c->builtin_ctx = make_checker_context(c);
|
|
|
return true;
|
|
|
}
|
|
|
|
|
@@ -917,7 +951,7 @@ void destroy_checker(Checker *c) {
|
|
|
array_free(&c->procs_to_check);
|
|
|
array_free(&c->procs_with_deferred_to_check);
|
|
|
|
|
|
- destroy_checker_context(&c->init_ctx);
|
|
|
+ destroy_checker_context(&c->builtin_ctx);
|
|
|
}
|
|
|
|
|
|
|
|
@@ -994,10 +1028,11 @@ Scope *scope_of_node(Ast *node) {
|
|
|
return node->scope;
|
|
|
}
|
|
|
ExprInfo *check_get_expr_info(CheckerInfo *i, Ast *expr) {
|
|
|
- return map_get(&i->untyped, hash_node(expr));
|
|
|
-}
|
|
|
-void check_set_expr_info(CheckerInfo *i, Ast *expr, ExprInfo info) {
|
|
|
- map_set(&i->untyped, hash_node(expr), info);
|
|
|
+ ExprInfo **found = map_get(&i->untyped, hash_node(expr));
|
|
|
+ if (found) {
|
|
|
+ return *found;
|
|
|
+ }
|
|
|
+ return nullptr;
|
|
|
}
|
|
|
void check_remove_expr_info(CheckerInfo *i, Ast *expr) {
|
|
|
map_remove(&i->untyped, hash_node(expr));
|
|
@@ -1143,7 +1178,7 @@ bool redeclaration_error(String name, Entity *prev, Entity *found) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
-bool add_entity_with_name(Checker *c, Scope *scope, Ast *identifier, Entity *entity, String name) {
|
|
|
+bool add_entity_with_name(CheckerContext *c, Scope *scope, Ast *identifier, Entity *entity, String name) {
|
|
|
if (scope == nullptr) {
|
|
|
return false;
|
|
|
}
|
|
@@ -1155,14 +1190,13 @@ bool add_entity_with_name(Checker *c, Scope *scope, Ast *identifier, Entity *ent
|
|
|
}
|
|
|
if (identifier != nullptr) {
|
|
|
if (entity->file == nullptr) {
|
|
|
- GB_ASSERT(c->curr_ctx != nullptr);
|
|
|
- entity->file = c->curr_ctx->file;
|
|
|
+ entity->file = c->file;
|
|
|
}
|
|
|
- add_entity_definition(&c->info, identifier, entity);
|
|
|
+ add_entity_definition(c->info, identifier, entity);
|
|
|
}
|
|
|
return true;
|
|
|
}
|
|
|
-bool add_entity(Checker *c, Scope *scope, Ast *identifier, Entity *entity) {
|
|
|
+bool add_entity(CheckerContext *c, Scope *scope, Ast *identifier, Entity *entity) {
|
|
|
return add_entity_with_name(c, scope, identifier, entity, entity->token.string);
|
|
|
}
|
|
|
|
|
@@ -1213,7 +1247,7 @@ void add_entity_and_decl_info(CheckerContext *c, Ast *identifier, Entity *e, Dec
|
|
|
scope = pkg->scope;
|
|
|
}
|
|
|
}
|
|
|
- add_entity(c->checker, scope, identifier, e);
|
|
|
+ add_entity(c, scope, identifier, e);
|
|
|
}
|
|
|
|
|
|
add_entity_definition(&c->checker->info, identifier, e);
|
|
@@ -1460,17 +1494,6 @@ void check_procedure_later(Checker *c, AstFile *file, Token token, DeclInfo *dec
|
|
|
check_procedure_later(c, info);
|
|
|
}
|
|
|
|
|
|
-void add_curr_ast_file(CheckerContext *ctx, AstFile *file) {
|
|
|
- if (file != nullptr) {
|
|
|
- TokenPos zero_pos = {};
|
|
|
- global_error_collector.prev = zero_pos;
|
|
|
- ctx->file = file;
|
|
|
- ctx->decl = file->pkg->decl_info;
|
|
|
- ctx->scope = file->scope;
|
|
|
- ctx->pkg = file->pkg;
|
|
|
- ctx->checker->curr_ctx = ctx;
|
|
|
- }
|
|
|
-}
|
|
|
|
|
|
void add_min_dep_type_info(Checker *c, Type *t) {
|
|
|
if (t == nullptr) {
|
|
@@ -1488,7 +1511,7 @@ void add_min_dep_type_info(Checker *c, Type *t) {
|
|
|
|
|
|
isize ti_index = type_info_index(&c->info, t, false);
|
|
|
if (ti_index < 0) {
|
|
|
- add_type_info_type(&c->init_ctx, t); // Missing the type information
|
|
|
+ add_type_info_type(&c->builtin_ctx, t); // Missing the type information
|
|
|
ti_index = type_info_index(&c->info, t, false);
|
|
|
}
|
|
|
GB_ASSERT(ti_index >= 0);
|
|
@@ -2282,8 +2305,7 @@ void init_core_map_type(Checker *c) {
|
|
|
if (t_map_hash == nullptr) {
|
|
|
Entity *e = find_core_entity(c, str_lit("Map_Hash"));
|
|
|
if (e->state == EntityState_Unresolved) {
|
|
|
- auto ctx = c->init_ctx;
|
|
|
- check_entity_decl(&ctx, e, nullptr, nullptr);
|
|
|
+ check_entity_decl(&c->builtin_ctx, e, nullptr, nullptr);
|
|
|
}
|
|
|
t_map_hash = e->type;
|
|
|
GB_ASSERT(t_map_hash != nullptr);
|
|
@@ -2292,8 +2314,7 @@ void init_core_map_type(Checker *c) {
|
|
|
if (t_map_header == nullptr) {
|
|
|
Entity *e = find_core_entity(c, str_lit("Map_Header"));
|
|
|
if (e->state == EntityState_Unresolved) {
|
|
|
- auto ctx = c->init_ctx;
|
|
|
- check_entity_decl(&ctx, e, nullptr, nullptr);
|
|
|
+ check_entity_decl(&c->builtin_ctx, e, nullptr, nullptr);
|
|
|
}
|
|
|
t_map_header = e->type;
|
|
|
GB_ASSERT(t_map_header != nullptr);
|
|
@@ -2887,7 +2908,7 @@ void check_builtin_attributes(CheckerContext *ctx, Entity *e, Array<Ast *> *attr
|
|
|
}
|
|
|
|
|
|
if (name == "builtin") {
|
|
|
- add_entity(ctx->checker, builtin_pkg->scope, nullptr, e);
|
|
|
+ add_entity(ctx, builtin_pkg->scope, nullptr, e);
|
|
|
GB_ASSERT(scope_lookup(builtin_pkg->scope, e->token.string) != nullptr);
|
|
|
if (value != nullptr) {
|
|
|
error(value, "'builtin' cannot have a field value");
|
|
@@ -3236,8 +3257,8 @@ void check_collect_entities(CheckerContext *c, Slice<Ast *> const &nodes) {
|
|
|
}
|
|
|
|
|
|
CheckerContext *create_checker_context(Checker *c) {
|
|
|
- CheckerContext *ctx = gb_alloc_item(heap_allocator(), CheckerContext);
|
|
|
- *ctx = c->init_ctx;
|
|
|
+ CheckerContext *ctx = gb_alloc_item(permanent_allocator(), CheckerContext);
|
|
|
+ *ctx = make_checker_context(c);
|
|
|
return ctx;
|
|
|
}
|
|
|
|
|
@@ -3611,7 +3632,7 @@ void check_add_import_decl(CheckerContext *ctx, Ast *decl) {
|
|
|
id->fullpath, id->import_name.string,
|
|
|
scope);
|
|
|
|
|
|
- add_entity(ctx->checker, parent_scope, nullptr, e);
|
|
|
+ add_entity(ctx, parent_scope, nullptr, e);
|
|
|
if (force_use || id->is_using) {
|
|
|
add_entity_use(ctx, nullptr, e);
|
|
|
}
|
|
@@ -3638,7 +3659,7 @@ void check_add_import_decl(CheckerContext *ctx, Ast *decl) {
|
|
|
// file scope otherwise the error would be the wrong way around
|
|
|
redeclaration_error(name, found, e);
|
|
|
} else {
|
|
|
- add_entity_with_name(ctx->checker, parent_scope, e->identifier, e, name);
|
|
|
+ add_entity_with_name(ctx, parent_scope, e->identifier, e, name);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -3700,7 +3721,7 @@ void check_add_foreign_import_decl(CheckerContext *ctx, Ast *decl) {
|
|
|
|
|
|
Entity *e = alloc_entity_library_name(parent_scope, fl->library_name, t_invalid,
|
|
|
fl->fullpaths, library_name);
|
|
|
- add_entity(ctx->checker, parent_scope, nullptr, e);
|
|
|
+ add_entity(ctx, parent_scope, nullptr, e);
|
|
|
|
|
|
|
|
|
AttributeContext ac = {};
|
|
@@ -3958,6 +3979,8 @@ void check_import_entities(Checker *c) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ CheckerContext ctx = make_checker_context(c);
|
|
|
+
|
|
|
for (isize loop_count = 0; ; loop_count++) {
|
|
|
bool new_files = false;
|
|
|
for_array(i, package_order) {
|
|
@@ -3970,8 +3993,7 @@ void check_import_entities(Checker *c) {
|
|
|
|
|
|
for_array(i, pkg->files) {
|
|
|
AstFile *f = pkg->files[i];
|
|
|
- CheckerContext ctx = c->init_ctx;
|
|
|
- add_curr_ast_file(&ctx, f);
|
|
|
+ reset_checker_context(&ctx, f);
|
|
|
new_files |= collect_checked_packages_from_decl_list(c, f->decls);
|
|
|
}
|
|
|
}
|
|
@@ -3994,9 +4016,8 @@ void check_import_entities(Checker *c) {
|
|
|
for_array(i, pkg->files) {
|
|
|
AstFile *f = pkg->files[i];
|
|
|
|
|
|
- CheckerContext ctx = c->init_ctx;
|
|
|
+ reset_checker_context(&ctx, f);
|
|
|
ctx.collect_delayed_decls = true;
|
|
|
- add_curr_ast_file(&ctx, f);
|
|
|
|
|
|
if (collect_file_decls(&ctx, f->decls)) {
|
|
|
new_packages = true;
|
|
@@ -4017,8 +4038,7 @@ void check_import_entities(Checker *c) {
|
|
|
|
|
|
for_array(i, pkg->files) {
|
|
|
AstFile *f = pkg->files[i];
|
|
|
- CheckerContext ctx = c->init_ctx;
|
|
|
- add_curr_ast_file(&ctx, f);
|
|
|
+ reset_checker_context(&ctx, f);
|
|
|
|
|
|
for_array(j, f->scope->delayed_imports) {
|
|
|
Ast *decl = f->scope->delayed_imports[j];
|
|
@@ -4027,8 +4047,7 @@ void check_import_entities(Checker *c) {
|
|
|
}
|
|
|
for_array(i, pkg->files) {
|
|
|
AstFile *f = pkg->files[i];
|
|
|
- CheckerContext ctx = c->init_ctx;
|
|
|
- add_curr_ast_file(&ctx, f);
|
|
|
+ reset_checker_context(&ctx, f);
|
|
|
|
|
|
for_array(j, f->scope->delayed_directives) {
|
|
|
Ast *expr = f->scope->delayed_directives[j];
|
|
@@ -4214,7 +4233,7 @@ void check_proc_info(Checker *c, ProcInfo pi) {
|
|
|
|
|
|
CheckerContext ctx = make_checker_context(c);
|
|
|
defer (destroy_checker_context(&ctx));
|
|
|
- add_curr_ast_file(&ctx, pi.file);
|
|
|
+ reset_checker_context(&ctx, pi.file);
|
|
|
ctx.decl = pi.decl;
|
|
|
|
|
|
TypeProc *pt = &pi.type->Proc;
|
|
@@ -4332,13 +4351,13 @@ void check_parsed_files(Checker *c) {
|
|
|
#define TIME_SECTION(str) do { if (build_context.show_more_timings) timings_start_section(&global_timings, str_lit(str)); } while (0)
|
|
|
|
|
|
TIME_SECTION("map full filepaths to scope");
|
|
|
- add_type_info_type(&c->init_ctx, t_invalid);
|
|
|
+ add_type_info_type(&c->builtin_ctx, t_invalid);
|
|
|
|
|
|
// Map full filepaths to Scopes
|
|
|
for_array(i, c->parser->packages) {
|
|
|
AstPackage *p = c->parser->packages[i];
|
|
|
- Scope *scope = create_scope_from_package(&c->init_ctx, p);
|
|
|
- p->decl_info = make_decl_info(scope, c->init_ctx.decl);
|
|
|
+ Scope *scope = create_scope_from_package(&c->builtin_ctx, p);
|
|
|
+ p->decl_info = make_decl_info(scope, c->builtin_ctx.decl);
|
|
|
string_map_set(&c->info.packages, p->fullpath, p);
|
|
|
|
|
|
if (scope->flags&ScopeFlag_Init) {
|
|
@@ -4353,21 +4372,20 @@ void check_parsed_files(Checker *c) {
|
|
|
|
|
|
TIME_SECTION("collect entities");
|
|
|
// Collect Entities
|
|
|
+ CheckerContext collect_entity_ctx = make_checker_context(c);
|
|
|
+ defer (destroy_checker_context(&collect_entity_ctx));
|
|
|
for_array(i, c->parser->packages) {
|
|
|
AstPackage *pkg = c->parser->packages[i];
|
|
|
|
|
|
- CheckerContext ctx = make_checker_context(c);
|
|
|
- defer (destroy_checker_context(&ctx));
|
|
|
- ctx.pkg = pkg;
|
|
|
- ctx.collect_delayed_decls = false;
|
|
|
+ CheckerContext *ctx = &collect_entity_ctx;
|
|
|
|
|
|
for_array(j, pkg->files) {
|
|
|
AstFile *f = pkg->files[j];
|
|
|
- create_scope_from_file(&ctx, f);
|
|
|
string_map_set(&c->info.files, f->fullpath, f);
|
|
|
|
|
|
- add_curr_ast_file(&ctx, f);
|
|
|
- check_collect_entities(&ctx, f->decls);
|
|
|
+ create_scope_from_file(f);
|
|
|
+ reset_checker_context(ctx, f);
|
|
|
+ check_collect_entities(ctx, f->decls);
|
|
|
}
|
|
|
|
|
|
pkg->used = true;
|
|
@@ -4382,9 +4400,9 @@ void check_parsed_files(Checker *c) {
|
|
|
TIME_SECTION("init preload");
|
|
|
init_preload(c);
|
|
|
|
|
|
- CheckerContext prev_context = c->init_ctx;
|
|
|
- defer (c->init_ctx = prev_context);
|
|
|
- c->init_ctx.decl = make_decl_info(nullptr, nullptr);
|
|
|
+ CheckerContext prev_context = c->builtin_ctx;
|
|
|
+ defer (c->builtin_ctx = prev_context);
|
|
|
+ c->builtin_ctx.decl = make_decl_info(nullptr, nullptr);
|
|
|
|
|
|
TIME_SECTION("check procedure bodies");
|
|
|
// NOTE(bill): Nested procedures bodies will be added to this "queue"
|
|
@@ -4418,7 +4436,7 @@ void check_parsed_files(Checker *c) {
|
|
|
auto *entry = &c->info.untyped.entries[i];
|
|
|
HashKey key = entry->key;
|
|
|
Ast *expr = cast(Ast *)cast(uintptr)key.key;
|
|
|
- ExprInfo *info = &entry->value;
|
|
|
+ ExprInfo *info = entry->value;
|
|
|
if (info != nullptr && expr != nullptr) {
|
|
|
if (is_type_typed(info->type)) {
|
|
|
compiler_error("%s (type %s) is typed!", expr_to_string(expr), type_to_string(info->type));
|
|
@@ -4444,7 +4462,7 @@ void check_parsed_files(Checker *c) {
|
|
|
Type *t = &basic_types[i];
|
|
|
if (t->Basic.size > 0 &&
|
|
|
(t->Basic.flags & BasicFlag_LLVM) == 0) {
|
|
|
- add_type_info_type(&c->init_ctx, t);
|
|
|
+ add_type_info_type(&c->builtin_ctx, t);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -4456,7 +4474,7 @@ void check_parsed_files(Checker *c) {
|
|
|
// i64 size = type_size_of(c->allocator, e->type);
|
|
|
i64 align = type_align_of(e->type);
|
|
|
if (align > 0 && ptr_set_exists(&c->info.minimum_dependency_set, e)) {
|
|
|
- add_type_info_type(&c->init_ctx, e->type);
|
|
|
+ add_type_info_type(&c->builtin_ctx, e->type);
|
|
|
}
|
|
|
|
|
|
} else if (e->kind == Entity_Procedure) {
|