From ced818ad5401270441106c58658e6ea5683d3faa Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 2 Jun 2018 11:58:35 +0100 Subject: [PATCH] Remove dead code from checker --- examples/demo/demo.odin | 8 ++ src/check_decl.cpp | 27 ++-- src/check_expr.cpp | 3 - src/check_type.cpp | 47 +++---- src/checker.cpp | 276 ++++++++++++---------------------------- src/checker.hpp | 74 +++++------ 6 files changed, 147 insertions(+), 288 deletions(-) diff --git a/examples/demo/demo.odin b/examples/demo/demo.odin index e9cca65e1..7aef164e4 100644 --- a/examples/demo/demo.odin +++ b/examples/demo/demo.odin @@ -735,6 +735,14 @@ deprecated_attribute :: proc() { // foo_v1(1); } +A :: struct {x, y, z: int}; +B :: struct {x, y, z: int}; +C :: struct { + using a: A, + b: B, +} + + main :: proc() { when true { general_stuff(); diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 2ffd0cfda..bdedc773e 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -544,9 +544,6 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { } pt->calling_convention = ProcCC_Contextless; if (e->pkg->kind == Package_Init) { - gb_mutex_lock(&ctx->info->mutex); - defer (gb_mutex_unlock(&ctx->info->mutex)); - if (ctx->info->entry_point != nullptr) { error(e->token, "Redeclaration of the entry pointer procedure 'main'"); } else { @@ -612,9 +609,6 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { init_entity_foreign_library(ctx, e); - gb_mutex_lock(&ctx->info->mutex); - defer (gb_mutex_unlock(&ctx->info->mutex)); - auto *fp = &ctx->info->foreigns; HashKey key = hash_string(name); Entity **found = map_get(fp, key); @@ -647,9 +641,6 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { name = e->Procedure.link_name; } if (e->Procedure.link_name.len > 0 || is_export) { - gb_mutex_lock(&ctx->info->mutex); - defer (gb_mutex_unlock(&ctx->info->mutex)); - auto *fp = &ctx->info->foreigns; HashKey key = hash_string(name); Entity **found = map_get(fp, key); @@ -726,8 +717,6 @@ void check_var_decl(CheckerContext *ctx, Entity *e, Entity **entities, isize ent if (e->Variable.link_name.len > 0) { name = e->Variable.link_name; } - gb_mutex_lock(&ctx->info->mutex); - defer (gb_mutex_unlock(&ctx->info->mutex)); auto *fp = &ctx->info->foreigns; HashKey key = hash_string(name); @@ -777,9 +766,8 @@ void check_proc_group_decl(CheckerContext *ctx, Entity *pg_entity, DeclInfo *d) // places the entity within itself pg_entity->type = t_invalid; - PtrSet entity_map = {}; - ptr_set_init(&entity_map, heap_allocator()); - defer (ptr_set_destroy(&entity_map)); + PtrSet entity_set = {}; + ptr_set_init(&entity_set, heap_allocator(), 2*pg->args.count); for_array(i, pg->args) { AstNode *arg = pg->args[i]; @@ -806,14 +794,17 @@ void check_proc_group_decl(CheckerContext *ctx, Entity *pg_entity, DeclInfo *d) continue; } - if (ptr_set_exists(&entity_map, e)) { + if (ptr_set_exists(&entity_set, e)) { error(arg, "Previous use of `%.*s` in procedure group", LIT(e->token.string)); continue; } - ptr_set_add(&entity_map, e); + ptr_set_add(&entity_set, e); array_add(&pge->entities, e); } + ptr_set_destroy(&entity_set); + + for_array(j, pge->entities) { Entity *p = pge->entities[j]; if (p->type == t_invalid) { @@ -1021,6 +1012,7 @@ void check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *decl, Type *ty if (token.kind == Token_Ident) { error(bs->close, "Missing return statement at the end of the procedure '%.*s'", LIT(token.string)); } else { + // NOTE(bill): Anonymous procedure (lambda) error(bs->close, "Missing return statement at the end of the procedure"); } } @@ -1029,9 +1021,6 @@ void check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *decl, Type *ty check_scope_usage(ctx->checker, ctx->scope); if (decl->parent != nullptr) { - gb_mutex_lock(&ctx->checker->mutex); - defer (gb_mutex_unlock(&ctx->checker->mutex)); - // NOTE(bill): Add the dependencies from the procedure literal (lambda) for_array(i, decl->deps.entries) { Entity *e = decl->deps.entries[i].ptr; diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 9c34faa49..1576989cc 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -267,9 +267,6 @@ bool find_or_generate_polymorphic_procedure(CheckerContext *c, Entity *base_enti } - gb_mutex_lock(&nctx.info->mutex); - defer (gb_mutex_unlock(&nctx.info->mutex)); - auto *found_gen_procs = map_get(&nctx.info->gen_procs, hash_pointer(base_entity->identifier)); if (found_gen_procs) { auto procs = *found_gen_procs; diff --git a/src/check_type.cpp b/src/check_type.cpp index 9e3a91a72..c75832446 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -1,5 +1,5 @@ -void populate_using_entity_map(CheckerContext *ctx, AstNode *node, Type *t, Map *entity_map) { +void populate_using_entity_scope(CheckerContext *ctx, AstNode *node, Type *t) { t = base_type(type_deref(t)); gbString str = nullptr; defer (gb_string_free(str)); @@ -11,11 +11,9 @@ void populate_using_entity_map(CheckerContext *ctx, AstNode *node, Type *t, Map< for_array(i, t->Struct.fields) { Entity *f = t->Struct.fields[i]; GB_ASSERT(f->kind == Entity_Variable); - String name = f->token.string; - HashKey key = hash_string(name); - Entity **found = map_get(entity_map, key); - if (found != nullptr && name != "_") { - Entity *e = *found; + String name = f->token.string;; + Entity *e = current_scope_lookup_entity(ctx->scope, name); + if (e != nullptr && name != "_") { // TODO(bill): Better type error if (str != nullptr) { error(e->token, "'%.*s' is already declared in '%s'", LIT(name), str); @@ -23,10 +21,9 @@ void populate_using_entity_map(CheckerContext *ctx, AstNode *node, Type *t, Map< error(e->token, "'%.*s' is already declared", LIT(name)); } } else { - map_set(entity_map, key, f); add_entity(ctx->checker, ctx->scope, nullptr, f); if (f->flags & EntityFlag_Using) { - populate_using_entity_map(ctx, node, f->type, entity_map); + populate_using_entity_scope(ctx, node, f->type); } } } @@ -38,11 +35,6 @@ void check_struct_fields(CheckerContext *ctx, AstNode *node, Array *fi isize init_field_capacity, Type *named_type, String context) { *fields = array_make(heap_allocator(), 0, init_field_capacity); - Map entity_map = {}; - map_init(&entity_map, ctx->allocator, 2*init_field_capacity); - defer (map_destroy(&entity_map)); - - GB_ASSERT(node->kind == AstNode_StructType); isize variable_count = 0; @@ -117,7 +109,7 @@ void check_struct_fields(CheckerContext *ctx, AstNode *node, Array *fi continue; } - populate_using_entity_map(ctx, node, type, &entity_map); + populate_using_entity_scope(ctx, node, type); } } } @@ -166,9 +158,6 @@ bool check_custom_align(CheckerContext *ctx, AstNode *node, i64 *align_) { Entity *find_polymorphic_struct_entity(CheckerContext *ctx, Type *original_type, isize param_count, Array ordered_operands) { - gb_mutex_lock(&ctx->checker->mutex); - defer (gb_mutex_unlock(&ctx->checker->mutex)); - auto *found_gen_types = map_get(&ctx->checker->info.gen_types, hash_pointer(original_type)); if (found_gen_types != nullptr) { for_array(i, *found_gen_types) { @@ -258,6 +247,8 @@ void check_struct_type(CheckerContext *ctx, Type *struct_type, AstNode *node, Ar } struct_type->Struct.names = make_names_field_for_struct(ctx, ctx->scope); + scope_reserve(ctx->scope, min_field_count); + if (st->is_raw_union) { struct_type->Struct.is_raw_union = true; context = str_lit("struct #raw_union"); @@ -513,10 +504,6 @@ void check_enum_type(CheckerContext *ctx, Type *enum_type, Type *named_type, Ast enum_type->Enum.base_type = base_type; enum_type->Enum.scope = ctx->scope; - Map entity_map = {}; // Key: String - map_init(&entity_map, ctx->allocator, 2*(et->fields.count)); - defer (map_destroy(&entity_map)); - auto fields = array_make(ctx->allocator, 0, et->fields.count); Type *constant_type = enum_type; @@ -528,6 +515,8 @@ void check_enum_type(CheckerContext *ctx, Type *enum_type, Type *named_type, Ast ExactValue min_value = exact_value_i64(0); ExactValue max_value = exact_value_i64(0); + scope_reserve(ctx->scope, et->fields.count); + for_array(i, et->fields) { AstNode *field = et->fields[i]; AstNode *ident = nullptr; @@ -600,13 +589,12 @@ void check_enum_type(CheckerContext *ctx, Type *enum_type, Type *named_type, Ast e->flags |= EntityFlag_Visited; e->state = EntityState_Resolved; - HashKey key = hash_string(name); - if (map_get(&entity_map, key) != nullptr) { + if (current_scope_lookup_entity(ctx->scope, name) != nullptr) { error(ident, "'%.*s' is already declared in this enumeration", LIT(name)); } else { - map_set(&entity_map, key, e); add_entity(ctx->checker, ctx->scope, nullptr, e); array_add(&fields, e); + // TODO(bill): Should I add a use for the enum value? add_entity_use(ctx, field, e); } } @@ -643,14 +631,12 @@ void check_bit_field_type(CheckerContext *ctx, Type *bit_field_type, AstNode *no ast_node(bft, BitFieldType, node); GB_ASSERT(is_type_bit_field(bit_field_type)); - Map entity_map = {}; // Key: String - map_init(&entity_map, ctx->allocator, 2*(bft->fields.count)); - defer (map_destroy(&entity_map)); - auto fields = array_make(ctx->allocator, 0, bft->fields.count); auto sizes = array_make (ctx->allocator, 0, bft->fields.count); auto offsets = array_make (ctx->allocator, 0, bft->fields.count); + scope_reserve(ctx->scope, bft->fields.count); + u32 curr_offset = 0; for_array(i, bft->fields) { AstNode *field = bft->fields[i]; @@ -687,13 +673,12 @@ void check_bit_field_type(CheckerContext *ctx, Type *bit_field_type, AstNode *no e->identifier = ident; e->flags |= EntityFlag_BitFieldValue; - HashKey key = hash_string(name); if (!is_blank_ident(name) && - map_get(&entity_map, key) != nullptr) { + current_scope_lookup_entity(ctx->scope, name) != nullptr) { error(ident, "'%.*s' is already declared in this bit field", LIT(name)); } else { - map_set(&entity_map, key, e); add_entity(ctx->checker, ctx->scope, nullptr, e); + // TODO(bill): Should this entity be "used"? add_entity_use(ctx, field, e); array_add(&fields, e); diff --git a/src/checker.cpp b/src/checker.cpp index e72d954ff..fec46d10f 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -34,7 +34,13 @@ void scope_reset(Scope *scope) { map_clear (&scope->elements); ptr_set_clear(&scope->implicit); ptr_set_clear(&scope->imported); - ptr_set_clear(&scope->exported); +} + +void scope_reserve(Scope *scope, isize capacity) { + isize cap = 2*capacity; + if (cap > scope->elements.hashes.capacity) { + map_rehash(&scope->elements, capacity); + } } i32 is_scope_an_ancestor(Scope *parent, Scope *child) { @@ -119,11 +125,10 @@ void import_graph_node_set_remove(ImportGraphNodeSet *s, ImportGraphNode *n) { ptr_set_remove(s, n); } -ImportGraphNode *import_graph_node_create(gbAllocator a, Scope *scope) { +ImportGraphNode *import_graph_node_create(gbAllocator a, AstPackage *pkg) { ImportGraphNode *n = gb_alloc_item(a, ImportGraphNode); - n->scope = scope; - n->path = scope->package->fullpath; - n->package_id = scope->package->id; + n->pkg = pkg; + n->scope = pkg->scope; return n; } @@ -144,7 +149,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->package_id < y->package_id ? +1 : -1; + if (xg && yg) return x->pkg->id < y->pkg->id ? +1 : -1; if (x->dep_count < y->dep_count) return -1; if (x->dep_count > y->dep_count) return +1; return 0; @@ -218,10 +223,9 @@ Scope *create_scope(Scope *parent, gbAllocator allocator, isize init_elements_ca map_init(&s->elements, heap_allocator(), init_elements_capacity); ptr_set_init(&s->implicit, heap_allocator(), 0); ptr_set_init(&s->imported, heap_allocator(), 0); - ptr_set_init(&s->exported, heap_allocator(), 0); s->delayed_imports.allocator = heap_allocator(); - s->delayed_asserts.allocator = heap_allocator(); + s->delayed_directives.allocator = heap_allocator(); if (parent != nullptr && parent != universal_scope) { DLIST_APPEND(parent->first_child, parent->last_child, s); @@ -237,7 +241,7 @@ Scope *create_scope_from_file(CheckerContext *c, AstFile *f) { Scope *s = create_scope(f->pkg->scope, c->allocator); array_reserve(&s->delayed_imports, f->imports.count); - array_reserve(&s->delayed_asserts, f->assert_decl_count); + array_reserve(&s->delayed_directives, f->assert_decl_count); s->is_file = true; s->file = f; @@ -296,10 +300,9 @@ void destroy_scope(Scope *scope) { map_destroy(&scope->elements); array_free(&scope->delayed_imports); - array_free(&scope->delayed_asserts); + array_free(&scope->delayed_directives); ptr_set_destroy(&scope->implicit); ptr_set_destroy(&scope->imported); - ptr_set_destroy(&scope->exported); // NOTE(bill): No need to free scope as it "should" be allocated in an arena (except for the global scope) } @@ -623,7 +626,6 @@ void init_checker_info(CheckerInfo *i) { map_init(&i->files, a); map_init(&i->packages, a); array_init(&i->variable_init_order, a); - gb_mutex_init(&i->mutex); } void destroy_checker_info(CheckerInfo *i) { @@ -639,7 +641,6 @@ void destroy_checker_info(CheckerInfo *i) { map_destroy(&i->files); map_destroy(&i->packages); array_free(&i->variable_init_order); - gb_mutex_destroy(&i->mutex); } CheckerContext make_checker_context(Checker *c) { @@ -666,7 +667,6 @@ void init_checker(Checker *c, Parser *parser) { c->parser = parser; init_checker_info(&c->info); - gb_mutex_init(&c->mutex); array_init(&c->procs_to_check, a); @@ -677,26 +677,16 @@ void init_checker(Checker *c, Parser *parser) { c->allocator = heap_allocator(); - isize pkg_cap = 2*c->parser->packages.count; - - map_init(&c->package_scopes, heap_allocator(), pkg_cap); - - array_init(&c->package_order, heap_allocator(), 0, c->parser->packages.count); - c->init_ctx = make_checker_context(c); } void destroy_checker(Checker *c) { destroy_checker_info(&c->info); - gb_mutex_destroy(&c->mutex); array_free(&c->procs_to_check); // gb_arena_free(&c->tmp_arena); - map_destroy(&c->package_scopes); - array_free(&c->package_order); - destroy_checker_context(&c->init_ctx); } @@ -709,9 +699,6 @@ Entity *entity_of_ident(AstNode *identifier) { } TypeAndValue type_and_value_of_expr(CheckerInfo *i, AstNode *expr) { - gb_mutex_lock(&i->mutex); - defer (gb_mutex_unlock(&i->mutex)); - TypeAndValue result = {}; TypeAndValue *found = map_get(&i->types, hash_node(expr)); if (found) result = *found; @@ -719,9 +706,6 @@ TypeAndValue type_and_value_of_expr(CheckerInfo *i, AstNode *expr) { } Type *type_of_expr(CheckerInfo *i, AstNode *expr) { - gb_mutex_lock(&i->mutex); - defer (gb_mutex_unlock(&i->mutex)); - TypeAndValue tav = type_and_value_of_expr(i, expr); if (tav.mode != Addressing_Invalid) { return tav.type; @@ -784,8 +768,6 @@ DeclInfo *decl_info_of_ident(AstNode *ident) { } AstFile *ast_file_of_filename(CheckerInfo *i, String filename) { - gb_mutex_lock(&i->mutex); - defer (gb_mutex_unlock(&i->mutex)); AstFile **found = map_get(&i->files, hash_string(filename)); if (found != nullptr) { return *found; @@ -796,18 +778,12 @@ Scope *scope_of_node(AstNode *node) { return node->scope; } ExprInfo *check_get_expr_info(CheckerInfo *i, AstNode *expr) { - gb_mutex_lock(&i->mutex); - defer (gb_mutex_unlock(&i->mutex)); return map_get(&i->untyped, hash_node(expr)); } void check_set_expr_info(CheckerInfo *i, AstNode *expr, ExprInfo info) { - gb_mutex_lock(&i->mutex); - defer (gb_mutex_unlock(&i->mutex)); map_set(&i->untyped, hash_node(expr), info); } void check_remove_expr_info(CheckerInfo *i, AstNode *expr) { - gb_mutex_lock(&i->mutex); - defer (gb_mutex_unlock(&i->mutex)); map_remove(&i->untyped, hash_node(expr)); } @@ -819,9 +795,6 @@ isize type_info_index(CheckerInfo *info, Type *type, bool error_on_failure) { type = t_bool; } - gb_mutex_lock(&info->mutex); - defer (gb_mutex_unlock(&info->mutex)); - isize entry_index = -1; HashKey key = hash_type(type); isize *found_entry_index = map_get(&info->type_info_map, key); @@ -860,8 +833,6 @@ void add_untyped(CheckerInfo *i, AstNode *expression, bool lhs, AddressingMode m if (mode == Addressing_Constant && type == t_invalid) { compiler_error("add_untyped - invalid type: %s", type_to_string(type)); } - gb_mutex_lock(&i->mutex); - defer (gb_mutex_unlock(&i->mutex)); map_set(&i->untyped, hash_node(expression), make_expr_info(mode, type, value, lhs)); } @@ -876,9 +847,6 @@ void add_type_and_value(CheckerInfo *i, AstNode *expression, AddressingMode mode compiler_error("add_type_and_value - invalid type: %s", type_to_string(type)); } - gb_mutex_lock(&i->mutex); - defer (gb_mutex_unlock(&i->mutex)); - TypeAndValue tv = {}; tv.type = type; tv.value = value; @@ -898,9 +866,6 @@ void add_entity_definition(CheckerInfo *i, AstNode *identifier, Entity *entity) } GB_ASSERT(entity != nullptr); - gb_mutex_lock(&i->mutex); - defer (gb_mutex_unlock(&i->mutex)); - identifier->Ident.entity = entity; entity->identifier = identifier; array_add(&i->definitions, entity); @@ -1030,9 +995,6 @@ void add_type_info_type(CheckerContext *c, Type *t) { return; } - gb_mutex_lock(&c->info->mutex); - defer (gb_mutex_unlock(&c->info->mutex)); - auto found = map_get(&c->info->type_info_map, hash_type(t)); if (found != nullptr) { // Types have already been added @@ -1171,9 +1133,7 @@ void add_type_info_type(CheckerContext *c, Type *t) { void check_procedure_later(Checker *c, ProcedureInfo info) { GB_ASSERT(info.decl != nullptr); - gb_mutex_lock(&c->mutex); array_add(&c->procs_to_check, info); - gb_mutex_unlock(&c->mutex); } void check_procedure_later(Checker *c, AstFile *file, Token token, DeclInfo *decl, Type *type, AstNode *body, u64 tags) { @@ -2176,16 +2136,12 @@ void check_add_foreign_block_decl(CheckerContext *ctx, AstNode *decl) { void check_collect_entities(CheckerContext *c, Array nodes) { for_array(decl_index, nodes) { AstNode *decl = nodes[decl_index]; - if (c->scope->is_file) { - } if (!is_ast_node_decl(decl) && !is_ast_node_when_stmt(decl)) { - 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->scope->delayed_asserts, expr); + expr->CallExpr.proc->kind == AstNode_BasicDirective) { + array_add(&c->scope->delayed_directives, expr); continue; } } @@ -2368,46 +2324,43 @@ String path_to_entity_name(String name, String fullpath) { #if 1 void add_import_dependency_node(Checker *c, AstNode *decl, Map *M) { - Scope *parent_package_scope = decl->file->pkg->scope; + AstPackage *parent_pkg = decl->file->pkg; switch (decl->kind) { case_ast_node(id, ImportDecl, decl); String path = id->fullpath; HashKey key = hash_string(path); - Scope **found = map_get(&c->package_scopes, key); + AstPackage **found = map_get(&c->info.packages, key); if (found == nullptr) { - 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)); + for_array(pkg_index, c->info.packages.entries) { + AstPackage *pkg = c->info.packages.entries[pkg_index].value; + gb_printf_err("%.*s\n", LIT(pkg->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)); + GB_PANIC("Unable to find package: %.*s", LIT(path)); } - Scope *scope = *found; - GB_ASSERT(scope != nullptr); + AstPackage *pkg = *found; + GB_ASSERT(pkg->scope != nullptr); - id->package = scope->package; + id->package = pkg; ImportGraphNode **found_node = nullptr; ImportGraphNode *m = nullptr; ImportGraphNode *n = nullptr; - found_node = map_get(M, hash_pointer(scope)); + found_node = map_get(M, hash_pointer(pkg)); GB_ASSERT(found_node != nullptr); m = *found_node; - found_node = map_get(M, hash_pointer(parent_package_scope)); + found_node = map_get(M, hash_pointer(parent_pkg)); GB_ASSERT(found_node != nullptr); n = *found_node; - // TODO(bill): How should the edges be attched for 'import'? + // TODO(bill): How should the edges be attached for 'import'? import_graph_node_set_add(&n->succ, m); import_graph_node_set_add(&m->pred, n); ptr_set_add(&m->scope->imported, n->scope); - if (id->is_using) { - ptr_set_add(&m->scope->exported, n->scope); - } case_end; case_ast_node(ws, WhenStmt, decl); @@ -2438,17 +2391,14 @@ void add_import_dependency_node(Checker *c, AstNode *decl, Map generate_import_dependency_graph(Checker *c) { - gbAllocator a = heap_allocator(); - - Map M = {}; // Key: Scope * - map_init(&M, a); + Map M = {}; // Key: AstPackage * + map_init(&M, heap_allocator(), 2*c->parser->packages.count); defer (map_destroy(&M)); 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); + AstPackage *pkg = c->parser->packages[i]; + ImportGraphNode *n = import_graph_node_create(heap_allocator(), pkg); + map_set(&M, hash_pointer(pkg), n); } // Calculate edges for graph M @@ -2464,28 +2414,25 @@ Array generate_import_dependency_graph(Checker *c) { } Array G = {}; - array_init(&G, a); + array_init(&G, heap_allocator(), 0, M.entries.count); for_array(i, M.entries) { - array_add(&G, M.entries[i].value); - } - - for_array(i, G) { - ImportGraphNode *n = G[i]; + auto n = M.entries[i].value; n->index = i; n->dep_count = n->succ.entries.count; GB_ASSERT(n->dep_count >= 0); + array_add(&G, n); } return G; } struct ImportPathItem { - Scope * scope; - AstNode *decl; + AstPackage *pkg; + AstNode * decl; }; -Array find_import_path(Checker *c, Scope *start, Scope *end, PtrSet *visited) { +Array find_import_path(Checker *c, AstPackage *start, AstPackage *end, PtrSet *visited) { Array empty_path = {}; if (ptr_set_exists(visited, start)) { @@ -2494,32 +2441,32 @@ Array find_import_path(Checker *c, Scope *start, Scope *end, Ptr ptr_set_add(visited, start); - String path = start->package->fullpath; + String path = start->fullpath; HashKey key = hash_string(path); - Scope **found = map_get(&c->package_scopes, key); + AstPackage **found = map_get(&c->info.packages, key); if (found) { - AstPackage *p = (*found)->package; - GB_ASSERT(p != nullptr); + AstPackage *pkg = *found; + GB_ASSERT(pkg != nullptr); - for_array(i, p->files) { - AstFile *f = p->files[i]; + for_array(i, pkg->files) { + AstFile *f = pkg->files[i]; for_array(j, f->imports) { - Scope *s = nullptr; + AstPackage *pkg = nullptr; AstNode *decl = f->imports[j]; if (decl->kind == AstNode_ImportDecl) { - s = decl->ImportDecl.package->scope; + pkg = decl->ImportDecl.package; } else { continue; } - GB_ASSERT(s != nullptr && s->is_package); + GB_ASSERT(pkg != nullptr && pkg->scope != nullptr); - ImportPathItem item = {s, decl}; - if (s == end) { + ImportPathItem item = {pkg, decl}; + if (pkg == end) { auto path = array_make(heap_allocator()); array_add(&path, item); return path; } - auto next_path = find_import_path(c, s, end, visited); + auto next_path = find_import_path(c, pkg, end, visited); if (next_path.count > 0) { array_add(&next_path, item); return next_path; @@ -2534,27 +2481,25 @@ void check_add_import_decl(CheckerContext *ctx, AstNodeImportDecl *id) { if (id->been_handled) return; id->been_handled = true; - 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; + auto *pkgs = &ctx->checker->info.packages; Token token = id->relpath; HashKey key = hash_string(id->fullpath); - Scope **found = map_get(pkg_scopes, key); + AstPackage **found = map_get(pkgs, key); if (found == nullptr) { - for_array(scope_index, pkg_scopes->entries) { - Scope *scope = pkg_scopes->entries[scope_index].value; - gb_printf_err("%.*s\n", LIT(scope->package->fullpath)); + for_array(pkg_index, pkgs->entries) { + AstPackage *pkg = pkgs->entries[pkg_index].value; + gb_printf_err("%.*s\n", LIT(pkg->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 package: %.*s", LIT(id->fullpath)); } - Scope *scope = *found; - GB_ASSERT(scope->is_package && scope->package != nullptr); + AstPackage *pkg = *found; + Scope *scope = pkg->scope; + GB_ASSERT(scope->is_package); // TODO(bill): Should this be allowed or not? // if (scope->is_global) { @@ -2707,29 +2652,30 @@ void check_import_entities(Checker *c) { // NOTE(bill): Priority queue auto pq = priority_queue_create(dep_graph, import_graph_node_cmp, import_graph_node_swap); - PtrSet emitted = {}; + PtrSet emitted = {}; ptr_set_init(&emitted, heap_allocator()); defer (ptr_set_destroy(&emitted)); + Array package_order = {}; + array_init(&package_order, heap_allocator(), 0, c->parser->packages.count); + defer (array_free(&package_order)); while (pq.queue.count > 0) { ImportGraphNode *n = priority_queue_pop(&pq); - Scope *s = n->scope; + AstPackage *pkg = n->pkg; if (n->dep_count > 0) { - PtrSet visited = {}; + PtrSet visited = {}; ptr_set_init(&visited, heap_allocator()); defer (ptr_set_destroy(&visited)); - auto path = find_import_path(c, s, s, &visited); + auto path = find_import_path(c, pkg, pkg, &visited); defer (array_free(&path)); // TODO(bill): This needs better TokenPos finding auto const fn = [](ImportPathItem item) -> String { - Scope *s = item.scope; - // return remove_directory_from_path(s->package->fullpath); - return s->package->name; + return item.pkg->name; }; if (path.count == 1) { @@ -2759,24 +2705,24 @@ void check_import_entities(Checker *c) { priority_queue_fix(&pq, p->index); } - if (s == nullptr) { + if (pkg == nullptr) { continue; } - if (ptr_set_exists(&emitted, s)) { + if (ptr_set_exists(&emitted, pkg)) { continue; } - ptr_set_add(&emitted, s); + ptr_set_add(&emitted, pkg); - array_add(&c->package_order, n); + array_add(&package_order, n); } - for_array(i, c->package_order) { - ImportGraphNode *node = c->package_order[i]; + for_array(i, package_order) { + ImportGraphNode *node = package_order[i]; GB_ASSERT(node->scope->is_package); - AstPackage *p = node->scope->package; + AstPackage *pkg = node->scope->package; - for_array(i, p->files) { - AstFile *f = p->files[i]; + for_array(i, pkg->files) { + AstFile *f = pkg->files[i]; CheckerContext ctx = c->init_ctx; add_curr_ast_file(&ctx, f); @@ -2787,21 +2733,17 @@ void check_import_entities(Checker *c) { } } - for_array(i, p->files) { - AstFile *f = p->files[i]; + for_array(i, pkg->files) { + AstFile *f = pkg->files[i]; 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]; + for_array(j, f->scope->delayed_directives) { + AstNode *expr = f->scope->delayed_directives[j]; Operand o = {}; check_expr(&ctx, &o, expr); } } } - - - // gb_printf_err("End here!\n"); - // gb_exit(1); } Array find_entity_path(Entity *start, Entity *end, Map *visited = nullptr) { @@ -2979,58 +2921,6 @@ GB_THREAD_PROC(check_proc_info_worker_proc) { return 0; } -void check_proc_bodies(Checker *c) { - // IMPORTANT TODO(bill): Figure out why this doesn't work on *nix sometimes -#if 0 && defined(GB_SYSTEM_WINDOWS) - isize thread_count = gb_max(build_context.thread_count, 1); - gb_printf_err("Threads: %td\n", thread_count); - // isize thread_count = 1; - if (thread_count > 1) { - isize volatile curr_proc_index = 0; - - auto worker_threads = array_make(heap_allocator(), thread_count); - defer (array_free(&worker_threads)); - - for_array(i, worker_threads) { - gbThread *t = &worker_threads[i]; - gb_thread_init(t); - } - defer (for_array(i, worker_threads) { - gb_thread_destroy(&worker_threads[i]); - }); - - - for (;;) { - bool are_any_alive = false; - for_array(i, worker_threads) { - gbThread *t = &worker_threads[i]; - if (gb_thread_is_running(t)) { - are_any_alive = true; - } else if (curr_proc_index < c->procs_to_check.count) { - t->user_index = curr_proc_index; - curr_proc_index++; - gb_thread_start(t, check_proc_info_worker_proc, c); - are_any_alive = true; - } - } - if (!are_any_alive && curr_proc_index >= c->procs_to_check.count) { - break; - } - } - - } else { - for_array(i, c->procs_to_check) { - ProcedureInfo pi = c->procs_to_check[i]; - check_proc_info(c, pi); - } - } -#else - for_array(i, c->procs_to_check) { - ProcedureInfo pi = c->procs_to_check[i]; - check_proc_info(c, pi); - } -#endif -} void check_parsed_files(Checker *c) { #if 0 @@ -3054,7 +2944,6 @@ void check_parsed_files(Checker *c) { 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); if (scope->is_init) { @@ -3100,7 +2989,10 @@ void check_parsed_files(Checker *c) { TIME_SECTION("check procedure bodies"); // NOTE(bill): Nested procedures bodies will be added to this "queue" - check_proc_bodies(c); + for_array(i, c->procs_to_check) { + ProcedureInfo pi = c->procs_to_check[i]; + check_proc_info(c, pi); + } for_array(i, c->info.files.entries) { AstFile *f = c->info.files.entries[i].value; diff --git a/src/checker.hpp b/src/checker.hpp index f58867479..eb358b906 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -220,10 +220,9 @@ struct Scope { PtrSet implicit; Scope * shared; - Array delayed_asserts; + Array delayed_directives; Array delayed_imports; PtrSet imported; - PtrSet exported; // NOTE(bhall): Contains 'using import' too bool is_proc; bool is_global; bool is_package; @@ -259,9 +258,8 @@ typedef PtrSet ImportGraphNodeSet; struct ImportGraphNode { + AstPackage * pkg; Scope * scope; - String path; - isize package_id; ImportGraphNodeSet pred; ImportGraphNodeSet succ; isize index; // Index in array/queue @@ -278,6 +276,31 @@ struct ForeignContext { typedef Array CheckerTypePath; +// CheckerInfo stores all the symbol information for a type-checked program +struct CheckerInfo { + Map types; // Key: AstNode * | Expression -> Type (and value) + Map untyped; // Key: AstNode * | Expression -> ExprInfo + Map files; // Key: String (full path) + Map packages; // Key: String (full path) + Map foreigns; // Key: String + Array definitions; + Array entities; + Array variable_init_order; + + Map > gen_procs; // Key: AstNode * | Identifier -> Entity + Map > gen_types; // Key: Type * + + Array type_info_types; + Map type_info_map; // Key: Type * + + + AstPackage * runtime_package; + Scope * init_scope; + Entity * entry_point; + PtrSet minimum_dependency_set; + PtrSet minimum_dependency_type_info_set; +}; + struct CheckerContext { Checker * checker; CheckerInfo * info; @@ -305,49 +328,14 @@ struct CheckerContext { Scope * polymorphic_scope; }; - -// CheckerInfo stores all the symbol information for a type-checked program -struct CheckerInfo { - Map types; // Key: AstNode * | Expression -> Type (and value) - Map untyped; // Key: AstNode * | Expression -> ExprInfo - Map files; // Key: String (full path) - Map packages; // Key: String (full path) - Map foreigns; // Key: String - Array definitions; - Array entities; - Array variable_init_order; - - Map > gen_procs; // Key: AstNode * | Identifier -> Entity - Map > gen_types; // Key: Type * - - Array type_info_types; - Map type_info_map; // Key: Type * - - - AstPackage * runtime_package; - Scope * init_scope; - Entity * entry_point; - PtrSet minimum_dependency_set; - PtrSet minimum_dependency_type_info_set; - - gbMutex mutex; -}; - struct Checker { Parser * parser; CheckerInfo info; - gbMutex mutex; - - Array procs_to_check; - Map package_scopes; // Key: String (fullpath) - Array package_order; - - gbAllocator allocator; - - CheckerContext init_ctx; - - bool done_preload; + Array procs_to_check; + gbAllocator allocator; + CheckerContext init_ctx; + bool done_preload; };