overload = (AstFunction *) *node;
}
else if ((*node)->kind == Ast_Kind_Polymorphic_Proc) {
- overload = polymorphic_proc_build_only_header((AstPolyProc *) *node, PPLM_By_Value_Array, arg_arr);
+ Arguments args;
+ args.values = (bh_arr(AstNode*)) arg_arr;
+ args.named_values = named_values;
+
+ overload = polymorphic_proc_build_only_header((AstPolyProc *) *node, PPLM_By_Arguments, &args);
}
if (overload == NULL) continue;
if (named_values != NULL && bh_arr_length(named_values) > 0) {
new_arg_arr = NULL;
bh_arr_new(global_heap_allocator, new_arg_arr, bh_arr_length(arg_arr) + bh_arr_length(named_values));
- fori (i, 0, bh_arr_length(arg_arr))
- new_arg_arr[i] = arg_arr[i];
+ fori (i, 0, bh_arr_length(arg_arr)) new_arg_arr[i] = arg_arr[i];
+ fori (i, 0, bh_arr_length(named_values)) new_arg_arr[i + bh_arr_length(arg_arr)] = NULL;
+ bh_arr_set_length(new_arg_arr, bh_arr_length(arg_arr) + bh_arr_length(named_values));
b32 values_place_correctly = fill_in_arguments(
(bh_arr(AstNode *)) new_arg_arr,
return (AstTyped *) *node;
no_match:
- if (named_values != NULL)
+ if (named_values != NULL && bh_arr_length(named_values) > 0)
bh_arr_free(new_arg_arr);
continue;
return NULL;
}
+static void report_unable_to_match_overload(AstCall* call) {
+ char* arg_str = bh_alloc(global_scratch_allocator, 1024);
+ arg_str[0] = '\0';
+
+ bh_arr_each(AstArgument *, arg, call->arg_arr) {
+ strncat(arg_str, type_get_name((*arg)->value->type), 1023);
+
+ if (arg != &bh_arr_last(call->arg_arr))
+ strncat(arg_str, ", ", 1023);
+ }
+
+ if (bh_arr_length(call->named_args) > 0) {
+ bh_arr_each(AstNamedValue *, named_value, call->named_args) {
+ token_toggle_end((*named_value)->token);
+ strncat(arg_str, (*named_value)->token->text, 1023);
+ token_toggle_end((*named_value)->token);
+
+ strncat(arg_str, "=", 1023);
+ strncat(arg_str, type_get_name(((AstTyped *) (*named_value)->value)->type), 1023); // CHECK: this might say 'unknown'.
+
+ if (named_value != &bh_arr_last(call->named_args))
+ strncat(arg_str, ", ", 1023);
+ }
+ }
+
+ onyx_report_error(call->token->pos, "unable to match overloaded function with provided argument types: (%s)", arg_str);
+
+ bh_free(global_scratch_allocator, arg_str);
+}
+
+
CheckStatus check_argument(AstArgument** parg) {
CHECK(expression, (AstTyped **) parg);
(*parg)->type = (*parg)->value->type;
((AstOverloadedFunction *) callee)->overloads);
if (call->callee == NULL) {
- char* arg_str = bh_alloc(global_scratch_allocator, 1024);
- arg_str[0] = '\0';
-
- bh_arr_each(AstArgument *, arg, call->arg_arr) {
- strncat(arg_str, type_get_name((*arg)->value->type), 1023);
-
- if (arg != &bh_arr_last(call->arg_arr))
- strncat(arg_str, ", ", 1023);
- }
-
- if (bh_arr_length(call->named_args) > 0) {
- bh_arr_each(AstNamedValue *, named_value, call->named_args) {
- token_toggle_end((*named_value)->token);
- strncat(arg_str, (*named_value)->token->text, 1023);
- token_toggle_end((*named_value)->token);
-
- strncat(arg_str, "=", 1023);
- strncat(arg_str, type_get_name(((AstTyped *) (*named_value)->value)->type), 1023); // CHECK: this might say 'unknown'.
-
- if (named_value != &bh_arr_last(call->named_args))
- strncat(arg_str, ", ", 1023);
- }
- }
-
- onyx_report_error(call->token->pos, "unable to match overloaded function with provided argument types: (%s)", arg_str);
-
- bh_free(global_scratch_allocator, arg_str);
+ report_unable_to_match_overload(call);
return Check_Error;
}
return Check_Error;
}
- i32 arg_count = bh_max(
- bh_arr_length(call->arg_arr) + bh_arr_length(call->named_args),
- (i32) callee->type->Function.param_count);
-
- bh_arr_grow(call->arg_arr, arg_count);
- fori (i, bh_arr_length(call->arg_arr), arg_count) call->arg_arr[i] = NULL;
- bh_arr_set_length(call->arg_arr, arg_count);
{
+ i32 non_vararg_param_count = (i32) callee->type->Function.param_count;
+ if (non_vararg_param_count > 0 &&
+ callee->type->Function.params[callee->type->Function.param_count - 1] == builtin_vararg_type_type)
+ non_vararg_param_count--;
+
+ i32 arg_count = bh_max(
+ bh_arr_length(call->arg_arr) + bh_arr_length(call->named_args),
+ non_vararg_param_count);
+
+ bh_arr_grow(call->arg_arr, arg_count);
+ fori (i, bh_arr_length(call->arg_arr), arg_count) call->arg_arr[i] = NULL;
+ bh_arr_set_length(call->arg_arr, arg_count);
+
char* err_msg = NULL;
fill_in_arguments((AstNode **) call->arg_arr, call->named_args, (AstNode *) callee, &err_msg);
*arg = (AstTyped *) make_argument(semstate.node_allocator, *arg);
implicit_call->arg_arr = (AstArgument **) args;
+ implicit_call->named_args = NULL;
return implicit_call;
}
return result;
}
+static Type* lookup_actual_type_in_arguments(AstPolyProc* pp, AstPolyParam* param, Arguments* args, char** err_msg) {
+ bh_arr(AstNode *) arg_arr = args->values;
+ bh_arr(AstNamedValue *) named_values = args->named_values;
+
+ if (param->idx >= (u64) bh_arr_length(arg_arr)) {
+ OnyxToken* param_name = pp->base_func->params[param->idx].local->token;
+
+ bh_arr_each(AstNamedValue *, named_value, named_values) {
+ if (token_equals(param_name, (*named_value)->token)) {
+ return resolve_expression_type((AstTyped *) (*named_value)->value);
+ }
+ }
+
+ // nocheckin
+ if (err_msg) *err_msg = "Not enough arguments to polymorphic procedure. This error message may not be entirely right.";
+
+ } else {
+ return resolve_expression_type((AstTyped *) arg_arr[param->idx]);
+ }
+
+ return NULL;
+}
+
static bh_arr(AstPolySolution) find_polymorphic_slns(AstPolyProc* pp, PolyProcLookupMethod pp_lookup, ptr actual, char** err_msg) {
bh_arr(AstPolySolution) slns = NULL;
bh_arr_new(global_heap_allocator, slns, bh_arr_length(pp->poly_params));
}
if (already_solved) continue;
- Type* actual_type;
+ Type* actual_type = NULL;
if (pp_lookup == PPLM_By_Call) {
- bh_arr(AstArgument *) arg_arr = ((AstCall *) actual)->arg_arr;
- bh_arr(AstNamedValue *) named_values = ((AstCall *) actual)->named_args;
-
- if (param->idx >= (u64) bh_arr_length(arg_arr)) {
- // CLEANUP: This is a really long access chain.
- OnyxToken* param_name = pp->base_func->params[param->idx].local->token;
-
- bh_arr_each(AstNamedValue *, named_value, named_values) {
- if (token_equals(param_name, (*named_value)->token)) {
- actual_type = resolve_expression_type((AstTyped *) (*named_value)->value);
- break;
- }
- }
-
- // nocheckin
- if (err_msg) *err_msg = "Not enough arguments to polymorphic procedure. This error message may not be entirely right.";
- goto sln_not_found;
+ Arguments args;
+ args.values = (bh_arr(AstNode *)) ((AstCall *) actual)->arg_arr;
+ args.named_values = ((AstCall *) actual)->named_args;
- } else {
- actual_type = resolve_expression_type(arg_arr[param->idx]->value);
- }
+ actual_type = lookup_actual_type_in_arguments(pp, param, &args, err_msg);
+ if (actual_type == NULL) goto sln_not_found;
}
- else if (pp_lookup == PPLM_By_Value_Array) {
- bh_arr(AstTyped *) arg_arr = (bh_arr(AstTyped *)) actual;
+ else if (pp_lookup == PPLM_By_Arguments) {
+ Arguments* args = (Arguments *) actual;
- // nocheckin
- if ((i32) param->idx >= bh_arr_length(arg_arr)) {
- if (err_msg) *err_msg = "Not enough arguments to polymorphic procedure.";
- goto sln_not_found;
- }
-
- actual_type = resolve_expression_type(arg_arr[param->idx]);
+ actual_type = lookup_actual_type_in_arguments(pp, param, args, err_msg);
+ if (actual_type == NULL) goto sln_not_found;
}
else if (pp_lookup == PPLM_By_Function_Type) {
case Ast_Kind_Function: {
AstFunction* func = (AstFunction *) provider;
- AstArgument* arg = make_argument(semstate.node_allocator, func->params[idx].default_value);
+ AstTyped* default_value = func->params[idx].default_value;
+ if (default_value == NULL) return NULL;
+
+ AstArgument* arg = make_argument(semstate.node_allocator, default_value);
return (AstNode *) arg;
}
// NOTE: The values array can be partially filled out, and is the resulting array.
// Returns if all the values were filled in.
b32 fill_in_arguments(bh_arr(AstNode *) values, bh_arr(AstNamedValue *) named_values, AstNode* provider, char** err_msg) {
- bh_arr_each(AstNamedValue *, p_named_value, named_values) {
- AstNamedValue* named_value = *p_named_value;
+ if (named_values != NULL) {
+ bh_arr_each(AstNamedValue *, p_named_value, named_values) {
+ AstNamedValue* named_value = *p_named_value;
- token_toggle_end(named_value->token);
- i32 idx = lookup_idx_by_name(provider, named_value->token->text);
- if (idx == -1) {
- if (err_msg) *err_msg = bh_aprintf(global_heap_allocator, "'%s' is not a valid named parameter here.", named_value->token->text);
token_toggle_end(named_value->token);
- return 0;
- }
+ i32 idx = lookup_idx_by_name(provider, named_value->token->text);
+ if (idx == -1) {
+ if (err_msg) *err_msg = bh_aprintf(global_heap_allocator, "'%s' is not a valid named parameter here.", named_value->token->text);
+ token_toggle_end(named_value->token);
+ return 0;
+ }
- assert(idx < bh_arr_length(values));
+ assert(idx < bh_arr_length(values));
- if (values[idx] != NULL) {
- if (err_msg) *err_msg = bh_aprintf(global_heap_allocator, "Multiple values given for parameter named '%s'.", named_value->token->text);
+ if (values[idx] != NULL) {
+ if (err_msg) *err_msg = bh_aprintf(global_heap_allocator, "Multiple values given for parameter named '%s'.", named_value->token->text);
+ token_toggle_end(named_value->token);
+ return 0;
+ }
+
+ values[idx] = named_value->value;
token_toggle_end(named_value->token);
- return 0;
}
-
- values[idx] = named_value->value;
- token_toggle_end(named_value->token);
}
b32 success = 1;