diff options
| author | gingerBill <bill@gingerbill.org> | 2018-05-28 15:57:53 +0100 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2018-05-28 15:57:53 +0100 |
| commit | 642aa0bc4b47752d4ea52f97dec3d478470b597e (patch) | |
| tree | 12a086696c6dc2948ee169bacb4bb7fa50c4af99 /src/checker.cpp | |
| parent | 45b3067068a95f3440c4caab63525e3fd6722d00 (diff) | |
Refactor: use CheckerContext rather than Checker in type checking part
Diffstat (limited to 'src/checker.cpp')
| -rw-r--r-- | src/checker.cpp | 310 |
1 files changed, 164 insertions, 146 deletions
diff --git a/src/checker.cpp b/src/checker.cpp index d6b564027..7791420e4 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1,7 +1,7 @@ #include "entity.cpp" #include "types.cpp" -void check_expr(Checker *c, Operand *operand, AstNode *expression); +void check_expr(CheckerContext *c, Operand *operand, AstNode *expression); bool is_operand_value(Operand o) { @@ -229,7 +229,7 @@ Scope *create_scope(Scope *parent, gbAllocator allocator, isize init_elements_ca return s; } -Scope *create_scope_from_file(Checker *c, AstFile *f) { +Scope *create_scope_from_file(CheckerContext *c, AstFile *f) { GB_ASSERT(f != nullptr); GB_ASSERT(f->pkg != nullptr); GB_ASSERT(f->pkg->scope != nullptr); @@ -246,7 +246,7 @@ Scope *create_scope_from_file(Checker *c, AstFile *f) { return s; } -Scope *create_scope_from_package(Checker *c, AstPackage *p) { +Scope *create_scope_from_package(CheckerContext *c, AstPackage *p) { GB_ASSERT(p != nullptr); isize decl_count = 0; @@ -254,14 +254,13 @@ Scope *create_scope_from_package(Checker *c, AstPackage *p) { decl_count += p->files[i]->decls.count; } isize init_elements_capacity = 2*decl_count; - Scope *s = create_scope(universal_scope, c->allocator, init_elements_capacity); s->is_package = true; s->package = p; p->scope = s; - if (p->fullpath == c->parser->init_fullpath) { + if (p->fullpath == c->checker->parser->init_fullpath) { s->is_init = true; } else { s->is_init = p->kind == Package_Init; @@ -306,7 +305,7 @@ void destroy_scope(Scope *scope) { } -void add_scope(Checker *c, AstNode *node, Scope *scope) { +void add_scope(CheckerContext *c, AstNode *node, Scope *scope) { GB_ASSERT(node != nullptr); GB_ASSERT(scope != nullptr); scope->node = node; @@ -314,12 +313,12 @@ void add_scope(Checker *c, AstNode *node, Scope *scope) { } -void check_open_scope(Checker *c, AstNode *node) { +void check_open_scope(CheckerContext *c, AstNode *node) { node = unparen_expr(node); GB_ASSERT(node->kind == AstNode_Invalid || is_ast_node_stmt(node) || is_ast_node_type(node)); - Scope *scope = create_scope(c->context.scope, c->allocator); + Scope *scope = create_scope(c->scope, c->allocator); add_scope(c, node, scope); switch (node->kind) { case AstNode_ProcType: @@ -331,12 +330,12 @@ void check_open_scope(Checker *c, AstNode *node) { scope->is_struct = true; break; } - c->context.scope = scope; - c->context.stmt_state_flags |= StmtStateFlag_bounds_check; + c->scope = scope; + c->stmt_state_flags |= StmtStateFlag_bounds_check; } -void check_close_scope(Checker *c) { - c->context.scope = c->context.scope->parent; +void check_close_scope(CheckerContext *c) { + c->scope = c->scope->parent; } @@ -488,7 +487,7 @@ void add_dependency(DeclInfo *d, Entity *e) { } void add_type_info_dependency(DeclInfo *d, Type *type) { if (d == nullptr) { - GB_ASSERT(type == t_invalid); + // GB_ASSERT(type == t_invalid); return; } ptr_set_add(&d->type_info_deps, type); @@ -505,22 +504,22 @@ AstPackage *get_core_package(CheckerInfo *info, String name) { } -void add_package_dependency(Checker *c, char *package_name, char *name) { +void add_package_dependency(CheckerContext *c, char *package_name, char *name) { String n = make_string_c(name); - AstPackage *p = get_core_package(&c->info, make_string_c(package_name)); + AstPackage *p = get_core_package(&c->checker->info, make_string_c(package_name)); Entity *e = scope_lookup_entity(p->scope, n); GB_ASSERT(e != nullptr); - ptr_set_add(&c->context.decl->deps, e); + ptr_set_add(&c->decl->deps, e); // add_type_info_type(c, e->type); } -void add_declaration_dependency(Checker *c, Entity *e) { +void add_declaration_dependency(CheckerContext *c, Entity *e) { if (e == nullptr) { return; } - if (c->context.decl != nullptr) { + if (c->decl != nullptr) { // DeclInfo *decl = decl_info_of_entity(&c->info, e); - add_dependency(c->context.decl, e); + add_dependency(c->decl, e); } } @@ -641,6 +640,20 @@ void destroy_checker_info(CheckerInfo *i) { array_free(&i->variable_init_order); } +CheckerContext make_checker_context(Checker *c) { + CheckerContext ctx = c->init_ctx; + ctx.checker = c; + ctx.allocator = c->allocator; + ctx.scope = universal_scope; + + ctx.type_path = new_checker_type_path(); + ctx.type_level = 0; + return ctx; +} + +void destroy_checker_context(CheckerContext *ctx) { + destroy_checker_type_path(ctx->type_path); +} void init_checker(Checker *c, Parser *parser) { if (global_error_collector.count > 0) { @@ -658,10 +671,8 @@ void init_checker(Checker *c, Parser *parser) { isize item_size = gb_max3(gb_size_of(Entity), gb_size_of(Type), gb_size_of(Scope)); 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); c->allocator = heap_allocator(); - // c->tmp_allocator = gb_arena_allocator(&c->tmp_arena); isize pkg_cap = 2*c->parser->packages.count; @@ -669,12 +680,7 @@ void init_checker(Checker *c, Parser *parser) { array_init(&c->package_order, heap_allocator(), 0, c->parser->packages.count); - // Init context - c->context.checker = c; - c->context.scope = universal_scope; - - c->context.type_path = new_checker_type_path(); - c->context.type_level = 0; + c->init_ctx = make_checker_context(c); } void destroy_checker(Checker *c) { @@ -688,7 +694,7 @@ void destroy_checker(Checker *c) { map_destroy(&c->package_scopes); array_free(&c->package_order); - destroy_checker_type_path(c->context.type_path); + destroy_checker_context(&c->init_ctx); } @@ -913,7 +919,7 @@ bool add_entity(Checker *c, Scope *scope, AstNode *identifier, Entity *entity) { return true; } -void add_entity_use(Checker *c, AstNode *identifier, Entity *entity) { +void add_entity_use(CheckerContext *c, AstNode *identifier, Entity *entity) { if (entity == nullptr) { return; } @@ -936,7 +942,7 @@ void add_entity_use(Checker *c, AstNode *identifier, Entity *entity) { } -void add_entity_and_decl_info(Checker *c, AstNode *identifier, Entity *e, DeclInfo *d) { +void add_entity_and_decl_info(CheckerContext *c, AstNode *identifier, Entity *e, DeclInfo *d) { GB_ASSERT(identifier->kind == AstNode_Ident); GB_ASSERT(e != nullptr && d != nullptr); GB_ASSERT(identifier->Ident.token.string == e->token.string); @@ -952,25 +958,25 @@ void add_entity_and_decl_info(Checker *c, AstNode *identifier, Entity *e, DeclIn default: { AstPackage *pkg = scope->file->pkg; GB_ASSERT(pkg->scope == scope->parent); - GB_ASSERT(c->context.pkg == pkg); + GB_ASSERT(c->pkg == pkg); scope = pkg->scope; break; } } } - add_entity(c, scope, identifier, e); + add_entity(c->checker, scope, identifier, e); } - add_entity_definition(&c->info, identifier, e); + add_entity_definition(&c->checker->info, identifier, e); GB_ASSERT(e->decl_info == nullptr); e->decl_info = d; - array_add(&c->info.entities, e); - e->order_in_src = c->info.entities.count; - e->pkg = c->context.pkg; + array_add(&c->checker->info.entities, e); + e->order_in_src = c->checker->info.entities.count; + e->pkg = c->pkg; } -void add_implicit_entity(Checker *c, AstNode *clause, Entity *e) { +void add_implicit_entity(CheckerContext *c, AstNode *clause, Entity *e) { GB_ASSERT(clause != nullptr); GB_ASSERT(e != nullptr); GB_ASSERT(clause->kind == AstNode_CaseClause); @@ -981,7 +987,7 @@ void add_implicit_entity(Checker *c, AstNode *clause, Entity *e) { -void add_type_info_type(Checker *c, Type *t) { +void add_type_info_type(CheckerContext *c, Type *t) { if (t == nullptr) { return; } @@ -996,17 +1002,17 @@ void add_type_info_type(Checker *c, Type *t) { return; } - auto found = map_get(&c->info.type_info_map, hash_type(t)); + auto found = map_get(&c->checker->info.type_info_map, hash_type(t)); if (found != nullptr) { // Types have already been added - add_type_info_dependency(c->context.decl, t); + add_type_info_dependency(c->decl, t); return; } bool prev = false; isize ti_index = -1; - for_array(i, c->info.type_info_map.entries) { - auto *e = &c->info.type_info_map.entries[i]; + for_array(i, c->checker->info.type_info_map.entries) { + auto *e = &c->checker->info.type_info_map.entries[i]; Type *prev_type = cast(Type *)e->key.ptr; if (are_types_identical(t, prev_type)) { // Duplicate entry @@ -1018,14 +1024,14 @@ void add_type_info_type(Checker *c, Type *t) { if (ti_index < 0) { // Unique entry // NOTE(bill): map entries grow linearly and in order - ti_index = c->info.type_info_types.count; - array_add(&c->info.type_info_types, t); + ti_index = c->checker->info.type_info_types.count; + array_add(&c->checker->info.type_info_types, t); } - map_set(&c->info.type_info_map, hash_type(t), ti_index); + map_set(&c->checker->info.type_info_map, hash_type(t), ti_index); if (prev) { // NOTE(bill): If a previous one exists already, no need to continue - add_type_info_dependency(c->context.decl, t); + add_type_info_dependency(c->decl, t); return; } @@ -1148,14 +1154,14 @@ void check_procedure_later(Checker *c, AstFile *file, Token token, DeclInfo *dec check_procedure_later(c, info); } -void add_curr_ast_file(Checker *c, AstFile *file) { +void add_curr_ast_file(CheckerContext *ctx, AstFile *file) { if (file != nullptr) { TokenPos zero_pos = {}; global_error_collector.prev = zero_pos; - c->context.file = file; - c->context.decl = file->pkg->decl_info; - c->context.scope = file->scope; - c->context.pkg = file->pkg; + ctx->file = file; + ctx->decl = file->pkg->decl_info; + ctx->scope = file->scope; + ctx->pkg = file->pkg; } } @@ -1530,22 +1536,22 @@ void destroy_checker_type_path(CheckerTypePath *tp) { } -void check_type_path_push(Checker *c, Entity *e) { - GB_ASSERT(c->context.type_path != nullptr); +void check_type_path_push(CheckerContext *c, Entity *e) { + GB_ASSERT(c->type_path != nullptr); GB_ASSERT(e != nullptr); - array_add(c->context.type_path, e); + array_add(c->type_path, e); } -Entity *check_type_path_pop(Checker *c) { - GB_ASSERT(c->context.type_path != nullptr); - return array_pop(c->context.type_path); +Entity *check_type_path_pop(CheckerContext *c) { + GB_ASSERT(c->type_path != nullptr); + return array_pop(c->type_path); } -void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type); +void check_entity_decl(CheckerContext *c, Entity *e, DeclInfo *d, Type *named_type); -Array<Entity *> proc_group_entities(Checker *c, Operand o) { +Array<Entity *> proc_group_entities(CheckerContext *c, Operand o) { Array<Entity *> procs = {}; if (o.mode == Addressing_ProcGroup) { GB_ASSERT(o.proc_group != nullptr); @@ -1681,7 +1687,7 @@ DECL_ATTRIBUTE_PROC(foreign_block_decl_attribute) { if (cc == ProcCC_Invalid) { error(elem, "Unknown procedure calling convention: '%.*s'\n", LIT(value.value_string)); } else { - c->context.foreign_context.default_cc = cc; + c->foreign_context.default_cc = cc; } } else { error(elem, "Expected a string value for '%.*s'", LIT(name)); @@ -1693,7 +1699,7 @@ DECL_ATTRIBUTE_PROC(foreign_block_decl_attribute) { if (!is_foreign_name_valid(link_prefix)) { error(elem, "Invalid link prefix: '%.*s'\n", LIT(link_prefix)); } else { - c->context.foreign_context.link_prefix = link_prefix; + c->foreign_context.link_prefix = link_prefix; } } else { error(elem, "Expected a string value for '%.*s'", LIT(name)); @@ -1742,7 +1748,7 @@ DECL_ATTRIBUTE_PROC(proc_decl_attribute) { } DECL_ATTRIBUTE_PROC(var_decl_attribute) { - if (c->context.curr_proc_decl != nullptr) { + if (c->curr_proc_decl != nullptr) { error(elem, "Only a variable at file scope can have a '%.*s'", LIT(name)); return true; } @@ -1770,7 +1776,7 @@ DECL_ATTRIBUTE_PROC(var_decl_attribute) { } else if (name == "thread_local") { if (ac->init_expr_list_count > 0) { error(elem, "A thread local variable declaration cannot have initialization values"); - } else if (c->context.foreign_context.curr_library || c->context.foreign_context.in_export) { + } else if (c->foreign_context.curr_library || c->foreign_context.in_export) { error(elem, "A foreign block variable cannot be thread local"); } else if (value.kind == ExactValue_Invalid) { ac->thread_local_model = str_lit("default"); @@ -1801,7 +1807,7 @@ DECL_ATTRIBUTE_PROC(var_decl_attribute) { -void check_decl_attributes(Checker *c, Array<AstNode *> attributes, DeclAttributeProc *proc, AttributeContext *ac) { +void check_decl_attributes(CheckerContext *c, Array<AstNode *> attributes, DeclAttributeProc *proc, AttributeContext *ac) { if (attributes.count == 0) return; String original_link_prefix = {}; @@ -1872,7 +1878,7 @@ void check_decl_attributes(Checker *c, Array<AstNode *> attributes, DeclAttribut } -bool check_arity_match(Checker *c, AstNodeValueDecl *vd, bool is_global) { +bool check_arity_match(CheckerContext *c, AstNodeValueDecl *vd, bool is_global) { isize lhs = vd->names.count; isize rhs = vd->values.count; @@ -1908,7 +1914,7 @@ bool check_arity_match(Checker *c, AstNodeValueDecl *vd, bool is_global) { return true; } -void check_collect_entities_from_when_stmt(Checker *c, AstNodeWhenStmt *ws) { +void check_collect_entities_from_when_stmt(CheckerContext *c, AstNodeWhenStmt *ws) { Operand operand = {Addressing_Invalid}; if (!ws->is_cond_determined) { check_expr(c, &operand, ws->cond); @@ -1944,14 +1950,14 @@ void check_collect_entities_from_when_stmt(Checker *c, AstNodeWhenStmt *ws) { } } -void check_collect_value_decl(Checker *c, AstNode *decl) { +void check_collect_value_decl(CheckerContext *c, AstNode *decl) { ast_node(vd, ValueDecl, decl); if (vd->been_handled) return; vd->been_handled = true; if (vd->is_mutable) { - if (!c->context.scope->is_file) { + if (!c->scope->is_file) { // NOTE(bill): local scope -> handle later and in order return; } @@ -1962,7 +1968,7 @@ void check_collect_value_decl(Checker *c, AstNode *decl) { Entity **entities = gb_alloc_array(c->allocator, Entity *, entity_cap); DeclInfo *di = nullptr; if (vd->values.count > 0) { - di = make_decl_info(heap_allocator(), c->context.scope, c->context.decl); + di = make_decl_info(heap_allocator(), c->scope, c->decl); di->entities = entities; di->type_expr = vd->type; di->init_expr = vd->values[0]; @@ -1979,7 +1985,7 @@ void check_collect_value_decl(Checker *c, AstNode *decl) { error(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind])); continue; } - Entity *e = alloc_entity_variable(c->context.scope, name->Ident.token, nullptr, false); + Entity *e = alloc_entity_variable(c->scope, name->Ident.token, nullptr, false); e->identifier = name; if (vd->is_using) { @@ -1987,15 +1993,15 @@ void check_collect_value_decl(Checker *c, AstNode *decl) { error(name, "'using' is not allowed at the file scope"); } - AstNode *fl = c->context.foreign_context.curr_library; + AstNode *fl = c->foreign_context.curr_library; if (fl != nullptr) { GB_ASSERT(fl->kind == AstNode_Ident); e->Variable.is_foreign = true; e->Variable.foreign_library_ident = fl; - e->Variable.link_prefix = c->context.foreign_context.link_prefix; + e->Variable.link_prefix = c->foreign_context.link_prefix; - } else if (c->context.foreign_context.in_export) { + } else if (c->foreign_context.in_export) { e->Variable.is_export = true; } @@ -2004,7 +2010,7 @@ void check_collect_value_decl(Checker *c, AstNode *decl) { DeclInfo *d = di; if (d == nullptr || i > 0) { AstNode *init_expr = value; - d = make_decl_info(heap_allocator(), e->scope, c->context.decl); + d = make_decl_info(heap_allocator(), e->scope, c->decl); d->type_expr = vd->type; d->init_expr = init_expr; } @@ -2034,8 +2040,8 @@ void check_collect_value_decl(Checker *c, AstNode *decl) { Token token = name->Ident.token; - AstNode *fl = c->context.foreign_context.curr_library; - DeclInfo *d = make_decl_info(c->allocator, c->context.scope, c->context.decl); + AstNode *fl = c->foreign_context.curr_library; + DeclInfo *d = make_decl_info(c->allocator, c->scope, c->decl); Entity *e = nullptr; d->attributes = vd->attributes; @@ -2049,7 +2055,7 @@ void check_collect_value_decl(Checker *c, AstNode *decl) { d->type_expr = init; d->init_expr = init; } else if (init->kind == AstNode_ProcLit) { - if (c->context.scope->is_struct) { + if (c->scope->is_struct) { error(name, "Procedure declarations are not allowed within a struct"); continue; } @@ -2064,16 +2070,16 @@ void check_collect_value_decl(Checker *c, AstNode *decl) { auto cc = pl->type->ProcType.calling_convention; if (cc == ProcCC_ForeignBlockDefault) { cc = ProcCC_CDecl; - if (c->context.foreign_context.default_cc > 0) { - cc = c->context.foreign_context.default_cc; + if (c->foreign_context.default_cc > 0) { + cc = c->foreign_context.default_cc; } } - e->Procedure.link_prefix = c->context.foreign_context.link_prefix; + e->Procedure.link_prefix = c->foreign_context.link_prefix; GB_ASSERT(cc != ProcCC_Invalid); pl->type->ProcType.calling_convention = cc; - } else if (c->context.foreign_context.in_export) { + } else if (c->foreign_context.in_export) { e->Procedure.is_export = true; } d->proc_lit = init; @@ -2093,7 +2099,7 @@ void check_collect_value_decl(Checker *c, AstNode *decl) { e->identifier = name; if (e->kind != Entity_Procedure) { - if (fl != nullptr || c->context.foreign_context.in_export) { + if (fl != nullptr || c->foreign_context.in_export) { AstNodeKind kind = init->kind; error(name, "Only procedures and variables are allowed to be in a foreign block, got %.*s", LIT(ast_node_strings[kind])); if (kind == AstNode_ProcType) { @@ -2110,7 +2116,7 @@ void check_collect_value_decl(Checker *c, AstNode *decl) { } } -void check_add_foreign_block_decl(Checker *c, AstNode *decl) { +void check_add_foreign_block_decl(CheckerContext *ctx, AstNode *decl) { ast_node(fb, ForeignBlockDecl, decl); if (fb->been_handled) return; @@ -2118,36 +2124,35 @@ void check_add_foreign_block_decl(Checker *c, AstNode *decl) { AstNode *foreign_library = fb->foreign_library; - CheckerContext prev_context = c->context; + CheckerContext c = *ctx; if (foreign_library->kind == AstNode_Ident) { - c->context.foreign_context.curr_library = foreign_library; + c.foreign_context.curr_library = foreign_library; } else if (foreign_library->kind == AstNode_Implicit && foreign_library->Implicit.kind == Token_export) { - c->context.foreign_context.in_export = true; + c.foreign_context.in_export = true; } else { error(foreign_library, "Foreign block name must be an identifier or 'export'"); - c->context.foreign_context.curr_library = nullptr; + c.foreign_context.curr_library = nullptr; } - check_decl_attributes(c, fb->attributes, foreign_block_decl_attribute, nullptr); + check_decl_attributes(&c, fb->attributes, foreign_block_decl_attribute, nullptr); - check_collect_entities(c, fb->decls); - c->context = prev_context; + check_collect_entities(&c, fb->decls); } // NOTE(bill): If file_scopes == nullptr, this will act like a local scope -void check_collect_entities(Checker *c, Array<AstNode *> nodes) { +void check_collect_entities(CheckerContext *c, Array<AstNode *> nodes) { for_array(decl_index, nodes) { AstNode *decl = nodes[decl_index]; - if (c->context.scope->is_file) { + if (c->scope->is_file) { } if (!is_ast_node_decl(decl) && !is_ast_node_when_stmt(decl)) { - if (c->context.scope->is_file && decl->kind == AstNode_ExprStmt) { + if (c->scope->is_file && decl->kind == AstNode_ExprStmt) { AstNode *expr = decl->ExprStmt.expr; if (expr->kind == AstNode_CallExpr && expr->CallExpr.proc->kind == AstNode_BasicDirective && expr->CallExpr.proc->BasicDirective.name == "assert") { - array_add(&c->context.scope->delayed_asserts, expr); + array_add(&c->scope->delayed_asserts, expr); continue; } } @@ -2167,17 +2172,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->scope->is_file) { 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; } - array_add(&c->context.scope->delayed_imports, decl); + array_add(&c->scope->delayed_imports, decl); case_end; case_ast_node(fl, ForeignImportDecl, decl); - if (!c->context.scope->is_file) { + if (!c->scope->is_file) { 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 @@ -2191,7 +2196,7 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes) { case_end; default: - if (c->context.scope->is_file) { + if (c->scope->is_file) { error(decl, "Only declarations are allowed at file scope"); } break; @@ -2200,7 +2205,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) { + if (!c->scope->is_file) { for_array(i, nodes) { AstNode *node = nodes[i]; switch (node->kind) { @@ -2215,8 +2220,8 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes) { void check_all_global_entities(Checker *c) { Scope *prev_file = nullptr; - bool processing_preload = true; + for_array(i, c->info.entities) { Entity *e = c->info.entities[i]; DeclInfo *d = e->decl_info; @@ -2226,10 +2231,14 @@ void check_all_global_entities(Checker *c) { } + CheckerContext ctx = c->init_ctx; + GB_ASSERT(d->scope->is_file); AstFile *file = d->scope->file; - add_curr_ast_file(c, file); + add_curr_ast_file(&ctx, file); Scope *package_scope = file->pkg->scope; + GB_ASSERT(ctx.pkg != nullptr); + GB_ASSERT(e->pkg != nullptr); if (e->token.string == "main") { if (e->kind != Entity_Procedure) { @@ -2243,11 +2252,9 @@ void check_all_global_entities(Checker *c) { } } - CheckerContext prev_context = c->context; - c->context.decl = d; - c->context.scope = d->scope; - check_entity_decl(c, e, d, nullptr); - c->context = prev_context; + ctx.decl = d; + ctx.scope = d->scope; + check_entity_decl(&ctx, e, d, nullptr); if (!package_scope->is_global) { @@ -2490,19 +2497,24 @@ Array<ImportPathItem> find_import_path(Checker *c, Scope *start, Scope *end, Ptr return empty_path; } #endif -void check_add_import_decl(Checker *c, AstNodeImportDecl *id) { +void check_add_import_decl(CheckerContext *ctx, AstNodeImportDecl *id) { if (id->been_handled) return; id->been_handled = true; - Scope *parent_scope = c->context.scope; + gb_mutex_lock(&ctx->checker->mutex); + defer (gb_mutex_unlock(&ctx->checker->mutex)); + + Scope *parent_scope = ctx->scope; GB_ASSERT(parent_scope->is_file); + auto *pkg_scopes = &ctx->checker->package_scopes; + Token token = id->relpath; HashKey key = hash_string(id->fullpath); - Scope **found = map_get(&c->package_scopes, key); + Scope **found = map_get(pkg_scopes, key); if (found == nullptr) { - for_array(scope_index, c->package_scopes.entries) { - Scope *scope = c->package_scopes.entries[scope_index].value; + for_array(scope_index, pkg_scopes->entries) { + Scope *scope = pkg_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); @@ -2542,9 +2554,9 @@ void check_add_import_decl(Checker *c, AstNodeImportDecl *id) { id->fullpath, id->import_name.string, scope); - add_entity(c, parent_scope, nullptr, e); + add_entity(ctx->checker, parent_scope, nullptr, e); if (id->is_using) { - add_entity_use(c, nullptr, e); + add_entity_use(ctx, nullptr, e); } } } @@ -2578,8 +2590,8 @@ void check_add_import_decl(Checker *c, AstNodeImportDecl *id) { bool implicit_is_found = ptr_set_exists(&scope->implicit, e); if (is_entity_exported(e) && !implicit_is_found) { - add_entity_use(c, node, e); - bool ok = add_entity(c, parent_scope, e->identifier, e); + add_entity_use(ctx, node, e); + bool ok = add_entity(ctx->checker, 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)); @@ -2594,8 +2606,7 @@ void check_add_import_decl(Checker *c, AstNodeImportDecl *id) { 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); + bool ok = add_entity(ctx->checker, parent_scope, e->identifier, e); if (ok) ptr_set_add(&parent_scope->implicit, e); } } @@ -2606,13 +2617,13 @@ void check_add_import_decl(Checker *c, AstNodeImportDecl *id) { } -void check_add_foreign_import_decl(Checker *c, AstNode *decl) { +void check_add_foreign_import_decl(CheckerContext *ctx, AstNode *decl) { ast_node(fl, ForeignImportDecl, decl); if (fl->been_handled) return; fl->been_handled = true; - Scope *parent_scope = c->context.scope; + Scope *parent_scope = ctx->scope; GB_ASSERT(parent_scope->is_file); String fullpath = fl->fullpath; @@ -2646,7 +2657,7 @@ void check_add_foreign_import_decl(Checker *c, AstNode *decl) { fl->library_name.string = library_name; Entity *e = alloc_entity_library_name(parent_scope, fl->library_name, t_invalid, fl->fullpath, library_name); - add_entity(c, parent_scope, nullptr, e); + add_entity(ctx->checker, parent_scope, nullptr, e); } @@ -2733,25 +2744,24 @@ void check_import_entities(Checker *c) { for_array(i, p->files) { AstFile *f = p->files[i]; - CheckerContext prev_context = c->context; - defer (c->context = prev_context); - add_curr_ast_file(c, f); + CheckerContext ctx = c->init_ctx; + + add_curr_ast_file(&ctx, f); for_array(j, f->scope->delayed_imports) { AstNode *decl = f->scope->delayed_imports[j]; ast_node(id, ImportDecl, decl); - check_add_import_decl(c, id); + check_add_import_decl(&ctx, id); } } for_array(i, p->files) { AstFile *f = p->files[i]; - CheckerContext prev_context = c->context; - defer (c->context = prev_context); - add_curr_ast_file(c, f); + CheckerContext ctx = c->init_ctx; + add_curr_ast_file(&ctx, f); for_array(j, f->scope->delayed_asserts) { AstNode *expr = f->scope->delayed_asserts[j]; Operand o = {}; - check_expr(c, &o, expr); + check_expr(&ctx, &o, expr); } } } @@ -2913,13 +2923,13 @@ void check_parsed_files(Checker *c) { TIME_SECTION("map full filepaths to scope"); - add_type_info_type(c, t_invalid); + add_type_info_type(&c->init_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, p); - p->decl_info = make_decl_info(c->allocator, scope, c->context.decl); + Scope *scope = create_scope_from_package(&c->init_ctx, p); + p->decl_info = make_decl_info(c->allocator, scope, c->init_ctx.decl); HashKey key = hash_string(p->fullpath); map_set(&c->package_scopes, key, scope); map_set(&c->info.packages, key, p); @@ -2937,17 +2947,20 @@ void check_parsed_files(Checker *c) { // Collect Entities for_array(i, c->parser->packages) { AstPackage *p = c->parser->packages[i]; - CheckerContext prev_context = c->context; + + CheckerContext ctx = make_checker_context(c); + defer (destroy_checker_context(&ctx)); + ctx.pkg = p; + for_array(j, p->files) { AstFile *f = p->files[j]; - create_scope_from_file(c, f); + create_scope_from_file(&ctx, f); HashKey key = hash_string(f->fullpath); map_set(&c->info.files, key, f); - add_curr_ast_file(c, f); - check_collect_entities(c, f->decls); + add_curr_ast_file(&ctx, f); + check_collect_entities(&ctx, f->decls); } - c->context = prev_context; } TIME_SECTION("import entities"); @@ -2959,6 +2972,9 @@ void check_parsed_files(Checker *c) { TIME_SECTION("init preload"); init_preload(c); // NOTE(bill): This could be setup previously through the use of 'type_info_of' + CheckerContext prev_context = c->init_ctx; + defer (c->init_ctx = prev_context); + TIME_SECTION("check procedure bodies"); // NOTE(bill): Nested procedures bodies will be added to this "queue" for_array(i, c->procs_to_check) { @@ -2966,8 +2982,10 @@ void check_parsed_files(Checker *c) { if (pi->type == nullptr) { continue; } - CheckerContext prev_context = c->context; - defer (c->context = prev_context); + + CheckerContext ctx = make_checker_context(c); + defer (destroy_checker_context(&ctx)); + add_curr_ast_file(&ctx, pi->file); TypeProc *pt = &pi->type->Proc; String name = pi->token.string; @@ -2975,22 +2993,22 @@ void check_parsed_files(Checker *c) { GB_ASSERT_MSG(pt->is_poly_specialized, "%.*s", LIT(name)); } - add_curr_ast_file(c, pi->file); bool bounds_check = (pi->tags & ProcTag_bounds_check) != 0; bool no_bounds_check = (pi->tags & ProcTag_no_bounds_check) != 0; if (bounds_check) { - c->context.stmt_state_flags |= StmtStateFlag_bounds_check; - c->context.stmt_state_flags &= ~StmtStateFlag_no_bounds_check; + ctx.stmt_state_flags |= StmtStateFlag_bounds_check; + ctx.stmt_state_flags &= ~StmtStateFlag_no_bounds_check; } else if (no_bounds_check) { - c->context.stmt_state_flags |= StmtStateFlag_no_bounds_check; - c->context.stmt_state_flags &= ~StmtStateFlag_bounds_check; + ctx.stmt_state_flags |= StmtStateFlag_no_bounds_check; + ctx.stmt_state_flags &= ~StmtStateFlag_bounds_check; } - check_proc_body(c, pi->token, pi->decl, pi->type, pi->body); + check_proc_body(&ctx, pi->token, pi->decl, pi->type, pi->body); } + for_array(i, c->info.files.entries) { AstFile *f = c->info.files.entries[i].value; check_scope_usage(c, f->scope); @@ -3030,7 +3048,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, t); + add_type_info_type(&c->init_ctx, t); } } @@ -3041,7 +3059,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, e->type); + add_type_info_type(&c->init_ctx, e->type); } } } |