|
@@ -14,8 +14,28 @@ enum CallArgumentError {
|
|
|
CallArgumentError_ParameterMissing,
|
|
|
CallArgumentError_DuplicateParameter,
|
|
|
CallArgumentError_NoneConstantParameter,
|
|
|
+
|
|
|
+ CallArgumentError_MAX,
|
|
|
+};
|
|
|
+char const *CallArgumentError_strings[CallArgumentError_MAX] = {
|
|
|
+ "None",
|
|
|
+ "NoneProcedureType",
|
|
|
+ "WrongTypes",
|
|
|
+ "NonVariadicExpand",
|
|
|
+ "VariadicTuple",
|
|
|
+ "MultipleVariadicExpand",
|
|
|
+ "AmbiguousPolymorphicVariadic",
|
|
|
+ "ArgumentCount",
|
|
|
+ "TooFewArguments",
|
|
|
+ "TooManyArguments",
|
|
|
+ "InvalidFieldValue",
|
|
|
+ "ParameterNotFound",
|
|
|
+ "ParameterMissing",
|
|
|
+ "DuplicateParameter",
|
|
|
+ "NoneConstantParameter",
|
|
|
};
|
|
|
|
|
|
+
|
|
|
enum CallArgumentErrorMode {
|
|
|
CallArgumentMode_NoErrors,
|
|
|
CallArgumentMode_ShowErrors,
|
|
@@ -25,6 +45,7 @@ struct CallArgumentData {
|
|
|
Entity *gen_entity;
|
|
|
i64 score;
|
|
|
Type * result_type;
|
|
|
+ Type * proc_type;
|
|
|
};
|
|
|
|
|
|
struct PolyProcData {
|
|
@@ -243,7 +264,6 @@ bool find_or_generate_polymorphic_procedure(CheckerContext *c, Entity *base_enti
|
|
|
}
|
|
|
|
|
|
|
|
|
-
|
|
|
gbAllocator a = heap_allocator();
|
|
|
|
|
|
Array<Operand> operands = {};
|
|
@@ -344,7 +364,6 @@ bool find_or_generate_polymorphic_procedure(CheckerContext *c, Entity *base_enti
|
|
|
}
|
|
|
|
|
|
|
|
|
-
|
|
|
Ast *proc_lit = clone_ast(old_decl->proc_lit);
|
|
|
ast_node(pl, ProcLit, proc_lit);
|
|
|
// NOTE(bill): Associate the scope declared above withinth this procedure declaration's type
|
|
@@ -6993,8 +7012,14 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type
|
|
|
|
|
|
CallArgumentData data = {};
|
|
|
CallArgumentError err = call_checker(c, call, e->type, e, operands, CallArgumentMode_ShowErrors, &data);
|
|
|
+ if (err != CallArgumentError_None) {
|
|
|
+ // handle error
|
|
|
+ }
|
|
|
Entity *entity_to_use = data.gen_entity != nullptr ? data.gen_entity : e;
|
|
|
- add_entity_use(c, ident, entity_to_use);
|
|
|
+ if (entity_to_use != nullptr) {
|
|
|
+ add_entity_use(c, ident, entity_to_use);
|
|
|
+ data.proc_type = entity_to_use->type;
|
|
|
+ }
|
|
|
|
|
|
return data;
|
|
|
}
|
|
@@ -7070,6 +7095,13 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type
|
|
|
auto valids = array_make<ValidIndexAndScore>(heap_allocator(), 0, procs.count);
|
|
|
defer (array_free(&valids));
|
|
|
|
|
|
+ auto proc_entities = array_make<Entity *>(heap_allocator(), 0, procs.count*2);
|
|
|
+ defer (array_free(&proc_entities));
|
|
|
+ for_array(i, procs) {
|
|
|
+ array_add(&proc_entities, procs[i]);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
gbString expr_name = expr_to_string(operand->expr);
|
|
|
defer (gb_string_free(expr_name));
|
|
|
|
|
@@ -7086,10 +7118,10 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type
|
|
|
ctx.hide_polymorphic_errors = true;
|
|
|
|
|
|
err = call_checker(&ctx, call, pt, p, operands, CallArgumentMode_NoErrors, &data);
|
|
|
-
|
|
|
if (err != CallArgumentError_None) {
|
|
|
continue;
|
|
|
}
|
|
|
+ isize index = i;
|
|
|
|
|
|
if (data.gen_entity != nullptr) {
|
|
|
Entity *e = data.gen_entity;
|
|
@@ -7104,10 +7136,13 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type
|
|
|
if (!evaluate_where_clauses(&ctx, call, decl->scope, &decl->proc_lit->ProcLit.where_clauses, false)) {
|
|
|
continue;
|
|
|
}
|
|
|
+
|
|
|
+ array_add(&proc_entities, data.gen_entity);
|
|
|
+ index = proc_entities.count-1;
|
|
|
}
|
|
|
|
|
|
ValidIndexAndScore item = {};
|
|
|
- item.index = i;
|
|
|
+ item.index = index;
|
|
|
item.score = data.score;
|
|
|
array_add(&valids, item);
|
|
|
}
|
|
@@ -7116,13 +7151,13 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type
|
|
|
if (valids.count > 1) {
|
|
|
gb_sort_array(valids.data, valids.count, valid_index_and_score_cmp);
|
|
|
i64 best_score = valids[0].score;
|
|
|
- Entity *best_entity = procs[valids[0].index];
|
|
|
+ Entity *best_entity = proc_entities[valids[0].index];
|
|
|
for (isize i = 1; i < valids.count; i++) {
|
|
|
if (best_score > valids[i].score) {
|
|
|
valids.count = i;
|
|
|
break;
|
|
|
}
|
|
|
- if (best_entity == procs[valids[i].index]) {
|
|
|
+ if (best_entity == proc_entities[valids[i].index]) {
|
|
|
valids.count = i;
|
|
|
break;
|
|
|
}
|
|
@@ -7200,7 +7235,7 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type
|
|
|
error_line(")\n");
|
|
|
|
|
|
for (isize i = 0; i < valids.count; i++) {
|
|
|
- Entity *proc = procs[valids[i].index];
|
|
|
+ Entity *proc = proc_entities[valids[i].index];
|
|
|
TokenPos pos = proc->token.pos;
|
|
|
Type *t = base_type(proc->type); GB_ASSERT(t->kind == Type_Proc);
|
|
|
gbString pt = nullptr;
|
|
@@ -7248,13 +7283,16 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type
|
|
|
ident = s;
|
|
|
}
|
|
|
|
|
|
- Entity *e = procs[valids[0].index];
|
|
|
+ Entity *e = proc_entities[valids[0].index];
|
|
|
|
|
|
proc_type = e->type;
|
|
|
CallArgumentData data = {};
|
|
|
CallArgumentError err = call_checker(c, call, proc_type, e, operands, CallArgumentMode_ShowErrors, &data);
|
|
|
Entity *entity_to_use = data.gen_entity != nullptr ? data.gen_entity : e;
|
|
|
- add_entity_use(c, ident, entity_to_use);
|
|
|
+ if (entity_to_use != nullptr) {
|
|
|
+ add_entity_use(c, ident, entity_to_use);
|
|
|
+ data.proc_type = entity_to_use->type;
|
|
|
+ }
|
|
|
|
|
|
if (data.gen_entity != nullptr) {
|
|
|
Entity *e = data.gen_entity;
|
|
@@ -7285,7 +7323,10 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type
|
|
|
CallArgumentData data = {};
|
|
|
CallArgumentError err = call_checker(c, call, proc_type, e, operands, CallArgumentMode_ShowErrors, &data);
|
|
|
Entity *entity_to_use = data.gen_entity != nullptr ? data.gen_entity : e;
|
|
|
- add_entity_use(c, ident, entity_to_use);
|
|
|
+ if (entity_to_use != nullptr) {
|
|
|
+ add_entity_use(c, ident, entity_to_use);
|
|
|
+ data.proc_type = entity_to_use->type;
|
|
|
+ }
|
|
|
|
|
|
if (data.gen_entity != nullptr) {
|
|
|
Entity *e = data.gen_entity;
|
|
@@ -7789,6 +7830,10 @@ ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *call, Ast *pr
|
|
|
}
|
|
|
|
|
|
Type *pt = base_type(proc_type);
|
|
|
+ if (data.proc_type != nullptr) {
|
|
|
+ pt = base_type(data.proc_type);
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
if (pt->kind == Type_Proc && pt->Proc.calling_convention == ProcCC_Odin) {
|
|
|
if ((c->scope->flags & ScopeFlag_ContextDefined) == 0) {
|
|
@@ -7852,6 +7897,8 @@ ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *call, Ast *pr
|
|
|
operand->mode = Addressing_OptionalOk;
|
|
|
}
|
|
|
|
|
|
+ add_type_and_value(c->info, operand->expr, operand->mode, operand->type, operand->value);
|
|
|
+
|
|
|
return Expr_Expr;
|
|
|
}
|
|
|
|