better and safer error reporting when using type expression in normal expressions
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 16 Jan 2021 19:23:52 +0000 (13:23 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 16 Jan 2021 19:23:52 +0000 (13:23 -0600)
bin/onyx
include/onyxastnodes.h
misc/onyx.sublime-syntax
onyx.exe
src/onyxastnodes.c
src/onyxchecker.c
src/onyxutils.c
tests/named_arguments_test.onyx

index 29aee206618053d8d1fd64ee00204155b9f950c6..8a7d4aeb047bea85e25a9c81483663c6481ad4e6 100755 (executable)
Binary files a/bin/onyx and b/bin/onyx differ
index d290e50170d295d6e522ebdfd6e77bbcacf6fc8f..bacc11161709202075cf642de945abfe18bf4cc5 100644 (file)
@@ -1031,6 +1031,9 @@ void arguments_clone(Arguments* dest, Arguments* src);
 void arguments_deep_clone(bh_allocator a, Arguments* dest, Arguments* src);
 void arguments_removed_baked(Arguments* args);
 
+// GROSS: Using void* to avoid having to cast everything.
+const char* node_get_type_name(void* node);
+
 typedef enum PolyProcLookupMethod {
     PPLM_By_Call,
     PPLM_By_Function_Type,
index 0a1a75780ddfdded4e61df7c4d2bfcab415b6d37..0ccd8427b21fa9182fc22a78687d01273035dac4 100644 (file)
@@ -29,7 +29,7 @@ contexts:
     - match: '\b(package|struct|proc|use|global|enum|if|elseif|else|for|while|do|break|continue|fallthrough|return|as|cast|sizeof|alignof|defer|switch|case)\b'
       scope: keyword.control.onyx
 
-    - match: '\b(bool|void|i8|u8|i16|u16|i32|u32|i64|u64|f32|f64|rawptr|str|cstr|range)\b'
+    - match: '\b(bool|void|i8|u8|i16|u16|i32|u32|i64|u64|f32|f64|rawptr|str|cstr|range|type_expr)\b'
       scope: storage.type
 
     - match: '\b(i8x16|i16x8|i32x4|i64x2|f32x4|f64x2|v128)\b'
index e409689db0df3bcbaa668f0bf43f588425c71566..1f1fd9c0ddaaf32a2c6d87db9558c406fa920f05 100644 (file)
Binary files a/onyx.exe and b/onyx.exe differ
index 85db0d236ba74220014b3a160bfc82de4a2f34d9..8d53e8ff96e812088dcc13716b2abf9d43264145 100644 (file)
@@ -414,6 +414,8 @@ b32 type_check_or_auto_cast(AstTyped** pnode, Type* type) {
     assert(type != NULL);
     assert(node != NULL);
 
+    if (node_is_type((AstNode *) node)) return 0;
+
     if (node->kind == Ast_Kind_Polymorphic_Proc) {
         AstFunction* func = polymorphic_proc_lookup((AstPolyProc *) node, PPLM_By_Function_Type, type, node->token);
         if (func == NULL) return 0;
@@ -724,4 +726,15 @@ void arguments_removed_baked(Arguments* args) {
         bh_arr_deleten(args->named_values, i, 1);
         i--;
     }
-}
\ No newline at end of file
+}
+
+// GROSS: Using void* to avoid having to cast everything.
+const char* node_get_type_name(void* node) {
+    if (node_is_type((AstNode *) node)) return "type_expr";
+
+    if (((AstNode *) node)->kind == Ast_Kind_Argument) {
+        return node_get_type_name(((AstArgument *) node)->value);
+    }
+
+    return type_get_name(((AstTyped *) node)->type);
+}
index 8e5ed61dd93af6b557056cc31f3910faff4e9c02..ea7905bbc2d3e292193310f4482df9d52a0e3f88 100644 (file)
@@ -96,7 +96,7 @@ CheckStatus check_return(AstReturn* retnode) {
             onyx_report_error(retnode->token->pos,
                     "Expected to return a value of type '%s', returning value of type '%s'.",
                     type_get_name(semstate.expected_return_type),
-                    type_get_name(retnode->expr->type));
+                    node_get_type_name(retnode->expr));
             return Check_Error;
         }
 
@@ -364,7 +364,7 @@ static void report_unable_to_match_overload(AstCall* call) {
     arg_str[0] = '\0';
 
     bh_arr_each(AstTyped *, arg, call->args.values) {
-        strncat(arg_str, type_get_name((*arg)->type), 1023);
+        strncat(arg_str, node_get_type_name(*arg), 1023);
 
         if (arg != &bh_arr_last(call->args.values))
             strncat(arg_str, ", ", 1023);
@@ -377,7 +377,7 @@ static void report_unable_to_match_overload(AstCall* call) {
             token_toggle_end((*named_value)->token);
 
             strncat(arg_str, "=", 1023);
-            strncat(arg_str, type_get_name((*named_value)->value->type), 1023); // CHECK: this might say 'unknown'.
+            strncat(arg_str, node_get_type_name((*named_value)->value), 1023); // CHECK: this might say 'unknown'.
 
             if (named_value != &bh_arr_last(call->args.named_values))
                 strncat(arg_str, ", ", 1023);
@@ -572,7 +572,7 @@ CheckStatus check_call(AstCall* call) {
                             type_get_name(formal_params[arg_pos]),
                             arg_pos + 1,
                             bh_num_suffix(arg_pos + 1),
-                            type_get_name(arg_arr[arg_pos]->value->type));
+                            node_get_type_name(arg_arr[arg_pos]->value));
                     return Check_Error;
                 }
 
@@ -591,7 +591,7 @@ CheckStatus check_call(AstCall* call) {
                             type_get_name(variadic_type),
                             variadic_param->local->token->text,
                             variadic_param->local->token->length,
-                            type_get_name(arg_arr[arg_pos]->value->type));
+                            node_get_type_name(arg_arr[arg_pos]->value));
                     return Check_Error;
                 }
 
