From fd3f0f667f09501c972c8976d8872d3534b62eae Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Thu, 4 Jan 2024 19:32:16 -0600 Subject: [PATCH] fixed: type inference bugs and certain error messages --- compiler/include/astnodes.h | 2 +- compiler/src/checker.c | 15 +++++---- compiler/src/polymorph.h | 62 +++++++++++++++++++++++++------------ 3 files changed, 53 insertions(+), 26 deletions(-) diff --git a/compiler/include/astnodes.h b/compiler/include/astnodes.h index a29b83a5..be565f6a 100644 --- a/compiler/include/astnodes.h +++ b/compiler/include/astnodes.h @@ -2066,7 +2066,7 @@ const char* node_get_type_name(void* node); b32 static_if_resolution(AstIf* static_if); void insert_poly_sln_into_scope(Scope* scope, AstPolySolution *sln); -TypeMatch find_polymorphic_sln(AstPolySolution *out, AstPolyParam *param, AstFunction *func, PolyProcLookupMethod pp_lookup, ptr actual, char** err_msg); +TypeMatch find_polymorphic_sln(AstPolySolution *out, AstPolyParam *param, AstFunction *func, PolyProcLookupMethod pp_lookup, ptr actual, OnyxError* err_msg); AstFunction* polymorphic_proc_lookup(AstFunction* pp, PolyProcLookupMethod pp_lookup, ptr actual, OnyxToken* tkn); AstFunction* polymorphic_proc_solidify(AstFunction* pp, bh_arr(AstPolySolution) slns, OnyxToken* tkn); AstNode* polymorphic_proc_try_solidify(AstFunction* pp, bh_arr(AstPolySolution) slns, OnyxToken* tkn); diff --git a/compiler/src/checker.c b/compiler/src/checker.c index 860ae511..5fac8aa5 100644 --- a/compiler/src/checker.c +++ b/compiler/src/checker.c @@ -1748,6 +1748,10 @@ CheckStatus check_struct_literal(AstStructLiteral* sl) { } CheckStatus check_array_literal(AstArrayLiteral* al) { + bh_arr_each(AstTyped *, expr, al->values) { + CHECK(expression, expr); + } + // :Idempotency if ((al->flags & Ast_Flag_Array_Literal_Typed) == 0) { if (al->atnode == NULL) return Check_Success; @@ -1769,7 +1773,7 @@ CheckStatus check_array_literal(AstArrayLiteral* al) { } if (al->type->Array.count != (u32) bh_arr_length(al->values)) { - ERROR_(al->token->pos, "Wrong array size (%d) for number of values (%d).", + ERROR_(al->token->pos, "Wrong number of values provided in array literal. Wanted %d values, got %d values.", al->type->Array.count, bh_arr_length(al->values)); } @@ -1778,8 +1782,6 @@ CheckStatus check_array_literal(AstArrayLiteral* al) { Type* elem_type = al->type->Array.elem; bh_arr_each(AstTyped *, expr, al->values) { - CHECK(expression, expr); - // HACK HACK HACK if ((*expr)->type == NULL && (*expr)->entity != NULL && @@ -1790,7 +1792,7 @@ CheckStatus check_array_literal(AstArrayLiteral* al) { al->flags &= ((*expr)->flags & Ast_Flag_Comptime) | (al->flags &~ Ast_Flag_Comptime); TYPE_CHECK(expr, elem_type) { - ERROR_((*expr)->token->pos, "Mismatched types for value of in array, expected '%s', got '%s'.", + ERROR_((*expr)->token->pos, "Mismatched types for value in array. Expected something of type '%s', got '%s' instead.", type_get_name(elem_type), node_get_type_name(*expr)); } @@ -3923,7 +3925,8 @@ CheckStatus check_polyquery(AstPolyQuery *query) { b32 solved_something = 0; i32 solved_count = 0; - char *err_msg = NULL; + OnyxError err_msg = { 0 }; + bh_arr_each(AstPolyParam, param, query->proc->poly_params) { AstPolySolution sln; bh_arr_each(AstPolySolution, solved_sln, query->slns) { @@ -3959,7 +3962,7 @@ CheckStatus check_polyquery(AstPolyQuery *query) { if (query->error_on_fail || context.cycle_detected) { onyx_report_error(query->token->pos, Error_Critical, "Error solving for polymorphic variable '%b'.", param->poly_sym->token->text, param->poly_sym->token->length); - if (err_msg != NULL) onyx_report_error(query->token->pos, Error_Critical, "%s", err_msg); + if (err_msg.text != NULL) onyx_submit_error(err_msg); if (query->error_loc) onyx_report_error(query->error_loc->pos, Error_Critical, "Here is where the call is located."); // :ErrorMessage } diff --git a/compiler/src/polymorph.h b/compiler/src/polymorph.h index ecc1ae6c..0e4ce20e 100644 --- a/compiler/src/polymorph.h +++ b/compiler/src/polymorph.h @@ -449,7 +449,7 @@ static PolySolveResult solve_poly_type(AstNode* target, AstType* type_expr, Type // and solve for the argument that matches the parameter. This is needed because polymorphic // procedure resolution has to happen before the named arguments are placed in their correct // positions. -static AstTyped* lookup_param_in_arguments(AstFunction* func, AstPolyParam* param, Arguments* args, char** err_msg) { +static AstTyped* lookup_param_in_arguments(AstFunction* func, AstPolyParam* param, Arguments* args, OnyxError* err_msg) { bh_arr(AstTyped *) arg_arr = args->values; bh_arr(AstNamedValue *) named_values = args->named_values; @@ -479,7 +479,9 @@ static AstTyped* lookup_param_in_arguments(AstFunction* func, AstPolyParam* para } // CLEANUP - if (err_msg) *err_msg = "Not enough arguments to polymorphic procedure. This error message may not be entirely right."; + if (err_msg) { + err_msg->text = "Not enough arguments to polymorphic procedure. This error message may not be entirely right."; + } } else { return (AstTyped *) arg_arr[param->idx]; @@ -524,7 +526,7 @@ static AstTyped* try_lookup_based_on_partial_function_type(AstFunction *pp, AstF // information. It is asssumed that the "param" is of kind PPK_Poly_Type. This function uses // either the arguments provided, or a function type to compare against to pattern match for // the type that the parameter but be. -static void solve_for_polymorphic_param_type(PolySolveResult* resolved, AstFunction* func, AstPolyParam* param, PolyProcLookupMethod pp_lookup, ptr actual, char** err_msg) { +static void solve_for_polymorphic_param_type(PolySolveResult* resolved, AstFunction* func, AstPolyParam* param, PolyProcLookupMethod pp_lookup, ptr actual, OnyxError* err_msg) { Type* actual_type = NULL; b32 can_strip_pointer = 0; @@ -567,7 +569,12 @@ static void solve_for_polymorphic_param_type(PolySolveResult* resolved, AstFunct skip_nested_polymorph_case: actual_type = query_expression_type(typed_param); - if (actual_type == NULL) return; + if (actual_type == NULL) { + if (typed_param) err_msg->pos = typed_param->token->pos; + + err_msg->text = "Unable to resolve type of this expression, needed to solve for polymorphic variable."; + return; + } break; } @@ -575,7 +582,9 @@ static void solve_for_polymorphic_param_type(PolySolveResult* resolved, AstFunct case PPLM_By_Function_Type: { Type* ft = (Type *) actual; if (param->idx >= ft->Function.param_count) { - if (err_msg) *err_msg = "Incompatible polymorphic argument to function parameter."; + if (err_msg) { + err_msg->text = "Incompatible polymorphic argument to function parameter."; + } return; } @@ -601,7 +610,8 @@ static void solve_for_polymorphic_param_type(PolySolveResult* resolved, AstFunct } if (res.kind == PSK_Undefined) { - *err_msg = bh_aprintf(global_scratch_allocator, + err_msg->pos = param->poly_sym->token->pos; + err_msg->text = bh_aprintf(global_scratch_allocator, "Unable to solve for polymorphic variable '%b', given the type '%s'.", param->poly_sym->token->text, param->poly_sym->token->length, @@ -618,9 +628,9 @@ static void solve_for_polymorphic_param_type(PolySolveResult* resolved, AstFunct // CLEANUP: This function is kind of gross at the moment, because it handles different cases for // the argument kind. When type expressions (type_expr) become first-class types in the type // system, this code should be able to be a lot cleaner. -static void solve_for_polymorphic_param_value(PolySolveResult* resolved, AstFunction* func, AstPolyParam* param, PolyProcLookupMethod pp_lookup, ptr actual, char** err_msg) { +static void solve_for_polymorphic_param_value(PolySolveResult* resolved, AstFunction* func, AstPolyParam* param, PolyProcLookupMethod pp_lookup, ptr actual, OnyxError* err_msg) { if (pp_lookup != PPLM_By_Arguments) { - *err_msg = "Function type cannot be used to solved for baked parameter value."; + err_msg->text = "Function type cannot be used to solved for baked parameter value."; return; } @@ -640,11 +650,12 @@ static void solve_for_polymorphic_param_value(PolySolveResult* resolved, AstFunc AstType *param_type_expr = func->params[param->idx].local->type_node; if (param_type_expr == (AstType *) &basic_type_type_expr) { if (!node_is_type((AstNode *) value)) { - if (err_msg) - // CLEANUP: Use a different allocator. - *err_msg = bh_aprintf(global_heap_allocator, + if (err_msg) { + err_msg->pos = value->token->pos; + err_msg->text = bh_aprintf(global_scratch_allocator, "Expected type expression here, got a '%s'.", type_get_name(value->type)); + } return; } @@ -659,7 +670,7 @@ static void solve_for_polymorphic_param_value(PolySolveResult* resolved, AstFunc param_type = type_build_from_ast(context.ast_alloc, param_type_expr); if (param_type == NULL) { flag_to_yield = 1; - *err_msg = "Waiting to know type for polymorphic value."; + err_msg->text = "Waiting to know type for polymorphic value."; return; } @@ -670,20 +681,28 @@ static void solve_for_polymorphic_param_value(PolySolveResult* resolved, AstFunc TypeMatch tm = unify_node_and_type(&value_to_use, param_type); if (tm == TYPE_MATCH_FAILED) { - if (err_msg) *err_msg = bh_aprintf(global_scratch_allocator, - "The procedure '%s' expects a value of type '%s' for baked %d%s parameter, got '%s'.", + if (err_msg) { + err_msg->pos = param->poly_sym->token->pos; + err_msg->text = bh_aprintf(global_scratch_allocator, + "The procedure '%s' expects a value of type '%s' for %d%s baked parameter '%b', got '%s'.", get_function_name(func), type_get_name(param_type), param->idx + 1, bh_num_suffix(param->idx + 1), + param->poly_sym->token->text, + param->poly_sym->token->length, node_get_type_name(value_to_use)); + } return; } if (tm == TYPE_MATCH_YIELD) flag_to_yield = 1; if ((value_to_use->flags & Ast_Flag_Comptime) == 0) { - if (err_msg) *err_msg = "Expected compile-time known argument here."; + if (err_msg) { + err_msg->pos = value_to_use->token->pos; + err_msg->text = "Expected compile-time known argument here."; + } return; } @@ -695,14 +714,19 @@ static void solve_for_polymorphic_param_value(PolySolveResult* resolved, AstFunc } } -TypeMatch find_polymorphic_sln(AstPolySolution *out, AstPolyParam *param, AstFunction *func, PolyProcLookupMethod pp_lookup, ptr actual, char** err_msg) { +TypeMatch find_polymorphic_sln(AstPolySolution *out, AstPolyParam *param, AstFunction *func, PolyProcLookupMethod pp_lookup, ptr actual, OnyxError* err_msg) { + if (err_msg) { + err_msg->pos = func->token->pos; + err_msg->rank = Error_Critical; + } + // NOTE: Solve for the polymorphic parameter's value PolySolveResult resolved = { PSK_Undefined }; switch (param->kind) { case PPK_Poly_Type: solve_for_polymorphic_param_type (&resolved, func, param, pp_lookup, actual, err_msg); break; case PPK_Baked_Value: solve_for_polymorphic_param_value(&resolved, func, param, pp_lookup, actual, err_msg); break; - default: if (err_msg) *err_msg = "Invalid polymorphic parameter kind. This is a compiler bug."; + default: if (err_msg) err_msg->text = "Invalid polymorphic parameter kind. This is a compiler bug."; } if (doing_nested_polymorph_lookup) { @@ -732,8 +756,8 @@ TypeMatch find_polymorphic_sln(AstPolySolution *out, AstPolyParam *param, AstFun default: // NOTE: If no error message has been assigned to why this polymorphic parameter // resolution was unsuccessful, provide a basic dummy one. - if (err_msg && *err_msg == NULL) - *err_msg = bh_aprintf(global_scratch_allocator, + if (err_msg && err_msg->text == NULL) + err_msg->text = bh_aprintf(global_scratch_allocator, "Unable to solve for polymorphic variable '%b'.", param->poly_sym->token->text, param->poly_sym->token->length); -- 2.25.1