overloads can be used by value
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 12 Apr 2021 20:52:37 +0000 (15:52 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 12 Apr 2021 20:52:37 +0000 (15:52 -0500)
bin/onyx
include/onyxastnodes.h
src/onyxastnodes.c
src/onyxchecker.c
src/onyxparser.c
src/onyxutils.c

index 478d054936f6b358c2c31bfaa23f38a4fb9b5a57..303d9fdd4600c06a6e214dd090834cdb2e735702 100755 (executable)
Binary files a/bin/onyx and b/bin/onyx differ
index 7a5039b856d2cc6bde71c043946082415e529301..e256743f6e98304f04ee11682c422f25d5e38323 100644 (file)
@@ -1184,6 +1184,7 @@ AstNode* polymorphic_proc_try_solidify(AstPolyProc* pp, bh_arr(AstPolySolution)
 AstFunction* polymorphic_proc_build_only_header(AstPolyProc* pp, PolyProcLookupMethod pp_lookup, ptr actual);
 
 AstTyped* find_matching_overload_by_arguments(bh_arr(AstTyped *) overloads, Arguments* args);
+AstTyped* find_matching_overload_by_type(bh_arr(AstTyped *) overloads, Type* type);
 void report_unable_to_match_overload(AstCall* call);
 
 AstStructType* polymorphic_struct_lookup(AstPolyStructType* ps_type, bh_arr(AstPolySolution) slns, OnyxFilePos pos);
index fb654767f55767d33b5dcf6187d31d20d22746d4..95a71acabd8ddcd95417bb63dd4a5edb73c1394c 100644 (file)
@@ -444,6 +444,18 @@ b32 type_check_or_auto_cast(AstTyped** pnode, Type* type) {
         return 1;
     }
 
+    if (node->kind == Ast_Kind_Overloaded_Function) {
+        AstTyped* func = find_matching_overload_by_type(((AstOverloadedFunction *) node)->overloads, type);
+        if (func == NULL) return 0;
+
+        // HACK: It feels like there should be a better place to flag that a procedure was definitely used.
+        if (func->kind == Ast_Kind_Function)
+            func->flags |= Ast_Flag_Function_Used;
+
+        *pnode = func;
+        node = *pnode;
+    }
+
     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;
@@ -646,6 +658,8 @@ b32 cast_is_legal(Type* from_, Type* to_, char** err_msg) {
 }
 
 char* get_function_name(AstFunction* func) {
+    if (func->kind != Ast_Kind_Function) return "<procedure>";
+
     if (func->name != NULL) {
         return bh_aprintf(global_scratch_allocator, "%b", func->name->text, func->name->length);
     }
index ef55f05d0f889c8ef8b8be74aa4358cbb45331b2..7e2eae1af494dcfae477cf145019e34c1a716fa8 100644 (file)
@@ -321,13 +321,6 @@ CheckStatus check_argument(AstArgument** parg) {
     CHECK(expression, &(*parg)->value);
     (*parg)->type = (*parg)->value->type;
 
-    if ((*parg)->value->kind == Ast_Kind_Overloaded_Function) {
-        onyx_report_error((*parg)->token->pos,
-            "Cannot pass overloaded function '%b' as argument.",
-            (*parg)->value->token->text, (*parg)->value->token->length);
-        return Check_Error;
-    }
-
     return Check_Success;
 }
 
index ae264191261f830c23adad5ee10675cdc0e5aab2..25c9314be2eacd13f8e6a4270ef77c23a8c2dfa2 100644 (file)
@@ -1876,6 +1876,7 @@ static AstFunction* parse_function_definition(OnyxParser* parser, OnyxToken* tok
     if (consume_token_if_next(parser, '{')) {
         AstOverloadedFunction* ofunc = make_node(AstOverloadedFunction, Ast_Kind_Overloaded_Function);
         ofunc->token = token;
+        ofunc->flags |= Ast_Flag_Comptime;
 
         bh_arr_new(global_heap_allocator, ofunc->overloads, 4);
 
index ded508040be48c2bc51fc258a11ea43547251553..6d7e3aeebf9af4c022696749cbaa09d73a8bf3bb 100644 (file)
@@ -1019,6 +1019,29 @@ AstTyped* find_matching_overload_by_arguments(bh_arr(AstTyped *) overloads, Argu
     return matched_overload;
 }
 
+AstTyped* find_matching_overload_by_type(bh_arr(AstTyped *) overloads, Type* type) {
+    if (type->kind != Type_Kind_Function) return NULL;
+
+    bh_imap all_overloads;
+    bh_imap_init(&all_overloads, global_heap_allocator, bh_arr_length(overloads) * 2);
+    build_all_overload_options(overloads, &all_overloads);
+
+    AstTyped *matched_overload = NULL;
+
+    bh_arr_each(bh__imap_entry, entry, all_overloads.entries) {
+        AstTyped* node = (AstTyped *) entry->key;
+        if (node->kind == Ast_Kind_Overloaded_Function) continue;
+
+        if (type_check_or_auto_cast(&node, type)) {
+            matched_overload = node;
+            break;
+        }
+    }
+    
+    bh_imap_free(&all_overloads);
+    return matched_overload;
+}
+
 void report_unable_to_match_overload(AstCall* call) {
     char* arg_str = bh_alloc(global_scratch_allocator, 1024);
     arg_str[0] = '\0';