@@ -620,7 +620,7 @@ type_checking_done:
         return Check_Error;
     }
 
-    if (arg_pos < arg_count) {
+    if (arg_pos < (u32) arg_count) {
         onyx_report_error(call->token->pos, "Too many arguments to function call.");
         return Check_Error;
     }
@@ -709,8 +709,8 @@ CheckStatus check_binop_assignment(AstBinaryOp* binop, b32 assignment_is_ok) {
     if (!type_check_or_auto_cast(&binop->right, binop->left->type)) {
         onyx_report_error(binop->token->pos,
                 "Cannot assign value of type '%s' to a '%s'.",
-                type_get_name(binop->right->type),
-                type_get_name(binop->left->type));
+                node_get_type_name(binop->right),
+                node_get_type_name(binop->left));
         return Check_Error;
     }
 
@@ -901,8 +901,8 @@ CheckStatus check_binaryop(AstBinaryOp** pbinop, b32 assignment_is_ok) {
             onyx_report_error(binop->token->pos,
                     "Mismatched types for binary operation '%s'. left: '%s', right: '%s'.",
                     binaryop_string[binop->operation],
-                    type_get_name(binop->left->type),
-                    type_get_name(binop->right->type));
+                    node_get_type_name(binop->left),
+                    node_get_type_name(binop->right));
             return Check_Error;
         }
     }
@@ -970,8 +970,8 @@ CheckStatus check_binaryop(AstBinaryOp** pbinop, b32 assignment_is_ok) {
 bad_binaryop:
     onyx_report_error(binop->token->pos, "Binary operator '%s' not understood for arguments of type '%s' and '%s'.",
             binaryop_string[binop->operation],
-            type_get_name(binop->left->type),
-            type_get_name(binop->right->type));
+            node_get_type_name(binop->left),
+            node_get_type_name(binop->right));
 
     return Check_Error;
 }
@@ -997,7 +997,7 @@ CheckStatus check_unaryop(AstUnaryOp** punop) {
         if (!type_is_bool(unaryop->expr->type)) {
             onyx_report_error(unaryop->token->pos,
                     "Bool negation operator expected bool type, got '%s'.",
-                    type_get_name(unaryop->expr->type));
+                    node_get_type_name(unaryop->expr));
             return Check_Error;
         }
     }
@@ -1006,7 +1006,7 @@ CheckStatus check_unaryop(AstUnaryOp** punop) {
         if (!type_is_integer(unaryop->expr->type)) {
             onyx_report_error(unaryop->token->pos,
                     "Bitwise operator expected integer type, got '%s'.",
-                    type_get_name(unaryop->expr->type));
+                    node_get_type_name(unaryop->expr));
             return Check_Error;
         }
     }
@@ -1075,7 +1075,7 @@ CheckStatus check_struct_literal(AstStructLiteral* sl) {
                     i + 1, bh_num_suffix(i + 1),
                     smem.name,
                     type_get_name(formal),
-                    type_get_name((*actual)->type));
+                    node_get_type_name(*actual));
             return Check_Error;
         }
 
@@ -1117,7 +1117,7 @@ CheckStatus check_array_literal(AstArrayLiteral* al) {
         if (!type_check_or_auto_cast(expr, elem_type)) {
             onyx_report_error((*expr)->token->pos, "Mismatched types for value of in array, expected '%s', got '%s'.",
                 type_get_name(elem_type),
-                type_get_name((*expr)->type));
+                node_get_type_name(*expr));
             return Check_Error;
         }
     }
@@ -1137,7 +1137,7 @@ CheckStatus check_range_literal(AstRangeLiteral** prange) {
     if (!type_check_or_auto_cast(&range->low, smem.type)) {
         onyx_report_error(range->token->pos,
             "Expected left side of range to be a 32-bit integer, got '%s'.",
-            type_get_name(range->low->type));
+            node_get_type_name(range->low));
         return Check_Error;
     }
 
