From 80505a7eb147422226d1b86da17f516982d0f4c8 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Sun, 23 Nov 2025 13:52:15 -0500 Subject: Better error messages and bugfix for compile_to_type logic --- src/compile/functions.c | 12 ++++++------ src/typecheck.c | 25 +++++++++++++------------ src/types.c | 21 +++++++++++++-------- src/types.h | 1 + 4 files changed, 33 insertions(+), 26 deletions(-) diff --git a/src/compile/functions.c b/src/compile/functions.c index 4a2812ba..cce93e3d 100644 --- a/src/compile/functions.c +++ b/src/compile/functions.c @@ -163,12 +163,12 @@ Text_t compile_function_call(env_t *env, ast_t *ast) { args = new (arg_t, .name = a->name, .type = get_type(env, a->value), .next = args); REVERSE_LIST(args); code_err(ast, - "This function's signature doesn't match this call site.\n" - "The signature is: ", - type_to_text(fn_t), - "\n" - "But it's being called with: ", - type_to_text(Type(FunctionType, .args = args))); + "This function's signature doesn't match this call site. \n" + " The function takes these args: (", + arg_types_to_text(Match(fn_t, FunctionType)->args, ", "), + ") \n" + " But it's being called with: (", + arg_types_to_text(args, ", "), ")"); } } return Texts(fn, "(", compile_arguments(env, ast, Match(fn_t, FunctionType)->args, call->args), ")"); diff --git a/src/typecheck.c b/src/typecheck.c index 27bb62c6..98fbf6da 100644 --- a/src/typecheck.c +++ b/src/typecheck.c @@ -1588,8 +1588,9 @@ bool is_valid_call(env_t *env, arg_t *spec_args, arg_ast_t *call_args, call_opts for (; unused_args; unused_args = unused_args->next) { if (unused_args->name) continue; // Already handled the keyword args if (options.promotion) { - if (!can_compile_to_type(arg_scope, unused_args->value, spec_type)) + if (!can_compile_to_type(arg_scope, unused_args->value, spec_type)) { return false; // Positional arg trying to fill in + } } else { type_t *call_type = get_arg_ast_type(arg_scope, unused_args); type_t *complete_call_type = @@ -1701,16 +1702,16 @@ PUREFUNC bool can_compile_to_type(env_t *env, ast_t *ast, type_t *needed) { if (is_numeric_type(needed) && ast->tag == Int) return true; if (needed->tag == NumType && ast->tag == Num) return true; - needed = non_optional(needed); - if (needed->tag == ListType && ast->tag == List) { - type_t *item_type = Match(needed, ListType)->item_type; + type_t *non_optional_needed = non_optional(needed); + if (non_optional_needed->tag == ListType && ast->tag == List) { + type_t *item_type = Match(non_optional_needed, ListType)->item_type; for (ast_list_t *item = Match(ast, List)->items; item; item = item->next) { if (!can_compile_to_type(env, item->ast, item_type)) return false; } return true; - } else if (needed->tag == TableType && ast->tag == Table) { - type_t *key_type = Match(needed, TableType)->key_type; - type_t *value_type = Match(needed, TableType)->value_type; + } else if (non_optional_needed->tag == TableType && ast->tag == Table) { + type_t *key_type = Match(non_optional_needed, TableType)->key_type; + type_t *value_type = Match(non_optional_needed, TableType)->value_type; for (ast_list_t *entry = Match(ast, Table)->entries; entry; entry = entry->next) { if (entry->ast->tag != TableEntry) continue; // TODO: fix this DeclareMatch(e, entry->ast, TableEntry); @@ -1725,16 +1726,16 @@ PUREFUNC bool can_compile_to_type(env_t *env, ast_t *ast, type_t *needed) { if (type_eq(actual, needed)) return true; if (actual->tag == OptionalType && needed->tag == OptionalType) return can_promote(actual, needed); - if (needed->tag == PointerType) { - DeclareMatch(ptr, needed, PointerType); + if (non_optional_needed->tag == PointerType) { + DeclareMatch(ptr, non_optional_needed, PointerType); if (ast->tag == HeapAllocate) return !ptr->is_stack && can_compile_to_type(env, Match(ast, HeapAllocate)->value, ptr->pointed); else if (ast->tag == StackReference) return ptr->is_stack && can_compile_to_type(env, Match(ast, StackReference)->value, ptr->pointed); - else return can_promote(actual, needed); - } else if (actual->tag == OptionalType && needed->tag != OptionalType) { + else return can_promote(actual, non_optional_needed); + } else if (actual->tag == OptionalType && non_optional_needed->tag != OptionalType) { return false; } else { - return can_promote(actual, needed); + return can_promote(actual, non_optional_needed); } } diff --git a/src/types.c b/src/types.c index 51555560..edfee27d 100644 --- a/src/types.c +++ b/src/types.c @@ -12,6 +12,15 @@ #include "stdlib/util.h" #include "types.h" +Text_t arg_types_to_text(arg_t *args, const char *separator) { + Text_t text = EMPTY_TEXT; + for (arg_t *arg = args; arg; arg = arg->next) { + text = Texts(text, type_to_text(arg->type)); + if (arg->next) text = Texts(text, separator); + } + return text; +} + Text_t type_to_text(type_t *t) { if (!t) return Text("(Unknown type)"); @@ -45,15 +54,11 @@ Text_t type_to_text(type_t *t) { return type_to_text(Match(t, ClosureType)->fn); } case FunctionType: { - Text_t c = Text("func("); DeclareMatch(fn, t, FunctionType); - for (arg_t *arg = fn->args; arg; arg = arg->next) { - c = Texts(c, type_to_text(arg->type)); - if (arg->next) c = Texts(c, ","); - } - if (fn->ret && fn->ret->tag != VoidType) c = Texts(c, fn->args ? " -> " : "-> ", type_to_text(fn->ret)); - c = Texts(c, ")"); - return c; + Text_t text = Texts("func(", arg_types_to_text(fn->args, ",")); + if (fn->ret && fn->ret->tag != VoidType) text = Texts(text, fn->args ? " -> " : "-> ", type_to_text(fn->ret)); + text = Texts(text, ")"); + return text; } case StructType: { DeclareMatch(struct_, t, StructType); diff --git a/src/types.h b/src/types.h index 2a94a512..b8f9a42f 100644 --- a/src/types.h +++ b/src/types.h @@ -136,6 +136,7 @@ struct type_s { _make_function_type(ret, sizeof((arg_t[]){__VA_ARGS__}) / sizeof(arg_t), (arg_t[]){__VA_ARGS__}) Text_t type_to_text(type_t *t); +Text_t arg_types_to_text(arg_t *args, const char *separator); const char *get_type_name(type_t *t); PUREFUNC bool type_eq(type_t *a, type_t *b); PUREFUNC bool type_is_a(type_t *t, type_t *req); -- cgit v1.2.3