fixed: type inference bugs and certain error messages
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 5 Jan 2024 01:32:16 +0000 (19:32 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 5 Jan 2024 01:32:16 +0000 (19:32 -0600)
compiler/include/astnodes.h
compiler/src/checker.c
compiler/src/polymorph.h

index a29b83a55b8cc0548317ef6b4d74ae56be27e0ae..be565f6ab0101f13385972a5f8ae5af732d1f151 100644 (file)
@@ -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);
index 860ae5113b21149fffd890c5343b3898e0a2b146..5fac8aa576ccf0bc41373439b81b190f9f871b67 100644 (file)
@@ -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
                 }
 
index ecc1ae6c87dfc83118f8616746906eacd3c09d1f..0e4ce20edf475fa1458952c7cfd8135107575ab3 100644 (file)
@@ -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);