aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/check_expr.cpp30
-rw-r--r--src/checker.cpp6
-rw-r--r--src/types.cpp1
3 files changed, 24 insertions, 13 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index 554b5a310..8f21d257a 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -5060,25 +5060,26 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
ProcedureInfo proc_info = {};
- if (pt->is_generic) {
+ if (pt->is_generic && !pt->is_generic_specialized) {
GB_ASSERT(entity != NULL);
+
DeclInfo *old_decl = decl_info_of_entity(&c->info, entity);
GB_ASSERT(old_decl != NULL);
gbAllocator a = heap_allocator();
- Scope *scope = entity->scope;
-
- AstNode *proc_decl = clone_ast_node(a, old_decl->proc_decl);
- ast_node(pd, ProcDecl, proc_decl);
+ CheckerContext prev_context = c->context;
+ defer (c->context = prev_context);
- check_open_scope(c, pd->type);
- defer (check_close_scope(c));
+ Scope *scope = make_scope(entity->scope, a);
+ scope->is_proc = true;
+ c->context.scope = scope;
+ // NOTE(bill): This is slightly memory leaking if the type already exists
+ // Maybe it's better to check with the previous types first?
final_proc_type = make_type_proc(c->allocator, c->context.scope, NULL, 0, NULL, 0, false, pt->calling_convention);
check_procedure_type(c, final_proc_type, pt->node, &operands);
-
bool skip = false;
auto *found = map_get(&c->info.gen_procs, hash_pointer(entity->identifier));
if (found) {
@@ -5093,7 +5094,16 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
}
}
- if (!skip) {
+ if (skip) {
+ // NOTE(bill): It is not needed any more, destroy it
+ destroy_scope(scope);
+ } else {
+ AstNode *proc_decl = clone_ast_node(a, old_decl->proc_decl);
+ ast_node(pd, ProcDecl, proc_decl);
+ // NOTE(bill): Associate the scope declared above with this procedure declaration's type
+ add_scope(c, pd->type, final_proc_type->Proc.scope);
+ final_proc_type->Proc.is_generic_specialized = true;
+
u64 tags = entity->Procedure.tags;
AstNode *ident = clone_ast_node(a, entity->identifier);
Token token = ident->Ident;
@@ -5151,7 +5161,7 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
if (are_types_identical(e->type, o.type)) {
score += assign_score_function(1);
} else {
- score += assign_score_function(5);
+ score += assign_score_function(10);
}
continue;
diff --git a/src/checker.cpp b/src/checker.cpp
index 8d0ae001c..a7e3aa524 100644
--- a/src/checker.cpp
+++ b/src/checker.cpp
@@ -387,9 +387,9 @@ Scope *make_scope(Scope *parent, gbAllocator allocator) {
Scope *s = gb_alloc_item(allocator, Scope);
s->parent = parent;
map_init(&s->elements, heap_allocator());
- map_init(&s->implicit, heap_allocator());
- array_init(&s->shared, heap_allocator());
- array_init(&s->imported, heap_allocator());
+ map_init(&s->implicit, heap_allocator());
+ array_init(&s->shared, heap_allocator());
+ array_init(&s->imported, heap_allocator());
if (parent != NULL && parent != universal_scope) {
DLIST_APPEND(parent->first_child, parent->last_child, s);
diff --git a/src/types.cpp b/src/types.cpp
index 41ce0a19d..465f69048 100644
--- a/src/types.cpp
+++ b/src/types.cpp
@@ -150,6 +150,7 @@ struct TypeRecord {
bool require_results; \
bool c_vararg; \
bool is_generic; \
+ bool is_generic_specialized; \
ProcCallingConvention calling_convention; \
}) \
TYPE_KIND(Map, struct { \