Browse Source

Explicit procedure group; Remove implicit procedure overloading

gingerBill 7 years ago
parent
commit
3703ca4df4
12 changed files with 351 additions and 524 deletions
  1. 3 3
      core/math.odin
  2. 2 2
      examples/game.odin
  3. 1 1
      src/build_settings.cpp
  4. 83 15
      src/check_decl.cpp
  5. 52 169
      src/check_expr.cpp
  6. 156 157
      src/check_stmt.cpp
  7. 20 146
      src/checker.cpp
  8. 4 4
      src/entity.cpp
  9. 11 10
      src/ir.cpp
  10. 0 1
      src/main.cpp
  11. 5 2
      src/map.cpp
  12. 14 14
      src/parser.cpp

+ 3 - 3
core/math.odin

@@ -148,9 +148,10 @@ div :: proc[
 ];
 
 inverse :: proc[mat4_inverse, quat_inverse];
+dot     :: proc[vec_dot, quat_dot];
+cross   :: proc[cross2, cross3];
 
-
-dot :: proc(a, b: $T/[$N]$E) -> E {
+vec_dot :: proc(a, b: $T/[$N]$E) -> E {
 	res: E;
 	for i in 0..N {
 		res += a[i] * b[i];
@@ -167,7 +168,6 @@ cross3 :: proc(a, b: $T/[3]$E) -> T {
 	j := swizzle(a, 2, 0, 1) * swizzle(b, 1, 2, 0);
 	return T(i - j);
 }
-cross :: proc[cross2, cross3];
 
 
 length :: proc(v: $T/[$N]$E) -> E { return sqrt(dot(v, v)); }

+ 2 - 2
examples/game.odin

@@ -1,5 +1,5 @@
-import win32 "core:sys/windows.odin" when ODIN_OS == "windows";
-import wgl "core:sys/wgl.odin" when ODIN_OS == "windows";
+when ODIN_OS == "windows" do import win32 "core:sys/windows.odin";
+when ODIN_OS == "windows" import wgl "core:sys/wgl.odin";
 import "core:fmt.odin";
 import "core:math.odin";
 import "core:os.odin";

+ 1 - 1
src/build_settings.cpp

@@ -308,7 +308,7 @@ String get_fullpath_core(gbAllocator a, String path) {
 }
 
 
-String const ODIN_VERSION = str_lit("0.7.1");
+String const ODIN_VERSION = str_lit("0.8.0-dev");
 String cross_compile_target = str_lit("");
 String cross_compile_lib_dir = str_lit("");
 

+ 83 - 15
src/check_decl.cpp

@@ -23,9 +23,9 @@ Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String contex
 		}
 
 
-		if (operand->mode == Addressing_Overload) {
+		if (operand->mode == Addressing_ProcGroup) {
 			if (e->type == nullptr) {
-				error(operand->expr, "Cannot determine type from overloaded procedure '%.*s'", LIT(operand->overload_entities[0]->token.string));
+				error(operand->expr, "Cannot determine type from overloaded procedure '%.*s'", LIT(operand->proc_group->token.string));
 			} else {
 				check_assignment(c, operand, e->type, str_lit("variable assignment"));
 				if (operand->mode != Addressing_Type) {
@@ -275,11 +275,15 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init,
 			e->type = t_invalid;
 			return;
 
-		case Addressing_Overload:
-			e->kind = Entity_Alias;
-			e->Alias.base = operand.overload_entities[0];
+		case Addressing_ProcGroup: {
+			GB_ASSERT(operand.proc_group != nullptr);
+			GB_ASSERT(operand.proc_group->kind == Entity_ProcGroup);
+
+			e->kind = Entity_ProcGroup;
 			e->type = t_invalid;
+			gb_memcopy(&e->ProcGroup, &operand.proc_group->ProcGroup, gb_size_of(e->ProcGroup));
 			return;
+		}
 	#endif
 		}
 	#if 1
@@ -708,11 +712,11 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count
 	check_init_variables(c, entities, entity_count, init_expr_list, context_name);
 }
 
-void check_proc_grouping_decl(Checker *c, Entity *pg_entity, DeclInfo *d) {
-	GB_ASSERT(pg_entity->kind == Entity_ProcedureGrouping);
-	auto *pge = &pg_entity->ProcedureGrouping;
+void check_proc_group_decl(Checker *c, Entity *pg_entity, DeclInfo *d) {
+	GB_ASSERT(pg_entity->kind == Entity_ProcGroup);
+	auto *pge = &pg_entity->ProcGroup;
 
-	ast_node(pg, ProcGrouping, d->init_expr);
+	ast_node(pg, ProcGroup, d->init_expr);
 
 	array_init(&pge->entities, c->allocator, pg->args.count);
 
@@ -731,22 +735,87 @@ void check_proc_grouping_decl(Checker *c, Entity *pg_entity, DeclInfo *d) {
 			e = check_selector(c, &o, arg, nullptr);
 		}
 		if (e == nullptr) {
-			error(arg, "Expected a valid entity name in procedure grouping");
+			error(arg, "Expected a valid entity name in procedure group");
 			continue;
 		}
-		if (e->kind != Entity_Procedure) {
+		if (e->kind == Entity_Variable) {
+			if (!is_type_proc(e->type)) {
+				error(arg, "Expected a procedure variable");
+				continue;
+			}
+		} else if (e->kind != Entity_Procedure) {
 			error(arg, "Expected a procedure entity");
 			continue;
 		}
 
 		if (ptr_set_exists(&entity_map, e)) {
-			error(arg, "Previous use of `%.*s` in procedure grouping", LIT(e->token.string));
+			error(arg, "Previous use of `%.*s` in procedure group", LIT(e->token.string));
 			continue;
 		}
 		ptr_set_add(&entity_map, e);
 
 		array_add(&pge->entities, e);
 	}
+
+	for_array(j, pge->entities) {
+		Entity *p = pge->entities[j];
+		if (p->type == t_invalid) {
+			// NOTE(bill): This invalid overload has already been handled
+			continue;
+		}
+
+		String name = p->token.string;
+
+		for (isize k = j+1; k < pge->entities.count; k++) {
+			Entity *q = pge->entities[k];
+			GB_ASSERT(p != q);
+
+			bool is_invalid = false;
+
+			TokenPos pos = q->token.pos;
+
+			if (q->type == nullptr || q->type == t_invalid) {
+				continue;
+			}
+
+			ProcTypeOverloadKind kind = are_proc_types_overload_safe(p->type, q->type);
+			switch (kind) {
+			case ProcOverload_Identical:
+				error(p->token, "Overloaded procedure '%.*s' as the same type as another procedure in this scope", LIT(name));
+				is_invalid = true;
+				break;
+			// case ProcOverload_CallingConvention:
+				// error(p->token, "Overloaded procedure '%.*s' as the same type as another procedure in this scope", LIT(name));
+				// is_invalid = true;
+				// break;
+			case ProcOverload_ParamVariadic:
+				error(p->token, "Overloaded procedure '%.*s' as the same type as another procedure in this scope", LIT(name));
+				is_invalid = true;
+				break;
+			case ProcOverload_ResultCount:
+			case ProcOverload_ResultTypes:
+				error(p->token, "Overloaded procedure '%.*s' as the same parameters but different results in this scope", LIT(name));
+				is_invalid = true;
+				break;
+			case ProcOverload_Polymorphic:
+				#if 0
+				error(p->token, "Overloaded procedure '%.*s' has a polymorphic counterpart in this scope which is not allowed", LIT(name));
+				is_invalid = true;
+				#endif
+				break;
+			case ProcOverload_ParamCount:
+			case ProcOverload_ParamTypes:
+				// This is okay :)
+				break;
+
+			}
+
+			if (is_invalid) {
+				gb_printf_err("\tprevious procedure at %.*s(%td:%td)\n", LIT(pos.file), pos.line, pos.column);
+				q->type = t_invalid;
+			}
+		}
+	}
 }
 
 void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) {
@@ -787,9 +856,8 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) {
 		check_proc_decl(c, e, d);
 		break;
 
-	case Entity_ProcedureGrouping:
-		// error(e->token, "Procedure groupings are not yet supported");
-		check_proc_grouping_decl(c, e, d);
+	case Entity_ProcGroup:
+		check_proc_group_decl(c, e, d);
 		break;
 	}
 

+ 52 - 169
src/check_expr.cpp

@@ -127,14 +127,6 @@ void check_scope_decls(Checker *c, Array<AstNode *> nodes, isize reserve_size) {
 			check_entity_decl(c, e, d, nullptr);
 		}
 	}
-
-	for_array(i, s->elements.entries) {
-		Entity *e = s->elements.entries[i].value;
-		if (e->kind != Entity_Procedure) {
-			continue;
-		}
-		check_procedure_overloading(c, e);
-	}
 }
 
 
@@ -659,18 +651,16 @@ void check_assignment(Checker *c, Operand *operand, Type *type, String context_n
 		return;
 	}
 
-	if (operand->mode == Addressing_Overload) {
+	if (operand->mode == Addressing_ProcGroup) {
 		// GB_PANIC("HERE!\n");
 
 		gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
 		defer (gb_temp_arena_memory_end(tmp));
 
-		Entity **procs = operand->overload_entities;
-		isize overload_count = operand->overload_count;
-
+		Array<Entity *> procs = proc_group_entities(c, *operand);
 		bool good = false;
 		// NOTE(bill): These should be done
-		for (isize i = 0; i < overload_count; i++) {
+		for_array(i, procs) {
 			Type *t = base_type(procs[i]->type);
 			if (t == t_invalid) {
 				continue;
@@ -783,7 +773,10 @@ bool is_polymorphic_type_assignable(Checker *c, Type *poly, Type *source, bool c
 		return false;
 	case Type_Array:
 		if (source->kind == Type_Array) {
-			if (poly->Array.generic_type && modify_type) {
+
+			// IMPORTANT TODO(bill): Which is correct?
+			// if (poly->Array.generic_type != nullptr && modify_type) {
+			if (poly->Array.generic_type != nullptr) {
 				Type *gt = poly->Array.generic_type;
 				GB_ASSERT(gt->kind == Type_Generic);
 				Entity *e = scope_lookup_entity(gt->Generic.scope, gt->Generic.name);
@@ -808,8 +801,6 @@ bool is_polymorphic_type_assignable(Checker *c, Type *poly, Type *source, bool c
 				} else {
 					return false;
 				}
-
-				return is_polymorphic_type_assignable(c, poly->Array.elem, source->Array.elem, true, modify_type);
 			}
 			if (poly->Array.count == source->Array.count) {
 				return is_polymorphic_type_assignable(c, poly->Array.elem, source->Array.elem, true, modify_type);
@@ -936,10 +927,6 @@ Entity *check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *
 			return nullptr;
 		}
 	}
-
-	bool is_overloaded = false;
-	isize overload_count = 0;
-
 	bool is_alias = false;
 	while (e->kind == Entity_Alias) {
 		GB_ASSERT(e->Alias.base != nullptr);
@@ -949,63 +936,14 @@ Entity *check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *
 
 	HashKey key = hash_string(e->token.string);
 
-
-	if (e->kind == Entity_Procedure) {
-		// NOTE(bill): Overloads are only allowed with the same scope
-		Scope *s = e->scope;
-		overload_count = multi_map_count(&s->elements, key);
-		if (overload_count > 1) {
-			is_overloaded = true;
-		}
-	}
-
-	if (is_overloaded) {
-		Scope *s = e->scope;
-		bool skip = false;
-
-		Entity **procs = gb_alloc_array(heap_allocator(), Entity *, overload_count);
-		multi_map_get_all(&s->elements, key, procs);
-		if (type_hint != nullptr) {
-			gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
-			defer (gb_temp_arena_memory_end(tmp));
-
-			// NOTE(bill): These should be done
-			for (isize i = 0; i < overload_count; i++) {
-				Type *t = base_type(procs[i]->type);
-				if (t == t_invalid) {
-					continue;
-				}
-				Operand x = {};
-				x.mode = Addressing_Value;
-				x.type = t;
-				if (check_is_assignable_to(c, &x, type_hint)) {
-					e = procs[i];
-					add_entity_use(c, n, e);
-					skip = true;
-					break;
-				}
-			}
-		}
-
-		if (!skip) {
-			o->mode              = Addressing_Overload;
-			o->type              = t_invalid;
-			o->overload_count    = overload_count;
-			o->overload_entities = procs;
-			return nullptr;
-		}
-		gb_free(heap_allocator(), procs);
-	}
-
-	if (e->kind == Entity_ProcedureGrouping) {
-		auto *pge = &e->ProcedureGrouping;
+	if (e->kind == Entity_ProcGroup) {
+		auto *pge = &e->ProcGroup;
 
 		DeclInfo *d = decl_info_of_entity(&c->info, e);
 		check_entity_decl(c, e, d, nullptr);
 
 
-		Entity **procs = pge->entities.data;
-		isize overload_count = pge->entities.count;
+		Array<Entity *> procs = pge->entities;
 		bool skip = false;
 
 		if (type_hint != nullptr) {
@@ -1013,7 +951,7 @@ Entity *check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *
 			defer (gb_temp_arena_memory_end(tmp));
 
 			// NOTE(bill): These should be done
-			for (isize i = 0; i < overload_count; i++) {
+			for_array(i, procs) {
 				Type *t = base_type(procs[i]->type);
 				if (t == t_invalid) {
 					continue;
@@ -1031,10 +969,9 @@ Entity *check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *
 		}
 
 		if (!skip) {
-			o->mode              = Addressing_Overload;
-			o->type              = t_invalid;
-			o->overload_count    = overload_count;
-			o->overload_entities = procs;
+			o->mode       = Addressing_ProcGroup;
+			o->type       = t_invalid;
+			o->proc_group = e;
 			return nullptr;
 		}
 	}
@@ -1550,13 +1487,13 @@ void check_comparison(Checker *c, Operand *x, Operand *y, TokenKind op) {
 		}
 	} else {
 		gbString xt, yt;
-		if (x->mode == Addressing_Overload) {
-			xt = gb_string_make(heap_allocator(), "overloaded procedure");
+		if (x->mode == Addressing_ProcGroup) {
+			xt = gb_string_make(heap_allocator(), "procedure group");
 		} else {
 			xt = type_to_string(x->type);
 		}
-		if (y->mode == Addressing_Overload) {
-			yt = gb_string_make(heap_allocator(), "overloaded procedure");
+		if (y->mode == Addressing_ProcGroup) {
+			yt = gb_string_make(heap_allocator(), "procedure group");
 		} else {
 			yt = type_to_string(y->type);
 		}
@@ -2483,18 +2420,6 @@ bool check_index_value(Checker *c, bool open_range, AstNode *index_value, i64 ma
 	return true;
 }
 
-isize entity_overload_count(Scope *s, String name) {
-	Entity *e = scope_lookup_entity(s, name);
-	if (e == nullptr) {
-		return 0;
-	}
-	if (e->kind == Entity_Procedure) {
-		// NOTE(bill): Overloads are only allowed with the same scope
-		return multi_map_count(&s->elements, hash_string(e->token.string));
-	}
-	return 1;
-}
-
 Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_hint) {
 	ast_node(se, SelectorExpr, node);
 
@@ -2572,7 +2497,7 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
 			}
 
 			check_entity_decl(c, entity, nullptr, nullptr);
-			GB_ASSERT(entity->type != nullptr || entity->kind == Entity_ProcedureGrouping);
+			GB_ASSERT(entity->type != nullptr || entity->kind == Entity_ProcGroup);
 
 			if (is_alias) {
 				// TODO(bill): Which scope do you search for for an alias?
@@ -2580,46 +2505,26 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
 				entity_name = entity->token.string;
 			}
 
-			isize overload_count = entity_overload_count(import_scope, entity_name);
-			bool is_overloaded = overload_count > 1;
 
 			bool implicit_is_found = is_entity_implicitly_imported(e, entity);
 			bool is_not_exported = !is_entity_exported(entity);
 			if (entity->kind == Entity_ImportName) {
 				is_not_exported = true;
 			} else if (implicit_is_found) {
-				is_not_exported = !is_overloaded;
-			}
-
-
-			Entity **procs = nullptr;
-
-			if (is_overloaded) {
-				HashKey key = hash_string(entity_name);
-				procs = gb_alloc_array(heap_allocator(), Entity *, overload_count);
-				multi_map_get_all(&import_scope->elements, key, procs);
-			} else if (entity->kind == Entity_ProcedureGrouping) {
-				is_overloaded = true;
-				procs = entity->ProcedureGrouping.entities.data;
-				overload_count = entity->ProcedureGrouping.entities.count;
+				is_not_exported = true;
 			}
 
-			if (is_overloaded) {
+			if (is_not_exported && entity->kind == Entity_ProcGroup) {
+				check_entity_decl(c, entity, nullptr, nullptr);
+				auto *pge = &entity->ProcGroup;
+				Array<Entity *> procs = pge->entities;
 				bool skip = false;
-				for (isize i = 0; i < overload_count; i++) {
+				for_array(i, procs) {
 					Type *t = base_type(procs[i]->type);
 					if (t == t_invalid) {
 						continue;
 					}
 
-					// NOTE(bill): Check to see if it's imported
-					if (is_entity_implicitly_imported(e, procs[i])) {
-						gb_swap(Entity *, procs[i], procs[overload_count-1]);
-						overload_count--;
-						i--; // NOTE(bill): Counteract the post event
-						continue;
-					}
-
 					Operand x = {};
 					x.mode = Addressing_Value;
 					x.type = t;
@@ -2633,16 +2538,12 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
 				}
 
 				if (!skip) {
-					if (overload_count > 0) {
-						operand->mode              = Addressing_Overload;
-						operand->type              = t_invalid;
-						operand->expr              = node;
-						operand->overload_count    = overload_count;
-						operand->overload_entities = procs;
-						return procs[0];
-					} else {
-						is_not_exported = true;
-					}
+					GB_ASSERT(e != nullptr);
+					operand->mode       = Addressing_ProcGroup;
+					operand->type       = t_invalid;
+					operand->expr       = node;
+					operand->proc_group = e;
+					return e;
 				}
 			}
 
@@ -2791,7 +2692,7 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
 		operand->builtin_id = cast(BuiltinProcId)entity->Builtin.id;
 		break;
 
-	case Entity_ProcedureGrouping:
+	case Entity_ProcGroup:
 		entity->type = t_invalid;
 		break;
 
@@ -4439,7 +4340,6 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) {
 	return err;
 }
 
-
 CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode *call) {
 	ast_node(ce, CallExpr, call);
 
@@ -4469,31 +4369,19 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t
 		check_unpack_arguments(c, nullptr, -1, &operands, ce->args, false);
 	}
 
-	if (operand->mode == Addressing_Overload) {
-		// GB_ASSERT_MSG(operand->overload_entities != nullptr &&
-		//               operand->overload_count > 0,
-		//               "%p %td", operand->overload_entities, operand->overload_count);
-		isize               overload_count = operand->overload_count;
-		Entity **           procs          = operand->overload_entities;
-		ValidIndexAndScore *valids         = gb_alloc_array(heap_allocator(), ValidIndexAndScore, overload_count);
-		isize               valid_count    = 0;
+	if (operand->mode == Addressing_ProcGroup) {
+		Array<Entity *> procs = proc_group_entities(c, *operand);
 
-		defer (gb_free(heap_allocator(), procs));
+		ValidIndexAndScore *valids         = gb_alloc_array(heap_allocator(), ValidIndexAndScore, procs.count);
+		isize               valid_count    = 0;
 		defer (gb_free(heap_allocator(), valids));
 
 		gbString expr_name = expr_to_string(operand->expr);
 		defer (gb_string_free(expr_name));
 
-		for (isize i = 0; i < overload_count; i++) {
-			Entity *e = procs[i];
-			// GB_ASSERT(e->token.string == name);
-			DeclInfo *d = decl_info_of_entity(&c->info, e);
-			GB_ASSERT(d != nullptr);
-			check_entity_decl(c, e, d, nullptr);
-		}
-
-		for (isize i = 0; i < overload_count; i++) {
+		for_array(i, procs) {
 			Entity *p = procs[i];
+			check_entity_decl(c, p, nullptr, nullptr);
 			Type *pt = base_type(p->type);
 			if (pt != nullptr && is_type_proc(pt)) {
 				CallArgumentError err = CallArgumentError_None;
@@ -4502,6 +4390,7 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t
 				defer (c->context = prev_context);
 				c->context.no_polymorphic_errors = true;
 				c->context.allow_polymorphic_types = is_type_polymorphic(pt);
+
 				err = call_checker(c, call, pt, p, operands, CallArgumentMode_NoErrors, &data);
 
 				if (err == CallArgumentError_None) {
@@ -4531,7 +4420,7 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t
 
 
 		if (valid_count == 0) {
-			error(operand->expr, "No overloads or ambiguous call for '%s' that match with the given arguments", expr_name);
+			error(operand->expr, "No procedures or ambiguous call for procedure group '%s' that match with the given arguments", expr_name);
 			gb_printf_err("\tGiven argument types -> (");
 			for_array(i, operands) {
 				Operand o = operands[i];
@@ -4542,10 +4431,10 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t
 			}
 			gb_printf_err(")\n");
 
-			if (overload_count > 0) {
+			if (procs.count > 0) {
 				gb_printf_err("Did you mean to use one of the following:\n");
 			}
-			for (isize i = 0; i < overload_count; i++) {
+			for_array(i, procs) {
 				Entity *proc = procs[i];
 				TokenPos pos = proc->token.pos;
 				Type *t = base_type(proc->type);
@@ -4562,12 +4451,12 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t
 				// gb_printf_err("\t%.*s :: %s at %.*s(%td:%td)\n", LIT(name), pt, LIT(pos.file), pos.line, pos.column);
 				gb_string_free(pt);
 			}
-			if (overload_count > 0) {
+			if (procs.count > 0) {
 				gb_printf_err("\n");
 			}
 			result_type = t_invalid;
 		} else if (valid_count > 1) {
-			error(operand->expr, "Ambiguous procedure call '%s' tha match with the given arguments", expr_name);
+			error(operand->expr, "Ambiguous procedure group call '%s' that match with the given arguments", expr_name);
 			gb_printf_err("\tGiven argument types -> (");
 			for_array(i, operands) {
 				Operand o = operands[i];
@@ -4606,11 +4495,8 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t
 			proc_type = e->type;
 			CallArgumentData data = {};
 			CallArgumentError err = call_checker(c, call, proc_type, e, operands, CallArgumentMode_ShowErrors, &data);
-			if (data.gen_entity != nullptr) {
-				add_entity_use(c, ident, data.gen_entity);
-			} else {
-				add_entity_use(c, ident, e);
-			}
+			Entity *entity_to_use = data.gen_entity != nullptr ? data.gen_entity : e;
+			add_entity_use(c, ident, entity_to_use);
 			return data;
 		}
 	} else {
@@ -4623,11 +4509,8 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t
 		Entity *e = entity_of_ident(&c->info, ident);
 		CallArgumentData data = {};
 		CallArgumentError err = call_checker(c, call, proc_type, e, operands, CallArgumentMode_ShowErrors, &data);
-		if (data.gen_entity != nullptr) {
-			add_entity_use(c, ident, data.gen_entity);
-		} else {
-			add_entity_use(c, ident, e);
-		}
+		Entity *entity_to_use = data.gen_entity != nullptr ? data.gen_entity : e;
+		add_entity_use(c, ident, entity_to_use);
 		return data;
 	}
 
@@ -4953,7 +4836,7 @@ ExprKind check_call_expr(Checker *c, Operand *operand, AstNode *call) {
 	}
 
 	Type *proc_type = base_type(operand->type);
-	if (operand->mode != Addressing_Overload) {
+	if (operand->mode != Addressing_ProcGroup) {
 		bool valid_type = (proc_type != nullptr) && is_type_proc(proc_type);
 		bool valid_mode = is_operand_value(*operand);
 		if (!valid_type || !valid_mode) {
@@ -5206,8 +5089,8 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
 		o->mode = Addressing_Constant;
 	case_end;
 
-	case_ast_node(pg, ProcGrouping, node);
-		error(node, "Illegal use of a procedure grouping");
+	case_ast_node(pg, ProcGroup, node);
+		error(node, "Illegal use of a procedure group");
 		o->mode = Addressing_Invalid;
 	case_end;
 
@@ -6205,7 +6088,7 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
 		str = gb_string_appendc(str, "---");
 	case_end;
 
-	case_ast_node(pg, ProcGrouping, node);
+	case_ast_node(pg, ProcGroup, node);
 		str = gb_string_appendc(str, "proc[");
 		for_array(i, pg->args) {
 			if (i > 0) str = gb_string_appendc(str, ", ");

+ 156 - 157
src/check_stmt.cpp

@@ -30,7 +30,7 @@ void check_stmt_list(Checker *c, Array<AstNode *> stmts, u32 flags) {
 		if (i+1 < max) {
 			switch (n->kind) {
 			case AstNode_ReturnStmt:
-				error(n, "Statements after this 'return' are never executed");
+				error(n, "Statements after this 'return' are never execu");
 				break;
 
 			case AstNode_BranchStmt:
@@ -182,7 +182,7 @@ Type *check_assignment_variable(Checker *c, Operand *lhs, Operand *rhs) {
 		return nullptr;
 	}
 	if (rhs->type == t_invalid &&
-	    rhs->mode != Addressing_Overload &&
+	    rhs->mode != Addressing_ProcGroup &&
 	    rhs->mode != Addressing_Builtin) {
 		return nullptr;
 	}
@@ -203,17 +203,16 @@ Type *check_assignment_variable(Checker *c, Operand *lhs, Operand *rhs) {
 	bool used = false;
 
 	if (lhs->mode == Addressing_Invalid ||
-	    (lhs->type == t_invalid && lhs->mode != Addressing_Overload)) {
+	    (lhs->type == t_invalid && lhs->mode != Addressing_ProcGroup)) {
 		return nullptr;
 	}
 
-	if (rhs->mode == Addressing_Overload) {
-		isize overload_count = rhs->overload_count;
-		Entity **procs = rhs->overload_entities;
-		GB_ASSERT(procs != nullptr && overload_count > 0);
+	if (rhs->mode == Addressing_ProcGroup) {
+		Array<Entity *> procs = proc_group_entities(c, *rhs);
+		GB_ASSERT(procs.count > 0);
 
 		// NOTE(bill): These should be done
-		for (isize i = 0; i < overload_count; i++) {
+		for_array(i, procs) {
 			Type *t = base_type(procs[i]->type);
 			if (t == t_invalid) {
 				continue;
@@ -232,8 +231,7 @@ Type *check_assignment_variable(Checker *c, Operand *lhs, Operand *rhs) {
 			// HACK TODO(bill): Should the entities be freed as it's technically a leak
 			rhs->mode = Addressing_Value;
 			rhs->type = e->type;
-			rhs->overload_count = 0;
-			rhs->overload_entities = nullptr;
+			rhs->proc_group = nullptr;
 		}
 	} else {
 		if (node->kind == AstNode_Ident) {
@@ -1680,176 +1678,177 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 	case_end;
 
 	case_ast_node(vd, ValueDecl, node);
-		if (!vd->is_mutable) {
-			break;
-		}
-		Entity **entities = gb_alloc_array(c->allocator, Entity *, vd->names.count);
-		isize entity_count = 0;
-
-		for_array(i, vd->names) {
-			AstNode *name = vd->names[i];
-			Entity *entity = nullptr;
-			if (name->kind != AstNode_Ident) {
-				error(name, "A variable declaration must be an identifier");
-			} else {
-				Token token = name->Ident.token;
-				String str = token.string;
-				Entity *found = nullptr;
-				// NOTE(bill): Ignore assignments to '_'
-				if (!is_blank_ident(str)) {
-					found = current_scope_lookup_entity(c->context.scope, str);
-				}
-				if (found == nullptr) {
-					entity = make_entity_variable(c->allocator, c->context.scope, token, nullptr, false);
-					entity->identifier = name;
-
-					AstNode *fl = c->context.foreign_context.curr_library;
-					if (fl != nullptr) {
-						GB_ASSERT(fl->kind == AstNode_Ident);
-						entity->Variable.is_foreign = true;
-						entity->Variable.foreign_library_ident = fl;
-					}
+		if (vd->is_mutable) {
+			Entity **entities = gb_alloc_array(c->allocator, Entity *, vd->names.count);
+			isize entity_count = 0;
+
+			for_array(i, vd->names) {
+				AstNode *name = vd->names[i];
+				Entity *entity = nullptr;
+				if (name->kind != AstNode_Ident) {
+					error(name, "A variable declaration must be an identifier");
 				} else {
-					TokenPos pos = found->token.pos;
-					error(token,
-					      "Redeclaration of '%.*s' in this scope\n"
-					      "\tat %.*s(%td:%td)",
-					      LIT(str), LIT(pos.file), pos.line, pos.column);
-					entity = found;
+					Token token = name->Ident.token;
+					String str = token.string;
+					Entity *found = nullptr;
+					// NOTE(bill): Ignore assignments to '_'
+					if (!is_blank_ident(str)) {
+						found = current_scope_lookup_entity(c->context.scope, str);
+					}
+					if (found == nullptr) {
+						entity = make_entity_variable(c->allocator, c->context.scope, token, nullptr, false);
+						entity->identifier = name;
+
+						AstNode *fl = c->context.foreign_context.curr_library;
+						if (fl != nullptr) {
+							GB_ASSERT(fl->kind == AstNode_Ident);
+							entity->Variable.is_foreign = true;
+							entity->Variable.foreign_library_ident = fl;
+						}
+					} else {
+						TokenPos pos = found->token.pos;
+						error(token,
+						      "Redeclaration of '%.*s' in this scope\n"
+						      "\tat %.*s(%td:%td)",
+						      LIT(str), LIT(pos.file), pos.line, pos.column);
+						entity = found;
+					}
+				}
+				if (entity == nullptr) {
+					entity = make_entity_dummy_variable(c->allocator, c->global_scope, ast_node_token(name));
+				}
+				entity->parent_proc_decl = c->context.curr_proc_decl;
+				entities[entity_count++] = entity;
+			}
+
+			Type *init_type = nullptr;
+			if (vd->type != nullptr) {
+				init_type = check_type(c, vd->type, nullptr);
+				if (init_type == nullptr) {
+					init_type = t_invalid;
+				} else if (is_type_polymorphic(base_type(init_type))) {
+					gbString str = type_to_string(init_type);
+					error(vd->type, "Invalid use of a polymorphic type '%s' in variable declaration", str);
+					gb_string_free(str);
+					init_type = t_invalid;
+				} else if (is_type_empty_union(init_type)) {
+					gbString str = type_to_string(init_type);
+					error(vd->type, "An empty union '%s' cannot be instantiated in variable declaration", str);
+					gb_string_free(str);
+					init_type = t_invalid;
 				}
 			}
-			if (entity == nullptr) {
-				entity = make_entity_dummy_variable(c->allocator, c->global_scope, ast_node_token(name));
-			}
-			entity->parent_proc_decl = c->context.curr_proc_decl;
-			entities[entity_count++] = entity;
-		}
-
-		Type *init_type = nullptr;
-		if (vd->type != nullptr) {
-			init_type = check_type(c, vd->type, nullptr);
-			if (init_type == nullptr) {
-				init_type = t_invalid;
-			} else if (is_type_polymorphic(base_type(init_type))) {
-				gbString str = type_to_string(init_type);
-				error(vd->type, "Invalid use of a polymorphic type '%s' in variable declaration", str);
-				gb_string_free(str);
-				init_type = t_invalid;
-			} else if (is_type_empty_union(init_type)) {
-				gbString str = type_to_string(init_type);
-				error(vd->type, "An empty union '%s' cannot be instantiated in variable declaration", str);
-				gb_string_free(str);
-				init_type = t_invalid;
-			}
-		}
 
 
-		// TODO NOTE(bill): This technically checks things multple times
-		AttributeContext ac = make_attribute_context(c->context.foreign_context.link_prefix);
-		check_decl_attributes(c, vd->attributes, var_decl_attribute, &ac);
+			// TODO NOTE(bill): This technically checks things multple times
+			AttributeContext ac = make_attribute_context(c->context.foreign_context.link_prefix);
+			check_decl_attributes(c, vd->attributes, var_decl_attribute, &ac);
 
-		for (isize i = 0; i < entity_count; i++) {
-			Entity *e = entities[i];
-			GB_ASSERT(e != nullptr);
-			if (e->flags & EntityFlag_Visited) {
-				e->type = t_invalid;
-				continue;
-			}
-			e->flags |= EntityFlag_Visited;
+			for (isize i = 0; i < entity_count; i++) {
+				Entity *e = entities[i];
+				GB_ASSERT(e != nullptr);
+				if (e->flags & EntityFlag_Visited) {
+					e->type = t_invalid;
+					continue;
+				}
+				e->flags |= EntityFlag_Visited;
 
-			if (e->type == nullptr) {
-				e->type = init_type;
-			}
-			ac.link_name = handle_link_name(c, e->token, ac.link_name, ac.link_prefix);
-			e->Variable.thread_local_model = ac.thread_local_model;
+				if (e->type == nullptr) {
+					e->type = init_type;
+				}
+				ac.link_name = handle_link_name(c, e->token, ac.link_name, ac.link_prefix);
+				e->Variable.thread_local_model = ac.thread_local_model;
 
-			if (ac.link_name.len > 0) {
-				e->Variable.link_name = ac.link_name;
+				if (ac.link_name.len > 0) {
+					e->Variable.link_name = ac.link_name;
+				}
 			}
-		}
-
-		check_arity_match(c, vd);
-		check_init_variables(c, entities, entity_count, vd->values, str_lit("variable declaration"));
 
-		for (isize i = 0; i < entity_count; i++) {
-			Entity *e = entities[i];
-			if (e->Variable.is_foreign) {
-				if (vd->values.count > 0) {
-					error(e->token, "A foreign variable declaration cannot have a default value");
-				}
+			check_arity_match(c, vd);
+			check_init_variables(c, entities, entity_count, vd->values, str_lit("variable declaration"));
 
-				String name = e->token.string;
-				if (e->Variable.link_name.len > 0) {
-					name = e->Variable.link_name;
-				}
+			for (isize i = 0; i < entity_count; i++) {
+				Entity *e = entities[i];
+				if (e->Variable.is_foreign) {
+					if (vd->values.count > 0) {
+						error(e->token, "A foreign variable declaration cannot have a default value");
+					}
 
-				if (vd->values.count > 0) {
-					error(e->token, "A foreign variable declaration cannot have a default value");
-				}
-				init_entity_foreign_library(c, e);
+					String name = e->token.string;
+					if (e->Variable.link_name.len > 0) {
+						name = e->Variable.link_name;
+					}
 
-				auto *fp = &c->info.foreigns;
-				HashKey key = hash_string(name);
-				Entity **found = map_get(fp, key);
-				if (found) {
-					Entity *f = *found;
-					TokenPos pos = f->token.pos;
-					Type *this_type = base_type(e->type);
-					Type *other_type = base_type(f->type);
-					if (!are_types_identical(this_type, other_type)) {
-						error(e->token,
-						      "Foreign entity '%.*s' previously declared elsewhere with a different type\n"
-						      "\tat %.*s(%td:%td)",
-						      LIT(name), LIT(pos.file), pos.line, pos.column);
+					if (vd->values.count > 0) {
+						error(e->token, "A foreign variable declaration cannot have a default value");
+					}
+					init_entity_foreign_library(c, e);
+
+					auto *fp = &c->info.foreigns;
+					HashKey key = hash_string(name);
+					Entity **found = map_get(fp, key);
+					if (found) {
+						Entity *f = *found;
+						TokenPos pos = f->token.pos;
+						Type *this_type = base_type(e->type);
+						Type *other_type = base_type(f->type);
+						if (!are_types_identical(this_type, other_type)) {
+							error(e->token,
+							      "Foreign entity '%.*s' previously declared elsewhere with a different type\n"
+							      "\tat %.*s(%td:%td)",
+							      LIT(name), LIT(pos.file), pos.line, pos.column);
+						}
+					} else {
+						map_set(fp, key, e);
 					}
-				} else {
-					map_set(fp, key, e);
 				}
-			}
-			add_entity(c, c->context.scope, e->identifier, e);
-		}
-
-		if (vd->is_using != 0) {
-			Token token = ast_node_token(node);
-			if (vd->type != nullptr && entity_count > 1) {
-				error(token, "'using' can only be applied to one variable of the same type");
-				// TODO(bill): Should a 'continue' happen here?
+				add_entity(c, c->context.scope, e->identifier, e);
 			}
 
-			for (isize entity_index = 0; entity_index < entity_count; entity_index++) {
-				Entity *e = entities[entity_index];
-				if (e == nullptr) {
-					continue;
+			if (vd->is_using != 0) {
+				Token token = ast_node_token(node);
+				if (vd->type != nullptr && entity_count > 1) {
+					error(token, "'using' can only be applied to one variable of the same type");
+					// TODO(bill): Should a 'continue' happen here?
 				}
-				if (e->kind != Entity_Variable) {
-					continue;
-				}
-				bool is_immutable = e->Variable.is_immutable;
-				String name = e->token.string;
-				Type *t = base_type(type_deref(e->type));
-
-				if (is_blank_ident(name)) {
-					error(token, "'using' cannot be applied variable declared as '_'");
-				} else if (is_type_struct(t) || is_type_raw_union(t)) {
-					Scope *scope = scope_of_node(&c->info, t->Struct.node);
-					for_array(i, scope->elements.entries) {
-						Entity *f = scope->elements.entries[i].value;
-						if (f->kind == Entity_Variable) {
-							Entity *uvar = make_entity_using_variable(c->allocator, e, f->token, f->type);
-							uvar->Variable.is_immutable = is_immutable;
-							Entity *prev = scope_insert_entity(c->context.scope, uvar);
-							if (prev != nullptr) {
-								error(token, "Namespace collision while 'using' '%.*s' of: %.*s", LIT(name), LIT(prev->token.string));
-								return;
+
+				for (isize entity_index = 0; entity_index < entity_count; entity_index++) {
+					Entity *e = entities[entity_index];
+					if (e == nullptr) {
+						continue;
+					}
+					if (e->kind != Entity_Variable) {
+						continue;
+					}
+					bool is_immutable = e->Variable.is_immutable;
+					String name = e->token.string;
+					Type *t = base_type(type_deref(e->type));
+
+					if (is_blank_ident(name)) {
+						error(token, "'using' cannot be applied variable declared as '_'");
+					} else if (is_type_struct(t) || is_type_raw_union(t)) {
+						Scope *scope = scope_of_node(&c->info, t->Struct.node);
+						for_array(i, scope->elements.entries) {
+							Entity *f = scope->elements.entries[i].value;
+							if (f->kind == Entity_Variable) {
+								Entity *uvar = make_entity_using_variable(c->allocator, e, f->token, f->type);
+								uvar->Variable.is_immutable = is_immutable;
+								Entity *prev = scope_insert_entity(c->context.scope, uvar);
+								if (prev != nullptr) {
+									error(token, "Namespace collision while 'using' '%.*s' of: %.*s", LIT(name), LIT(prev->token.string));
+									return;
+								}
 							}
 						}
+					} else {
+						// NOTE(bill): skip the rest to remove extra errors
+						error(token, "'using' can only be applied to variables of type struct or raw_union");
+						return;
 					}
-				} else {
-					// NOTE(bill): skip the rest to remove extra errors
-					error(token, "'using' can only be applied to variables of type struct or raw_union");
-					return;
 				}
 			}
+		} else {
+			// constant value declarations
 		}
 	case_end;
 	}

+ 20 - 146
src/checker.cpp

@@ -120,7 +120,7 @@ enum AddressingMode {
 	Addressing_Constant,      // constant
 	Addressing_Type,          // type
 	Addressing_Builtin,       // built-in procedure
-	Addressing_Overload,      // overloaded procedure
+	Addressing_ProcGroup,     // procedure group (overloaded procedure)
 	Addressing_MapIndex,      // map index expression -
 	                          // 	lhs: acts like a Variable
 	                          // 	rhs: acts like OptionalOk
@@ -138,8 +138,7 @@ struct Operand {
 	ExactValue     value;
 	AstNode *      expr;
 	BuiltinProcId  builtin_id;
-	isize          overload_count;
-	Entity **      overload_entities;
+	Entity *       proc_group;
 };
 
 struct TypeAndValue {
@@ -166,6 +165,8 @@ bool is_operand_undef(Operand o) {
 	return o.mode == Addressing_Value && o.type == t_untyped_undef;
 }
 
+
+
 struct BlockLabel {
 	String   name;
 	AstNode *label; //  AstNode_Label;
@@ -780,28 +781,10 @@ Entity *scope_insert_entity(Scope *s, Entity *entity) {
 	HashKey key = hash_string(name);
 	Entity **found = map_get(&s->elements, key);
 
-#ifndef DISABLE_PROCEDURE_OVERLOADING
-	// IMPORTANT NOTE(bill): Procedure overloading code
-	Entity *prev = nullptr;
-	if (found) {
-		prev = *found;
-		if (prev->kind != Entity_Procedure ||
-		    entity->kind != Entity_Procedure) {
-			return prev;
-		}
-	}
-
-	if (prev != nullptr && entity->kind == Entity_Procedure) {
-		multi_map_insert(&s->elements, key, entity);
-	} else {
-		map_set(&s->elements, key, entity);
-	}
-#else
 	if (found) {
 		return *found;
 	}
 	map_set(&s->elements, key, entity);
-#endif
 	if (entity->scope == nullptr) {
 		entity->scope = s;
 	}
@@ -1620,6 +1603,18 @@ Type *find_core_type(Checker *c, String name) {
 
 void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type);
 
+Array<Entity *> proc_group_entities(Checker *c, Operand o) {
+	Array<Entity *> procs = {};
+	if (o.mode == Addressing_ProcGroup) {
+		GB_ASSERT(o.proc_group != nullptr);
+		if (o.proc_group->kind == Entity_ProcGroup) {
+			check_entity_decl(c, o.proc_group, nullptr, nullptr);
+			return o.proc_group->ProcGroup.entities;
+		}
+	}
+	return procs;
+}
+
 void init_preload(Checker *c) {
 	if (t_type_info == nullptr) {
 		Entity *type_info_entity = find_core_entity(c, str_lit("Type_Info"));
@@ -1736,118 +1731,6 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes);
 void check_collect_entities_from_when_stmt(Checker *c, AstNodeWhenStmt *ws);
 void check_delayed_file_import_entity(Checker *c, AstNode *decl);
 
-bool check_is_entity_overloaded(Entity *e) {
-	if (e->kind != Entity_Procedure) {
-		return false;
-	}
-	Scope *s = e->scope;
-	HashKey key = hash_string(e->token.string);
-	isize overload_count = multi_map_count(&s->elements, key);
-	return overload_count > 1;
-}
-
-void check_procedure_overloading(Checker *c, Entity *e) {
-	GB_ASSERT(e->kind == Entity_Procedure);
-	if (e->type == t_invalid) {
-		return;
-	}
-	if (e->Procedure.overload_kind != Overload_Unknown) {
-		// NOTE(bill): The overloading has already been handled
-		return;
-	}
-
-
-	// NOTE(bill): Procedures call only overload other procedures in the same scope
-
-	String name = e->token.string;
-	HashKey key = hash_string(name);
-	Scope *s = e->scope;
-	isize overload_count = multi_map_count(&s->elements, key);
-	GB_ASSERT(overload_count >= 1);
-	if (overload_count == 1) {
-		e->Procedure.overload_kind = Overload_No;
-		return;
-	}
-	GB_ASSERT(overload_count > 1);
-
-
-	gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
-	Entity **procs = gb_alloc_array(c->tmp_allocator, Entity *, overload_count);
-	multi_map_get_all(&s->elements, key, procs);
-
-	for (isize j = 0; j < overload_count; j++) {
-		Entity *p = procs[j];
-		if (p->type == t_invalid) {
-			// NOTE(bill): This invalid overload has already been handled
-			continue;
-		}
-
-		String name = p->token.string;
-
-		GB_ASSERT(p->kind == Entity_Procedure);
-		for (isize k = j+1; k < overload_count; k++) {
-			Entity *q = procs[k];
-			GB_ASSERT(p != q);
-
-			bool is_invalid = false;
-			GB_ASSERT(q->kind == Entity_Procedure);
-
-			TokenPos pos = q->token.pos;
-
-			if (q->type == nullptr || q->type == t_invalid) {
-				continue;
-			}
-
-			ProcTypeOverloadKind kind = are_proc_types_overload_safe(p->type, q->type);
-			switch (kind) {
-			case ProcOverload_Identical:
-				error(p->token, "Overloaded procedure '%.*s' as the same type as another procedure in this scope", LIT(name));
-				is_invalid = true;
-				break;
-			// case ProcOverload_CallingConvention:
-				// error(p->token, "Overloaded procedure '%.*s' as the same type as another procedure in this scope", LIT(name));
-				// is_invalid = true;
-				// break;
-			case ProcOverload_ParamVariadic:
-				error(p->token, "Overloaded procedure '%.*s' as the same type as another procedure in this scope", LIT(name));
-				is_invalid = true;
-				break;
-			case ProcOverload_ResultCount:
-			case ProcOverload_ResultTypes:
-				error(p->token, "Overloaded procedure '%.*s' as the same parameters but different results in this scope", LIT(name));
-				is_invalid = true;
-				break;
-			case ProcOverload_Polymorphic:
-				#if 0
-				error(p->token, "Overloaded procedure '%.*s' has a polymorphic counterpart in this scope which is not allowed", LIT(name));
-				is_invalid = true;
-				#endif
-				break;
-			case ProcOverload_ParamCount:
-			case ProcOverload_ParamTypes:
-				// This is okay :)
-				break;
-
-			}
-
-			if (is_invalid) {
-				gb_printf_err("\tprevious procedure at %.*s(%td:%td)\n", LIT(pos.file), pos.line, pos.column);
-				q->type = t_invalid;
-			}
-		}
-	}
-
-	for (isize j = 0; j < overload_count; j++) {
-		Entity *p = procs[j];
-		if (p->type != t_invalid) {
-			p->Procedure.overload_kind = Overload_Yes;
-		}
-	}
-
-	gb_temp_arena_memory_end(tmp);
-}
-
-
 struct AttributeContext {
 	String  link_name;
 	String  link_prefix;
@@ -2259,11 +2142,11 @@ void check_collect_value_decl(Checker *c, AstNode *decl) {
 				}
 				d->proc_lit = init;
 				d->type_expr = pl->type;
-			} else if (init->kind == AstNode_ProcGrouping) {
-				ast_node(pg, ProcGrouping, init);
-				e = make_entity_procedure_grouping(c->allocator, d->scope, token, nullptr);
+			} else if (init->kind == AstNode_ProcGroup) {
+				ast_node(pg, ProcGroup, init);
+				e = make_entity_proc_group(c->allocator, d->scope, token, nullptr);
 				if (fl != nullptr) {
-					error(name, "Procedure groupings are not allowed within a foreign block");
+					error(name, "Procedure groups are not allowed within a foreign block");
 				}
 				d->init_expr = init;
 			} else {
@@ -2447,15 +2330,6 @@ void check_all_global_entities(Checker *c) {
 			init_preload(c);
 		}
 	}
-
-	for_array(i, c->info.entities.entries) {
-		auto *entry = &c->info.entities.entries[i];
-		Entity *e = cast(Entity *)entry->key.ptr;
-		if (e->kind != Entity_Procedure) {
-			continue;
-		}
-		check_procedure_overloading(c, e);
-	}
 }
 
 

+ 4 - 4
src/entity.cpp

@@ -10,7 +10,7 @@ struct DeclInfo;
 	ENTITY_KIND(Variable) \
 	ENTITY_KIND(TypeName) \
 	ENTITY_KIND(Procedure) \
-	ENTITY_KIND(ProcedureGrouping) \
+	ENTITY_KIND(ProcGroup) \
 	ENTITY_KIND(Builtin) \
 	ENTITY_KIND(Alias) \
 	ENTITY_KIND(ImportName) \
@@ -110,7 +110,7 @@ struct Entity {
 		} Procedure;
 		struct {
 			Array<Entity *> entities;
-		} ProcedureGrouping;
+		} ProcGroup;
 		struct {
 			i32 id;
 		} Builtin;
@@ -248,8 +248,8 @@ Entity *make_entity_procedure(gbAllocator a, Scope *scope, Token token, Type *si
 	return entity;
 }
 
-Entity *make_entity_procedure_grouping(gbAllocator a, Scope *scope, Token token, Type *type) {
-	Entity *entity = alloc_entity(a, Entity_ProcedureGrouping, scope, token, type);
+Entity *make_entity_proc_group(gbAllocator a, Scope *scope, Token token, Type *type) {
+	Entity *entity = alloc_entity(a, Entity_ProcGroup, scope, token, type);
 	return entity;
 }
 

+ 11 - 10
src/ir.cpp

@@ -3620,7 +3620,7 @@ String ir_mangle_name(irGen *s, String path, Entity *e) {
 	isize base_len = ext-1-base;
 
 	isize max_len = base_len + 1 + 1 + 10 + 1 + name.len;
-	bool require_suffix_id = check_is_entity_overloaded(e) || is_type_polymorphic(e->type);
+	bool require_suffix_id = is_type_polymorphic(e->type);
 	if (require_suffix_id) {
 		max_len += 21;
 	}
@@ -8304,19 +8304,22 @@ void ir_gen_tree(irGen *s) {
 	}
 
 	for_array(i, info->entities.entries) {
-		auto *entry = &info->entities.entries[i];
-		Entity *e = cast(Entity *)entry->key.ptr;
-		String name = e->token.string;
-		DeclInfo *decl = entry->value;
-		Scope *scope = e->scope;
+		auto *    entry = &info->entities.entries[i];
+		Entity *  e     = cast(Entity *)entry->key.ptr;
+		String    name  = e->token.string;
+		DeclInfo *decl  = entry->value;
+		Scope *   scope = e->scope;
 
 		if (!scope->is_file) {
 			continue;
 		}
 
-		if (e->kind == Entity_Variable || e->kind == Entity_ProcedureGrouping) {
+		switch (e->kind) {
+		case Entity_Variable:
 			// NOTE(bill): Handled above as it requires a specific load order
 			continue;
+		case Entity_ProcGroup:
+			continue;
 		}
 
 		bool polymorphic_struct = false;
@@ -8341,8 +8344,6 @@ void ir_gen_tree(irGen *s) {
 			} else {
 				name = ir_mangle_name(s, e->token.pos.file, e);
 			}
-		} else if (check_is_entity_overloaded(e)) {
-			name = ir_mangle_name(s, e->token.pos.file, e);
 		}
 		ir_add_entity_name(m, e, name);
 
@@ -8373,7 +8374,7 @@ void ir_gen_tree(irGen *s) {
 			ir_module_add_value(m, e, p);
 			HashKey hash_name = hash_string(name);
 			if (map_get(&m->members, hash_name) == nullptr) {
-				multi_map_insert(&m->members, hash_name, p);
+				map_set(&m->members, hash_name, p);
 			}
 			break;
 		}

+ 0 - 1
src/main.cpp

@@ -1,5 +1,4 @@
 #define ALLOW_ARRAY_PROGRAMMING
-// #define DISABLE_PROCEDURE_OVERLOADING
 // #define NO_ARRAY_BOUNDS_CHECK
 
 

+ 5 - 2
src/map.cpp

@@ -2,6 +2,8 @@
 // with the use of the `multi_*` procedures.
 // TODO(bill): I should probably allow the `multi_map_*` stuff to be #ifdefed out
 
+#define MAP_ENABLE_MULTI_MAP 1
+
 #ifndef MAP_UTIL_STUFF
 #define MAP_UTIL_STUFF
 // NOTE(bill): This util stuff is the same for every `Map`
@@ -110,6 +112,7 @@ template <typename T> void map_clear            (Map<T> *h);
 template <typename T> void map_grow             (Map<T> *h);
 template <typename T> void map_rehash           (Map<T> *h, isize new_count);
 
+#if MAP_ENABLE_MULTI_MAP
 // Mutlivalued map procedure
 template <typename T> MapEntry<T> * multi_map_find_first(Map<T> *h, HashKey key);
 template <typename T> MapEntry<T> * multi_map_find_next (Map<T> *h, MapEntry<T> *e);
@@ -119,7 +122,7 @@ template <typename T> void  multi_map_get_all   (Map<T> *h, HashKey key, T *item
 template <typename T> void  multi_map_insert    (Map<T> *h, HashKey key, T const &value);
 template <typename T> void  multi_map_remove    (Map<T> *h, HashKey key, MapEntry<T> *e);
 template <typename T> void  multi_map_remove_all(Map<T> *h, HashKey key);
-
+#endif
 
 template <typename T>
 gb_inline void map_init(Map<T> *h, gbAllocator a, isize capacity) {
@@ -291,7 +294,7 @@ gb_inline void map_clear(Map<T> *h) {
 }
 
 
-#if 1
+#if MAP_ENABLE_MULTI_MAP
 template <typename T>
 MapEntry<T> *multi_map_find_first(Map<T> *h, HashKey key) {
 	isize i = map__find(h, key).entry_index;

+ 14 - 14
src/parser.cpp

@@ -164,7 +164,7 @@ Array<AstNode *> make_ast_node_array(AstFile *f, isize init_capacity = 8) {
 		Token token; \
 		AstNode *expr; \
 	}) \
-	AST_NODE_KIND(ProcGrouping, "procedure grouping", struct { \
+	AST_NODE_KIND(ProcGroup, "procedure group", struct { \
 		Token token; \
 		Token open;  \
 		Token close; \
@@ -540,7 +540,7 @@ Token ast_node_token(AstNode *node) {
 	case AstNode_Undef:          return node->Undef;
 	case AstNode_BasicLit:       return node->BasicLit;
 	case AstNode_BasicDirective: return node->BasicDirective.token;
-	case AstNode_ProcGrouping:   return node->ProcGrouping.token;
+	case AstNode_ProcGroup:      return node->ProcGroup.token;
 	case AstNode_ProcLit:        return ast_node_token(node->ProcLit.type);
 	case AstNode_CompoundLit:
 		if (node->CompoundLit.type != nullptr) {
@@ -669,8 +669,8 @@ AstNode *clone_ast_node(gbAllocator a, AstNode *node) {
 	case AstNode_Ellipsis:
 		n->Ellipsis.expr = clone_ast_node(a, n->Ellipsis.expr);
 		break;
-	case AstNode_ProcGrouping:
-		n->ProcGrouping.args = clone_ast_node_array(a, n->ProcGrouping.args);
+	case AstNode_ProcGroup:
+		n->ProcGroup.args = clone_ast_node_array(a, n->ProcGroup.args);
 		break;
 	case AstNode_ProcLit:
 		n->ProcLit.type = clone_ast_node(a, n->ProcLit.type);
@@ -1121,12 +1121,12 @@ AstNode *ast_ellipsis(AstFile *f, Token token, AstNode *expr) {
 }
 
 
-AstNode *ast_proc_grouping(AstFile *f, Token token, Token open, Token close, Array<AstNode *> args) {
-	AstNode *result = make_ast_node(f, AstNode_ProcGrouping);
-	result->ProcGrouping.token = token;
-	result->ProcGrouping.open  = open;
-	result->ProcGrouping.close = close;
-	result->ProcGrouping.args = args;
+AstNode *ast_proc_group(AstFile *f, Token token, Token open, Token close, Array<AstNode *> args) {
+	AstNode *result = make_ast_node(f, AstNode_ProcGroup);
+	result->ProcGroup.token = token;
+	result->ProcGroup.open  = open;
+	result->ProcGroup.close = close;
+	result->ProcGroup.args = args;
 	return result;
 }
 
@@ -2266,11 +2266,11 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
 		return expr;
 	} break;
 
-	// Parse Procedure Type or Literal or Grouping
+	// Parse Procedure Type or Literal or Group
 	case Token_proc: {
 		Token token = expect_token(f, Token_proc);
 
-		if (f->curr_token.kind == Token_OpenBracket) { // ProcGrouping
+		if (f->curr_token.kind == Token_OpenBracket) { // ProcGroup
 			Token open = expect_token(f, Token_OpenBracket);
 
 			Array<AstNode *> args = {};
@@ -2289,10 +2289,10 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
 			Token close = expect_token(f, Token_CloseBracket);
 
 			if (args.count == 0) {
-				syntax_error(token, "Expected a least 1 argument in a procedure grouping");
+				syntax_error(token, "Expected a least 1 argument in a procedure group");
 			}
 
-			return ast_proc_grouping(f, token, open, close, args);
+			return ast_proc_group(f, token, open, close, args);
 		}
 
 		AstNode *type = parse_proc_type(f, token);