Browse Source

Fix procedure group "best fit" algorithm for polymorphic procedures

gingerBill 5 years ago
parent
commit
416ff149bd
4 changed files with 47 additions and 22 deletions
  1. 24 3
      core/math/linalg/linalg.odin
  2. 18 16
      src/check_expr.cpp
  3. 4 3
      src/check_type.cpp
  4. 1 0
      src/checker.hpp

+ 24 - 3
core/math/linalg/linalg.odin

@@ -70,7 +70,7 @@ identity :: proc($T: typeid/[$N][N]$E) -> (m: T) {
 	return m;
 	return m;
 }
 }
 
 
-transpose :: proc(a: $T/[$N][$M]$E) -> (m: ((M == N) ? T : [M][N]E)) {
+transpose :: proc(a: $T/[$N][$M]$E) -> (m: [M][N]E) {
 	for j in 0..<M {
 	for j in 0..<M {
 		for i in 0..<N {
 		for i in 0..<N {
 			m[j][i] = a[i][j];
 			m[j][i] = a[i][j];
@@ -79,9 +79,23 @@ transpose :: proc(a: $T/[$N][$M]$E) -> (m: ((M == N) ? T : [M][N]E)) {
 	return;
 	return;
 }
 }
 
 
-mul_matrix :: proc(a: $A/[$I][$J]$E, b: $B/[J][$K]E) -> (c: ((I == J && J == K && A == B) ? A : [I][K]E))
+mul_matrix :: proc(a, b: $M/[$N][N]$E) -> (c: M)
 	where !intrinsics.type_is_array(E),
 	where !intrinsics.type_is_array(E),
 	      intrinsics.type_is_numeric(E) {
 	      intrinsics.type_is_numeric(E) {
+	for i in 0..<N {
+		for k in 0..<N {
+			for j in 0..<N {
+				c[i][k] += a[i][j] * b[j][k];
+			}
+		}
+	}
+	return;
+}
+
+mul_matrix_differ :: proc(a: $A/[$I][$J]$E, b: $B/[J][$K]E) -> (c: [I][K]E)
+	where !intrinsics.type_is_array(E),
+	      intrinsics.type_is_numeric(E),
+	      I != J {
 	for i in 0..<I {
 	for i in 0..<I {
 		for k in 0..<K {
 		for k in 0..<K {
 			for j in 0..<J {
 			for j in 0..<J {
@@ -92,6 +106,7 @@ mul_matrix :: proc(a: $A/[$I][$J]$E, b: $B/[J][$K]E) -> (c: ((I == J && J == K &
 	return;
 	return;
 }
 }
 
 
+
 mul_matrix_vector :: proc(a: $A/[$I][$J]$E, b: $B/[I]E) -> (c: B)
 mul_matrix_vector :: proc(a: $A/[$I][$J]$E, b: $B/[I]E) -> (c: B)
 	where !intrinsics.type_is_array(E),
 	where !intrinsics.type_is_array(E),
 	      intrinsics.type_is_numeric(E) {
 	      intrinsics.type_is_numeric(E) {
@@ -124,7 +139,13 @@ mul_quaternion256_vector3 :: proc(q: $Q/quaternion256, v: $V/[3]$F/f64) -> V {
 }
 }
 mul_quaternion_vector3 :: proc{mul_quaternion128_vector3, mul_quaternion256_vector3};
 mul_quaternion_vector3 :: proc{mul_quaternion128_vector3, mul_quaternion256_vector3};
 
 
-mul :: proc{mul_matrix, mul_matrix_vector, mul_quaternion128_vector3, mul_quaternion256_vector3};
+mul :: proc{
+	mul_matrix,
+	mul_matrix_differ,
+	mul_matrix_vector,
+	mul_quaternion128_vector3,
+	mul_quaternion256_vector3,
+};
 
 
 
 
 // Specific
 // Specific

+ 18 - 16
src/check_expr.cpp

@@ -5855,6 +5855,7 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type
 			}
 			}
 
 
 
 
+
 			if (proc_arg_count >= 0 && proc_arg_count_all_equal) {
 			if (proc_arg_count >= 0 && proc_arg_count_all_equal) {
 				lhs_count = proc_arg_count;
 				lhs_count = proc_arg_count;
 				if (lhs_count > 0)  {
 				if (lhs_count > 0)  {
@@ -5898,9 +5899,8 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type
 			gb_free(heap_allocator(), lhs);
 			gb_free(heap_allocator(), lhs);
 		}
 		}
 
 
-		ValidIndexAndScore *valids         = gb_alloc_array(heap_allocator(), ValidIndexAndScore, procs.count);
-		isize               valid_count    = 0;
-		defer (gb_free(heap_allocator(), valids));
+		auto valids = array_make<ValidIndexAndScore>(heap_allocator(), 0, procs.count);
+		defer (array_free(&valids));
 
 
 		gbString expr_name = expr_to_string(operand->expr);
 		gbString expr_name = expr_to_string(operand->expr);
 		defer (gb_string_free(expr_name));
 		defer (gb_string_free(expr_name));
@@ -5915,12 +5915,14 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type
 
 
 				ctx.no_polymorphic_errors = true;
 				ctx.no_polymorphic_errors = true;
 				ctx.allow_polymorphic_types = is_type_polymorphic(pt);
 				ctx.allow_polymorphic_types = is_type_polymorphic(pt);
+				ctx.hide_polymorphic_errors = true;
 
 
 				err = call_checker(&ctx, call, pt, p, operands, CallArgumentMode_NoErrors, &data);
 				err = call_checker(&ctx, call, pt, p, operands, CallArgumentMode_NoErrors, &data);
 
 
 				if (err != CallArgumentError_None) {
 				if (err != CallArgumentError_None) {
 					continue;
 					continue;
 				}
 				}
+
 				if (data.gen_entity != nullptr) {
 				if (data.gen_entity != nullptr) {
 					Entity *e = data.gen_entity;
 					Entity *e = data.gen_entity;
 					DeclInfo *decl = data.gen_entity->decl_info;
 					DeclInfo *decl = data.gen_entity->decl_info;
@@ -5936,31 +5938,31 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type
 					}
 					}
 				}
 				}
 
 
-				valids[valid_count].index = i;
-				valids[valid_count].score = data.score;
-				valid_count++;
+				ValidIndexAndScore item = {};
+				item.index = i;
+				item.score = data.score;
+				array_add(&valids, item);
 			}
 			}
 		}
 		}
 
 
-		if (valid_count > 1) {
-			gb_sort_array(valids, valid_count, valid_index_and_score_cmp);
+		if (valids.count > 1) {
+			gb_sort_array(valids.data, valids.count, valid_index_and_score_cmp);
 			i64 best_score = valids[0].score;
 			i64 best_score = valids[0].score;
 			Entity *best_entity = procs[valids[0].index];
 			Entity *best_entity = procs[valids[0].index];
-			for (isize i = 1; i < valid_count; i++) {
+			for (isize i = 1; i < valids.count; i++) {
 				if (best_score > valids[i].score) {
 				if (best_score > valids[i].score) {
-					valid_count = i;
+					valids.count = i;
 					break;
 					break;
 				}
 				}
 				if (best_entity == procs[valids[i].index]) {
 				if (best_entity == procs[valids[i].index]) {
-					valid_count = i;
+					valids.count = i;
 					break;
 					break;
 				}
 				}
-				best_score = valids[i].score;
 			}
 			}
 		}
 		}
 
 
 
 
-		if (valid_count == 0) {
+		if (valids.count == 0) {
 			begin_error_block();
 			begin_error_block();
 			defer (end_error_block());
 			defer (end_error_block());
 
 
@@ -6015,7 +6017,7 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type
 			}
 			}
 
 
 			result_type = t_invalid;
 			result_type = t_invalid;
-		} else if (valid_count > 1) {
+		} else if (valids.count > 1) {
 			begin_error_block();
 			begin_error_block();
 			defer (end_error_block());
 			defer (end_error_block());
 
 
@@ -6030,11 +6032,11 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type
 			}
 			}
 			error_line(")\n");
 			error_line(")\n");
 
 
-			for (isize i = 0; i < valid_count; i++) {
+			for (isize i = 0; i < valids.count; i++) {
 				Entity *proc = procs[valids[i].index];
 				Entity *proc = procs[valids[i].index];
 				TokenPos pos = proc->token.pos;
 				TokenPos pos = proc->token.pos;
 				Type *t = base_type(proc->type); GB_ASSERT(t->kind == Type_Proc);
 				Type *t = base_type(proc->type); GB_ASSERT(t->kind == Type_Proc);
-				gbString pt;
+				gbString pt = nullptr;
 				defer (gb_string_free(pt));
 				defer (gb_string_free(pt));
 				if (t->Proc.node != nullptr) {
 				if (t->Proc.node != nullptr) {
 					pt = expr_to_string(t->Proc.node);
 					pt = expr_to_string(t->Proc.node);

+ 4 - 3
src/check_type.cpp

@@ -1263,20 +1263,21 @@ bool check_type_specialization_to(CheckerContext *ctx, Type *specialization, Typ
 
 
 Type *determine_type_from_polymorphic(CheckerContext *ctx, Type *poly_type, Operand operand) {
 Type *determine_type_from_polymorphic(CheckerContext *ctx, Type *poly_type, Operand operand) {
 	bool modify_type = !ctx->no_polymorphic_errors;
 	bool modify_type = !ctx->no_polymorphic_errors;
+	bool show_error = modify_type && !ctx->hide_polymorphic_errors;
 	if (!is_operand_value(operand)) {
 	if (!is_operand_value(operand)) {
-		if (modify_type) {
+		if (show_error) {
 			error(operand.expr, "Cannot determine polymorphic type from parameter");
 			error(operand.expr, "Cannot determine polymorphic type from parameter");
 		}
 		}
 		return t_invalid;
 		return t_invalid;
 	}
 	}
 
 
 	if (is_polymorphic_type_assignable(ctx, poly_type, operand.type, false, modify_type)) {
 	if (is_polymorphic_type_assignable(ctx, poly_type, operand.type, false, modify_type)) {
-		if (modify_type) {
+		if (show_error) {
 			set_procedure_abi_types(ctx, poly_type);
 			set_procedure_abi_types(ctx, poly_type);
 		}
 		}
 		return poly_type;
 		return poly_type;
 	}
 	}
-	if (modify_type) {
+	if (show_error) {
 		gbString pts = type_to_string(poly_type);
 		gbString pts = type_to_string(poly_type);
 		gbString ots = type_to_string(operand.type);
 		gbString ots = type_to_string(operand.type);
 		defer (gb_string_free(pts));
 		defer (gb_string_free(pts));

+ 1 - 0
src/checker.hpp

@@ -285,6 +285,7 @@ struct CheckerContext {
 	bool       collect_delayed_decls;
 	bool       collect_delayed_decls;
 	bool       allow_polymorphic_types;
 	bool       allow_polymorphic_types;
 	bool       no_polymorphic_errors;
 	bool       no_polymorphic_errors;
+	bool       hide_polymorphic_errors;
 	bool       in_polymorphic_specialization;
 	bool       in_polymorphic_specialization;
 	Scope *    polymorphic_scope;
 	Scope *    polymorphic_scope;
 };
 };