Remove dead code from checker

This commit is contained in:
gingerBill
2018-06-02 11:58:35 +01:00
parent ccbb6df749
commit ced818ad54
6 changed files with 147 additions and 288 deletions

View File

@@ -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();

View File

@@ -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 *> entity_map = {};
ptr_set_init(&entity_map, heap_allocator());
defer (ptr_set_destroy(&entity_map));
PtrSet<Entity *> 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;

View File

@@ -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;

View File

@@ -1,5 +1,5 @@
void populate_using_entity_map(CheckerContext *ctx, AstNode *node, Type *t, Map<Entity *> *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<Entity *> *fi
isize init_field_capacity, Type *named_type, String context) {
*fields = array_make<Entity *>(heap_allocator(), 0, init_field_capacity);
Map<Entity *> 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<Entity *> *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<Operand> 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 *> entity_map = {}; // Key: String
map_init(&entity_map, ctx->allocator, 2*(et->fields.count));
defer (map_destroy(&entity_map));
auto fields = array_make<Entity *>(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 *> entity_map = {}; // Key: String
map_init(&entity_map, ctx->allocator, 2*(bft->fields.count));
defer (map_destroy(&entity_map));
auto fields = array_make<Entity*>(ctx->allocator, 0, bft->fields.count);
auto sizes = array_make<u32> (ctx->allocator, 0, bft->fields.count);
auto offsets = array_make<u32> (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);

View File

@@ -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<AstNode *> 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<ImportGraphNode *> *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<ImportGraphNode *
}
Array<ImportGraphNode *> generate_import_dependency_graph(Checker *c) {
gbAllocator a = heap_allocator();
Map<ImportGraphNode *> M = {}; // Key: Scope *
map_init(&M, a);
Map<ImportGraphNode *> 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<ImportGraphNode *> generate_import_dependency_graph(Checker *c) {
}
Array<ImportGraphNode *> 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<ImportPathItem> find_import_path(Checker *c, Scope *start, Scope *end, PtrSet<Scope *> *visited) {
Array<ImportPathItem> find_import_path(Checker *c, AstPackage *start, AstPackage *end, PtrSet<AstPackage *> *visited) {
Array<ImportPathItem> empty_path = {};
if (ptr_set_exists(visited, start)) {
@@ -2494,32 +2441,32 @@ Array<ImportPathItem> 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<ImportPathItem>(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<Scope *> emitted = {};
PtrSet<AstPackage *> emitted = {};
ptr_set_init(&emitted, heap_allocator());
defer (ptr_set_destroy(&emitted));
Array<ImportGraphNode *> 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<Scope *> visited = {};
PtrSet<AstPackage *> 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<Entity *> find_entity_path(Entity *start, Entity *end, Map<Entity *> *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<gbThread>(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;

View File

@@ -220,10 +220,9 @@ struct Scope {
PtrSet<Entity *> implicit;
Scope * shared;
Array<AstNode *> delayed_asserts;
Array<AstNode *> delayed_directives;
Array<AstNode *> delayed_imports;
PtrSet<Scope *> imported;
PtrSet<Scope *> exported; // NOTE(bhall): Contains 'using import' too
bool is_proc;
bool is_global;
bool is_package;
@@ -259,9 +258,8 @@ typedef PtrSet<ImportGraphNode *> 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<Entity *> CheckerTypePath;
// CheckerInfo stores all the symbol information for a type-checked program
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;
Array<DeclInfo *> variable_init_order;
Map<Array<Entity *> > gen_procs; // Key: AstNode * | Identifier -> Entity
Map<Array<Entity *> > gen_types; // Key: Type *
Array<Type *> type_info_types;
Map<isize> type_info_map; // Key: Type *
AstPackage * runtime_package;
Scope * init_scope;
Entity * entry_point;
PtrSet<Entity *> minimum_dependency_set;
PtrSet<isize> 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<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;
Array<DeclInfo *> variable_init_order;
Map<Array<Entity *> > gen_procs; // Key: AstNode * | Identifier -> Entity
Map<Array<Entity *> > gen_types; // Key: Type *
Array<Type *> type_info_types;
Map<isize> type_info_map; // Key: Type *
AstPackage * runtime_package;
Scope * init_scope;
Entity * entry_point;
PtrSet<Entity *> minimum_dependency_set;
PtrSet<isize> minimum_dependency_type_info_set;
gbMutex mutex;
};
struct Checker {
Parser * parser;
CheckerInfo info;
gbMutex mutex;
Array<ProcedureInfo> procs_to_check;
Map<Scope *> package_scopes; // Key: String (fullpath)
Array<ImportGraphNode *> package_order;
gbAllocator allocator;
CheckerContext init_ctx;
bool done_preload;
Array<ProcedureInfo> procs_to_check;
gbAllocator allocator;
CheckerContext init_ctx;
bool done_preload;
};