Browse Source

Reduce excessive node cloning on para-poly checking and fix scope bug

Ginger Bill 8 years ago
parent
commit
d974b29f67
3 changed files with 24 additions and 13 deletions
  1. 20 10
      src/check_expr.cpp
  2. 3 3
      src/checker.cpp
  3. 1 0
      src/types.cpp

+ 20 - 10
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;

+ 3 - 3
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);

+ 1 - 0
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 {                               \