mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 15:18:49 +00:00
Fix procedure group "best fit" algorithm for polymorphic procedures
This commit is contained in:
@@ -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
@@ -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);
|
auto valids = array_make<ValidIndexAndScore>(heap_allocator(), 0, procs.count);
|
||||||
isize valid_count = 0;
|
defer (array_free(&valids));
|
||||||
defer (gb_free(heap_allocator(), 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;
|
ValidIndexAndScore item = {};
|
||||||
valids[valid_count].score = data.score;
|
item.index = i;
|
||||||
valid_count++;
|
item.score = data.score;
|
||||||
|
array_add(&valids, item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (valid_count > 1) {
|
if (valids.count > 1) {
|
||||||
gb_sort_array(valids, valid_count, valid_index_and_score_cmp);
|
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
@@ -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));
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user