From: Brendan Hansen Date: Sat, 16 Jan 2021 19:23:52 +0000 (-0600) Subject: better and safer error reporting when using type expression in normal expressions X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=6edc36196b134a817db640bb0953aa0dc554d29c;p=onyx.git better and safer error reporting when using type expression in normal expressions --- diff --git a/bin/onyx b/bin/onyx index 29aee206..8a7d4aeb 100755 Binary files a/bin/onyx and b/bin/onyx differ diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index d290e501..bacc1116 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -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, diff --git a/misc/onyx.sublime-syntax b/misc/onyx.sublime-syntax index 0a1a7578..0ccd8427 100644 --- a/misc/onyx.sublime-syntax +++ b/misc/onyx.sublime-syntax @@ -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' diff --git a/onyx.exe b/onyx.exe index e409689d..1f1fd9c0 100644 Binary files a/onyx.exe and b/onyx.exe differ diff --git a/src/onyxastnodes.c b/src/onyxastnodes.c index 85db0d23..8d53e8ff 100644 --- a/src/onyxastnodes.c +++ b/src/onyxastnodes.c @@ -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); +} diff --git a/src/onyxchecker.c b/src/onyxchecker.c index 8e5ed61d..ea7905bb 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -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; } diff --git a/src/onyxutils.c b/src/onyxutils.c index 23abe8fe..63d064d2 100644 --- a/src/onyxutils.c +++ b/src/onyxutils.c @@ -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, diff --git a/tests/named_arguments_test.onyx b/tests/named_arguments_test.onyx index f3fe33b6..643393d6 100644 --- a/tests/named_arguments_test.onyx +++ b/tests/named_arguments_test.onyx @@ -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