Improve procedure group selection based on the minimum number of arguments

This commit is contained in:
gingerBill
2022-03-18 22:18:12 +00:00
parent df233f72a9
commit a68f0b2d72
5 changed files with 82 additions and 31 deletions

View File

@@ -4872,25 +4872,16 @@ bool is_expr_constant_zero(Ast *expr) {
return false;
}
CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
ast_node(ce, CallExpr, call);
GB_ASSERT(is_type_proc(proc_type));
proc_type = base_type(proc_type);
TypeProc *pt = &proc_type->Proc;
isize get_procedure_param_count_excluding_defaults(Type *pt, isize *param_count_) {
GB_ASSERT(pt != nullptr);
GB_ASSERT(pt->kind == Type_Proc);
isize param_count = 0;
isize param_count_excluding_defaults = 0;
bool variadic = pt->variadic;
bool vari_expand = (ce->ellipsis.pos.line != 0);
i64 score = 0;
bool show_error = show_error_mode == CallArgumentMode_ShowErrors;
bool variadic = pt->Proc.variadic;
TypeTuple *param_tuple = nullptr;
if (pt->params != nullptr) {
param_tuple = &pt->params->Tuple;
if (pt->Proc.params != nullptr) {
param_tuple = &pt->Proc.params->Tuple;
param_count = param_tuple->variables.count;
if (variadic) {
@@ -4930,6 +4921,31 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
}
}
if (param_count_) *param_count_ = param_count;
return param_count_excluding_defaults;
}
CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
ast_node(ce, CallExpr, call);
GB_ASSERT(is_type_proc(proc_type));
proc_type = base_type(proc_type);
TypeProc *pt = &proc_type->Proc;
isize param_count = 0;
isize param_count_excluding_defaults = get_procedure_param_count_excluding_defaults(proc_type, &param_count);
bool variadic = pt->variadic;
bool vari_expand = (ce->ellipsis.pos.line != 0);
i64 score = 0;
bool show_error = show_error_mode == CallArgumentMode_ShowErrors;
TypeTuple *param_tuple = nullptr;
if (pt->params != nullptr) {
param_tuple = &pt->params->Tuple;
}
CallArgumentError err = CallArgumentError_None;
Type *final_proc_type = proc_type;
Entity *gen_entity = nullptr;
@@ -5602,7 +5618,37 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type
if (operand->mode == Addressing_ProcGroup) {
check_entity_decl(c, operand->proc_group, nullptr, nullptr);
Array<Entity *> procs = proc_group_entities(c, *operand);
auto procs = proc_group_entities_cloned(c, *operand);
if (procs.count > 1) {
isize max_arg_count = args.count;
for_array(i, args) {
// NOTE(bill): The only thing that may have multiple values
// will be a call expression (assuming `or_return` and `()` will be stripped)
Ast *arg = strip_or_return_expr(args[i]);
if (arg && arg->kind == Ast_CallExpr) {
max_arg_count = ISIZE_MAX;
break;
}
}
for (isize proc_index = 0; proc_index < procs.count; /**/) {
Entity *proc = procs[proc_index];
Type *pt = base_type(proc->type);
if (!(pt != nullptr && is_type_proc(pt))) {
continue;
}
isize param_count = 0;
isize param_count_excluding_defaults = get_procedure_param_count_excluding_defaults(pt, &param_count);
if (param_count_excluding_defaults > max_arg_count) {
array_unordered_remove(&procs, proc_index);
} else {
proc_index++;
}
}
}
if (procs.count == 1) {
Ast *ident = operand->expr;
@@ -5632,6 +5678,7 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type
return data;
}
Entity **lhs = nullptr;
isize lhs_count = -1;

View File

@@ -1960,20 +1960,6 @@ bool check_procedure_type(CheckerContext *ctx, Type *type, Ast *proc_type_node,
if (params) param_count = params ->Tuple.variables.count;
if (results) result_count = results->Tuple.variables.count;
if (param_count > 0) {
for_array(i, params->Tuple.variables) {
Entity *param = params->Tuple.variables[i];
if (param->kind == Entity_Variable) {
ParameterValue pv = param->Variable.param_value;
if (pv.kind == ParameterValue_Constant &&
pv.value.kind == ExactValue_Procedure) {
type->Proc.has_proc_default_values = true;
break;
}
}
}
}
if (result_count > 0) {
Entity *first = results->Tuple.variables[0];
type->Proc.has_named_results = first->token.string != "";

View File

@@ -2657,6 +2657,15 @@ Array<Entity *> proc_group_entities(CheckerContext *c, Operand o) {
return procs;
}
Array<Entity *> proc_group_entities_cloned(CheckerContext *c, Operand o) {
auto entities = proc_group_entities(c, o);
if (entities.count == 0) {
return {};
}
return array_clone(permanent_allocator(), entities);
}
void init_core_type_info(Checker *c) {

View File

@@ -115,6 +115,16 @@ struct ParameterValue {
};
};
bool has_parameter_value(ParameterValue const &param_value) {
if (param_value.kind != ParameterValue_Invalid) {
return true;
}
if (param_value.original_ast_expr != nullptr) {
return true;
}
return false;
}
enum EntityConstantFlags : u32 {
EntityConstantFlag_ImplicitEnumValue = 1<<0,
};

View File

@@ -186,7 +186,6 @@ struct TypeProc {
bool c_vararg;
bool is_polymorphic;
bool is_poly_specialized;
bool has_proc_default_values;
bool has_named_results;
bool diverging; // no return
bool return_by_pointer;