@@ -1145,7 +1145,7 @@ CheckStatus check_range_literal(AstRangeLiteral** prange) {
     if (!type_check_or_auto_cast(&range->high, smem.type)) {
         onyx_report_error(range->token->pos,
             "Expected right side of range to be a 32-bit integer, got '%s'.",
-            type_get_name(range->high->type));
+            node_get_type_name(range->high));
         return Check_Error;
     }
 
@@ -1214,7 +1214,7 @@ CheckStatus check_array_access(AstArrayAccess* aa) {
     if (!type_is_array_accessible(aa->addr->type)) {
         onyx_report_error(aa->token->pos,
                 "Expected pointer or array type for left of array access, got '%s'.",
-                type_get_name(aa->addr->type));
+                node_get_type_name(aa->addr));
         return Check_Error;
     }
 
@@ -1243,7 +1243,7 @@ CheckStatus check_array_access(AstArrayAccess* aa) {
             || (aa->expr->type->Basic.kind != Basic_Kind_I32 && aa->expr->type->Basic.kind != Basic_Kind_U32)) {
         onyx_report_error(aa->token->pos,
             "Expected type u32 or i32 for index, got '%s'.",
-            type_get_name(aa->expr->type));
+            node_get_type_name(aa->expr));
         return Check_Error;
     }
 
@@ -1291,7 +1291,7 @@ CheckStatus check_field_access(AstFieldAccess** pfield) {
             "Cannot access field '%b' on '%s'. Type is not a struct.",
             field->token->text,
             field->token->length,
-            type_get_name(field->expr->type));
+            node_get_type_name(field->expr));
         return Check_Error;
     }
 
@@ -1317,7 +1317,7 @@ CheckStatus check_field_access(AstFieldAccess** pfield) {
         onyx_report_error(field->token->pos,
             "Field '%s' does not exists on '%s'.",
             field->field,
-            type_get_name(field->expr->type));
+            node_get_type_name(field->expr));
 
         return Check_Error;
     }
@@ -1713,7 +1713,7 @@ CheckStatus check_memres(AstMemRes* memres) {
             if (!type_check_or_auto_cast(&memres->initial_value, memres_type)) {
                 onyx_report_error(memres->token->pos,
                         "Cannot assign value of type '%s' to a '%s'.",
-                        type_get_name(memres->initial_value->type),
+                        node_get_type_name(memres->initial_value),
                         type_get_name(memres_type));
                 return Check_Error;
             }
index 23abe8fec78c795a18adfe40e6b096589febe99e..63d064d24d3b88d4cc641faa9fa3feee68aaef03 100644 (file)
@@ -394,7 +394,7 @@ static bh_arr(AstPolySolution) find_polymorphic_slns(AstPolyProc* pp, PolyProcLo
         if (already_solved) continue;
 
         // CLEANUP CLEANUP CLEANUP
-        PolySolveResult resolved;
+        PolySolveResult resolved = { 0 };
 
         if (param->kind == PPK_Poly_Type) {
             Type* actual_type = NULL;
@@ -759,6 +759,15 @@ AstFunction* polymorphic_proc_build_only_header(AstPolyProc* pp, PolyProcLookupM
     solidified_func.func->flags |= Ast_Flag_Incomplete_Body;
     solidified_func.func->flags |= Ast_Flag_From_Polymorphism;
 
+    // HACK HACK HACK
+    u32 removed_params = 0;
+    bh_arr_each(AstPolyParam, param, pp->poly_params) {
+        if (param->kind != PPK_Baked_Value) continue;
+
+        bh_arr_deleten(solidified_func.func->params, param->idx - removed_params, 1);
+        removed_params++;
+    }
+
     Entity func_header_entity = {
         .state = Entity_State_Resolve_Symbols,
         .type = Entity_Type_Function_Header,
index f3fe33b67a54866df5fbd7a7bdbaf813e02b71f0..643393d6d50e61c9e2a1dc39ce1c0ae4dc7482d4 100644 (file)
@@ -70,4 +70,16 @@ main :: proc (args: [] cstr) {
 
     lotza_options(options_e = true, options_c = false, /* option_a */ false, /* option_b */ true);
     lotza_options(options_e = true, options_c = false, options_a = true);
+
+
+    // This currently does not work and would require a lot of rewriting of compiler internals to make work.
+    // named_baked_overloaded_parameters :: proc {
+    //     proc ($T: type_expr, x: T)      do { println("MATCHED X"); },
+    //     proc ($T: type_expr, y: [$N] T) do { println("MATCHED X"); },
+    //     proc ($T: type_expr, z: T)      do { println("MATCHED X"); },
+    // }
+
+    // named_baked_overloaded_parameters(i32, 10);
+    // named_baked_overloaded_parameters(i32, u32.[ 10, 20, 30 ]);
+    // named_baked_overloaded_parameters(i32, z = u32.[ 10, 20, 30 ]);
 }
\ No newline at end of file