From d974b29f67ea536e1da033e41f3b03e05696f438 Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Mon, 26 Jun 2017 14:39:51 +0100 Subject: [PATCH] Reduce excessive node cloning on para-poly checking and fix scope bug --- src/check_expr.cpp | 30 ++++++++++++++++++++---------- src/checker.cpp | 6 +++--- src/types.cpp | 1 + 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; + CheckerContext prev_context = c->context; + defer (c->context = prev_context); - AstNode *proc_decl = clone_ast_node(a, old_decl->proc_decl); - ast_node(pd, ProcDecl, proc_decl); - - 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 { \