polymorphic overloads can signal yield for header
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 6 Aug 2021 20:46:10 +0000 (15:46 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 6 Aug 2021 20:46:10 +0000 (15:46 -0500)
bin/onyx
core/container/iter.onyx
include/onyxastnodes.h
src/onyxchecker.c
src/onyxutils.c

index f63a1aec542cfb2fefdd73be9e6837acce87689b..9181d948936d0e19d3088cb6851deaef7018ae7d 100755 (executable)
Binary files a/bin/onyx and b/bin/onyx differ
index 880c8245cd6683153a2ebcc86c49ccfba4ffc144..c9c6c4e9ceadb88300fe7e55e8973258322c2388 100644 (file)
@@ -248,41 +248,43 @@ enumerate :: (it: Iterator($T), start_index: i32 = 0) -> Iterator(Enumeration_Va
     };
 }
 
-from_array :: (arr: [..] $T) -> Iterator(^T) {
-    return from_slice((#type [] T).{ arr.data, arr.count });
-}
+from_array :: #match {
+    (arr: [..] $T) -> Iterator(^T) {
+        return from_slice((#type [] T).{ arr.data, arr.count });
+    },
+
+    (arr: [] $T) -> Iterator(^T) {
+        Context :: struct (T: type_expr) {
+            data: ^T;
+            count: u32;
+            current: u32;
+        }
 
-from_slice :: (arr: [] $T) -> Iterator(^T) {
-    Context :: struct (T: type_expr) {
-        data: ^T;
-        count: u32;
-        current: u32;
-    }
+        c := make(#type Context(T));
+        c.data = arr.data;
+        c.count = arr.count;
+        c.current = 0;
 
-    c := make(#type Context(T));
-    c.data = arr.data;
-    c.count = arr.count;
-    c.current = 0;
+        next :: ($T: type_expr, use _: ^Context(T)) -> (^T, bool) {
+            if current < count {
+                defer current += 1;
+                return ^data[current], true;
 
-    next :: ($T: type_expr, use _: ^Context(T)) -> (^T, bool) {
-        if current < count {
-            defer current += 1;
-            return ^data[current], true;
+            } else {
+                return null, false;
+            }
+        }
 
-        } else {
-            return null, false;
+        close :: (data: rawptr) {
+            cfree(data);
         }
-    }
 
-    close :: (data: rawptr) {
-        cfree(data);
+        return .{
+            data  = c,
+            next  = #solidify next { T = T },
+            close = close,
+        };
     }
-
-    return .{
-        data  = c,
-        next  = #solidify next { T = T },
-        close = close,
-    };
 }
 
 fold :: (it: Iterator($T), initial_value: R, combine: (T, $R) -> R) -> R {
index f9b8ee261b913343c07db3d91cc8c2a0c80e4b35..4d7c137df8db0a858b2637a43891b7d75b76bde7 100644 (file)
@@ -939,6 +939,9 @@ struct AstPolySolution {
 };
 
 struct AstSolidifiedFunction {
+    b32 header_complete: 1;
+    b32 body_complete:   1;
+    
     AstFunction* func;
     Scope*       poly_scope;
 };
@@ -1326,7 +1329,7 @@ AstNode* polymorphic_proc_try_solidify(AstPolyProc* pp, bh_arr(AstPolySolution)
 AstFunction* polymorphic_proc_build_only_header(AstPolyProc* pp, PolyProcLookupMethod pp_lookup, ptr actual);
 
 void add_overload_option(bh_arr(OverloadOption)* poverloads, u64 precedence, AstTyped* overload);
-AstTyped* find_matching_overload_by_arguments(bh_arr(OverloadOption) overloads, Arguments* args);
+AstTyped* find_matching_overload_by_arguments(bh_arr(OverloadOption) overloads, Arguments* args, b32* should_yield);
 AstTyped* find_matching_overload_by_type(bh_arr(OverloadOption) overloads, Type* type);
 void report_unable_to_match_overload(AstCall* call);
 
index 3bf1c7465205eaf3599408d07cd7b1c5cffb227f..ca848767626c464b369f5b99d90f303d8bb8a570 100644 (file)
@@ -435,9 +435,10 @@ CheckStatus check_call(AstCall* call) {
     while (call->callee->kind == Ast_Kind_Alias) call->callee = ((AstAlias *) call->callee)->alias;
 
     if (call->callee->kind == Ast_Kind_Overloaded_Function) {
-        AstTyped* new_callee = find_matching_overload_by_arguments(((AstOverloadedFunction *) call->callee)->overloads, &call->args);
+        b32 should_yield = 0;
+        AstTyped* new_callee = find_matching_overload_by_arguments(((AstOverloadedFunction *) call->callee)->overloads, &call->args, &should_yield);
         if (new_callee == NULL) {
-            if (call->callee->entity->state > Entity_State_Check_Types) {
+            if (call->callee->entity->state > Entity_State_Check_Types && !should_yield) {
                 report_unable_to_match_overload(call);
                 return Check_Error;
 
@@ -906,7 +907,8 @@ static AstCall* binaryop_try_operator_overload(AstBinaryOp* binop) {
     bh_arr_push(args.values, binop->left);
     bh_arr_push(args.values, binop->right);
 
-    AstTyped* overload = find_matching_overload_by_arguments(operator_overloads[binop->operation], &args);
+    b32 should_yield = 0;
+    AstTyped* overload = find_matching_overload_by_arguments(operator_overloads[binop->operation], &args, &should_yield);
     if (overload == NULL) {
         bh_arr_free(args.values);
         return NULL;
index 77b926436ef41ae6dee1b99635f45a5f9dd90671..359482453e26fb974545458930f90084b29310cd 100644 (file)
@@ -372,6 +372,8 @@ static AstSolidifiedFunction generate_solidified_function(
     b32 header_only) {
 
     AstSolidifiedFunction solidified_func;
+    solidified_func.header_complete = 0;
+    solidified_func.body_complete = 0;
 
     // NOTE: Use the position of token if one was provided, otherwise just use NULL.
     OnyxFilePos poly_scope_pos = { 0 };
@@ -943,16 +945,20 @@ AstFunction* polymorphic_proc_build_only_header(AstPolyProc* pp, PolyProcLookupM
 
     ensure_polyproc_cache_is_created(pp);
 
+    AstSolidifiedFunction solidified_func;
+
     char* unique_key = build_poly_slns_unique_key(slns);
     if (bh_table_has(AstSolidifiedFunction, pp->concrete_funcs, unique_key)) {
-        AstSolidifiedFunction solidified_func = bh_table_get(AstSolidifiedFunction, pp->concrete_funcs, unique_key);
-        return solidified_func.func;
+        solidified_func = bh_table_get(AstSolidifiedFunction, pp->concrete_funcs, unique_key);
+
+    } else {
+        // NOTE: This function is only going to have the header of it correctly created.
+        // Nothing should happen to this function's body or else the original will be corrupted.
+        //                                                      - brendanfh 2021/01/10
+        solidified_func = generate_solidified_function(pp, slns, NULL, 1);
     }
 
-    // NOTE: This function is only going to have the header of it correctly created.
-    // Nothing should happen to this function's body or else the original will be corrupted.
-    //                                                      - brendanfh 2021/01/10
-    AstSolidifiedFunction solidified_func = generate_solidified_function(pp, slns, NULL, 1);
+    if (solidified_func.header_complete) return solidified_func.func;
 
     Entity func_header_entity = {
         .state = Entity_State_Resolve_Symbols,
@@ -968,6 +974,8 @@ AstFunction* polymorphic_proc_build_only_header(AstPolyProc* pp, PolyProcLookupM
         return NULL;
     }
 
+    solidified_func.header_complete = successful;
+
     // NOTE: Cache the function for later use, only if it didn't have errors in its header.
     bh_table_put(AstSolidifiedFunction, pp->concrete_funcs, unique_key, solidified_func);
     
@@ -1058,7 +1066,7 @@ void build_all_overload_options(bh_arr(OverloadOption) overloads, bh_imap* all_o
     }
 }
 
-AstTyped* find_matching_overload_by_arguments(bh_arr(OverloadOption) overloads, Arguments* param_args) {
+AstTyped* find_matching_overload_by_arguments(bh_arr(OverloadOption) overloads, Arguments* param_args, b32* should_yield) {
     Arguments args;
     arguments_clone(&args, param_args);
     arguments_ensure_length(&args, bh_arr_length(args.values) + bh_arr_length(args.named_values));
@@ -1084,7 +1092,15 @@ AstTyped* find_matching_overload_by_arguments(bh_arr(OverloadOption) overloads,
         // NOTE: Overload is not something that is known to be overloadable.
         if (overload == NULL) continue;
         if (overload->kind != Ast_Kind_Function) continue;
-        if (overload->type == NULL) continue;
+        if (overload->type == NULL) {
+            // If it was not possible to create the type for this procedure, tell the
+            // caller that this should yield and try again later.
+            if (should_yield) *should_yield = 1;
+
+            // return and not continue because if the overload that didn't have a type will
+            // work in the future, then it has to take precedence over the other options available.
+            return NULL;
+        }
         assert(overload->type->kind == Type_Kind_Function);
 
         // NOTE: If the arguments cannot be placed successfully in the parameters list