Added more yielding and remove ugly code
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 9 Nov 2021 03:22:20 +0000 (21:22 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 9 Nov 2021 03:22:20 +0000 (21:22 -0600)
include/astnodes.h
src/astnodes.c
src/checker.c
src/polymorph.c
src/symres.c
src/utils.c

index bdcac1b77695f91871e53526695c1a7b6ac7c338..1c5b052530499082ef567459da327a3bf078040d 100644 (file)
@@ -1009,9 +1009,8 @@ struct AstPolySolution {
 };
 
 struct AstSolidifiedFunction {
-    AstFunction* func;
-
-    b32 header_complete: 1;
+    AstFunction   *func;
+    struct Entity *func_header_entity;
 };
 
 struct AstPolyProc {
@@ -1145,6 +1144,7 @@ typedef enum EntityType {
     Entity_Type_Polymorphic_Proc,
     Entity_Type_Macro,
     Entity_Type_Foreign_Function_Header,
+    Entity_Type_Temp_Function_Header,    // Same as a Function_Header, except it disappears after it checks completely.
     Entity_Type_Function_Header,
     Entity_Type_Global_Header,
     Entity_Type_Process_Directive,
@@ -1219,7 +1219,6 @@ void entity_heap_remove_top(EntityHeap* entities);
 // If target_arr is null, the entities will be placed directly in the heap.
 void add_entities_for_node(bh_arr(Entity *)* target_arr, AstNode* node, Scope* scope, Package* package);
 
-b32  entity_bring_to_state(Entity* ent, EntityState state);
 void symres_entity(Entity* ent);
 void check_entity(Entity* ent);
 void emit_entity(Entity* ent);
@@ -1385,8 +1384,13 @@ void clone_function_body(bh_allocator a, AstFunction* dest, AstFunction* source)
 void promote_numlit_to_larger(AstNumLit* num);
 b32 convert_numlit_to_type(AstNumLit* num, Type* type);
 
+typedef enum TypeMatch {
+    TYPE_MATCH_SUCCESS,
+    TYPE_MATCH_FAILED,
+    TYPE_MATCH_YIELD,
+} TypeMatch;
 #define unify_node_and_type(node, type) (unify_node_and_type_((node), (type), 1))
-b32 unify_node_and_type_(AstTyped** pnode, Type* type, b32 permanent);
+TypeMatch unify_node_and_type_(AstTyped** pnode, Type* type, b32 permanent);
 Type* resolve_expression_type(AstTyped* node);
 i64 get_expression_integer_value(AstTyped* node);
 
@@ -1414,7 +1418,7 @@ void arguments_copy(Arguments* dest, Arguments* src);
 void arguments_clone(Arguments* dest, Arguments* src);
 void arguments_deep_clone(bh_allocator a, Arguments* dest, Arguments* src);
 void arguments_remove_baked(Arguments* args);
-b32 check_arguments_against_type(Arguments* args, TypeFunction* func_type, VarArgKind* va_kind,
+TypeMatch check_arguments_against_type(Arguments* args, TypeFunction* func_type, VarArgKind* va_kind,
                                  OnyxToken* location, char* func_name, struct OnyxError* error);
 i32 get_argument_buffer_size(TypeFunction* type, Arguments* args);
 
@@ -1431,6 +1435,7 @@ AstFunction* polymorphic_proc_lookup(AstPolyProc* pp, PolyProcLookupMethod pp_lo
 AstFunction* polymorphic_proc_solidify(AstPolyProc* pp, bh_arr(AstPolySolution) slns, OnyxToken* tkn);
 AstNode* polymorphic_proc_try_solidify(AstPolyProc* pp, bh_arr(AstPolySolution) slns, OnyxToken* tkn);
 AstFunction* polymorphic_proc_build_only_header(AstPolyProc* pp, PolyProcLookupMethod pp_lookup, ptr actual);
+AstFunction* polymorphic_proc_build_only_header_with_slns(AstPolyProc* pp, bh_arr(AstPolySolution) slns);
 
 void add_overload_option(bh_arr(OverloadOption)* poverloads, u64 precedence, AstTyped* overload);
 AstTyped* find_matching_overload_by_arguments(bh_arr(OverloadOption) overloads, Arguments* args, b32* should_yield);
index 0b246471508f3874c24968b745c7d1d4b04d61ae..5a5d6dc6a48253223d9feae3171a6a18ae04f338 100644 (file)
@@ -503,36 +503,35 @@ b32 convert_numlit_to_type(AstNumLit* num, Type* type) {
     return 0;
 }
 
-// NOTE: Returns 0 if it was not possible to make the types compatible.
 // TODO: This function should be able return a "yield" condition. There
 // are a couple cases that need to yield in order to be correct, like
 // polymorphic functions with a typeof for the return type.
-b32 unify_node_and_type_(AstTyped** pnode, Type* type, b32 permanent) {
+TypeMatch unify_node_and_type_(AstTyped** pnode, Type* type, b32 permanent) {
     AstTyped* node = *pnode;
-    if (type == NULL) return 0;
-    if (node == NULL) return 0;
+    if (type == NULL) return TYPE_MATCH_FAILED;
+    if (node == NULL) return TYPE_MATCH_FAILED;
 
     if (node->kind == Ast_Kind_Struct_Literal && node->type_node == NULL) {
-        if (node->entity != NULL) return 1;
+        if (node->entity != NULL) return TYPE_MATCH_SUCCESS;
         if (type->kind == Type_Kind_VarArgs) type = type->VarArgs.elem;
-        if (!type_is_sl_constructable(type)) return 0;
+        if (!type_is_sl_constructable(type)) return TYPE_MATCH_FAILED;
 
         // If this shouldn't make permanent changes and submit entities,
         // just assume that it works and don't submit the entities.
-        if (!permanent) return 1;
+        if (!permanent) return TYPE_MATCH_SUCCESS;
 
         node->type = type;
 
         add_entities_for_node(NULL, (AstNode *) node, NULL, NULL);
-        return 1;
+        return TYPE_MATCH_SUCCESS;
     }
 
     if (node->kind == Ast_Kind_Array_Literal && node->type == NULL) {
-        if (node->entity != NULL) return 1;
+        if (node->entity != NULL) return TYPE_MATCH_SUCCESS;
 
         // If this shouldn't make permanent changes and submit entities,
         // just assume that it works and don't submit the entities.
-        if (!permanent) return 1;
+        if (!permanent) return TYPE_MATCH_SUCCESS;
 
         Type* array_type=NULL;
         switch (type->kind) {
@@ -554,21 +553,21 @@ b32 unify_node_and_type_(AstTyped** pnode, Type* type, b32 permanent) {
         node->flags |= Ast_Flag_Array_Literal_Typed;
 
         add_entities_for_node(NULL, (AstNode *) node, NULL, NULL);
-        return 1;
+        return TYPE_MATCH_SUCCESS;
     }
 
     if (node->kind == Ast_Kind_Unary_Field_Access) {
         AstType* ast_type = type->ast_type;
         AstNode* resolved = try_symbol_resolve_from_node((AstNode *) ast_type, node->token);
-        if (resolved == NULL) return 0;
+        if (resolved == NULL) return TYPE_MATCH_FAILED;
 
         if (permanent) *pnode = (AstTyped *) resolved;
-        return 1;
+        return TYPE_MATCH_SUCCESS;
     }
 
     if (node->kind == Ast_Kind_Overloaded_Function) {
         AstTyped* func = find_matching_overload_by_type(((AstOverloadedFunction *) node)->overloads, type);
-        if (func == NULL) return 0;
+        if (func == NULL) return TYPE_MATCH_FAILED;
 
         // HACK: It feels like there should be a better place to flag that a procedure was definitely used.
         if (func->kind == Ast_Kind_Function)
@@ -580,10 +579,10 @@ b32 unify_node_and_type_(AstTyped** pnode, Type* type, b32 permanent) {
 
     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;
+        if (func == NULL) return TYPE_MATCH_FAILED;
 
         // FIXME: This is incorrect. It should actually yield and not return a failure.
-        if (func == (AstFunction *) &node_that_signals_a_yield) return 0;
+        if (func == (AstFunction *) &node_that_signals_a_yield) return TYPE_MATCH_YIELD;
 
         *pnode = (AstTyped *) func;
         node = *pnode;
@@ -592,14 +591,14 @@ b32 unify_node_and_type_(AstTyped** pnode, Type* type, b32 permanent) {
     // HACK: NullProcHack
     // The null_proc matches any procedure, and because of that, will cause a runtime error if you
     // try to call it.
-    if (type->kind == Type_Kind_Function && (node->flags & Ast_Flag_Proc_Is_Null) != 0) return 1;
+    if (type->kind == Type_Kind_Function && (node->flags & Ast_Flag_Proc_Is_Null) != 0) return TYPE_MATCH_SUCCESS;
 
     // The normal case where everything works perfectly.
     Type* node_type = get_expression_type(node);
-    if (types_are_compatible(node_type, type)) return 1;
+    if (types_are_compatible(node_type, type)) return TYPE_MATCH_SUCCESS;
 
     i64 any_id = type_build_from_ast(context.ast_alloc, builtin_any_type)->id;
-    if (node_type && node_type->id != any_id && type->id == any_id) return 1;
+    if (node_type && node_type->id != any_id && type->id == any_id) return TYPE_MATCH_SUCCESS;
 
     // Here are some of the ways you can unify a node with a type if the type of the
     // node does not match the given type:
@@ -612,7 +611,7 @@ b32 unify_node_and_type_(AstTyped** pnode, Type* type, b32 permanent) {
         && type->kind == Type_Kind_Function) {
 
         node_type->Function.return_type = type->Function.return_type;
-        return 1;
+        return TYPE_MATCH_SUCCESS;
     }
 
     // If the node is an auto cast (~~) node, then check to see if the cast is legal
@@ -621,11 +620,11 @@ b32 unify_node_and_type_(AstTyped** pnode, Type* type, b32 permanent) {
         char* dummy;
         Type* from_type = get_expression_type(((AstUnaryOp *) node)->expr);
         if (!from_type || !cast_is_legal(from_type, type, &dummy)) {
-            return 0;
+            return TYPE_MATCH_FAILED;
 
         } else {
             if (permanent) ((AstUnaryOp *) node)->type = type;
-            return 1;
+            return TYPE_MATCH_SUCCESS;
         }
     }
 
@@ -643,47 +642,53 @@ b32 unify_node_and_type_(AstTyped** pnode, Type* type, b32 permanent) {
                 *pnode = (AstTyped *) make_cast(context.ast_alloc, node, type);
             }
 
-            return legal;
+            return legal ? TYPE_MATCH_SUCCESS : TYPE_MATCH_FAILED;
         }
     }
 
     // If the node is a numeric literal, try to convert it to the destination type.
     else if (node->kind == Ast_Kind_NumLit) {
-        if (convert_numlit_to_type((AstNumLit *) node, type)) return 1;
+        if (convert_numlit_to_type((AstNumLit *) node, type)) return TYPE_MATCH_SUCCESS;
     }
 
     // If the node is a compound expression, and it doesn't have a type created,
     // recursive call this function with the individual components of the compound
     // expression.
     else if (node->kind == Ast_Kind_Compound) {
-        if (type->kind != Type_Kind_Compound) return 0;
+        if (type->kind != Type_Kind_Compound) return TYPE_MATCH_FAILED;
 
         AstCompound* compound = (AstCompound *) node;
 
         u32 expr_count = bh_arr_length(compound->exprs);
-        if (expr_count != type->Compound.count) return 0;
+        if (expr_count != type->Compound.count) return TYPE_MATCH_FAILED;
 
         fori (i, 0, (i64) expr_count) {
-            if (!unify_node_and_type_(&compound->exprs[i], type->Compound.types[i], permanent)) return 0;
+            TypeMatch tm = unify_node_and_type_(&compound->exprs[i], type->Compound.types[i], permanent);
+            if (tm != TYPE_MATCH_SUCCESS) {
+                return tm;
+            }
         }
 
         compound->type = type_build_compound_type(context.ast_alloc, compound);
         
-        return 1;
+        return TYPE_MATCH_SUCCESS;
     }
 
     else if (node->kind == Ast_Kind_If_Expression) {
         AstIfExpression* if_expr = (AstIfExpression *) node;
 
-        b32 true_success  = unify_node_and_type_(&if_expr->true_expr,  type, permanent);
-        b32 false_success = unify_node_and_type_(&if_expr->false_expr, type, permanent);
+        TypeMatch true_success  = unify_node_and_type_(&if_expr->true_expr,  type, permanent);
+        TypeMatch false_success = unify_node_and_type_(&if_expr->false_expr, type, permanent);
 
-        if (true_success && false_success) {
+        if (true_success == TYPE_MATCH_SUCCESS && false_success == TYPE_MATCH_SUCCESS) {
             if (permanent) if_expr->type = type;
-            return 1;
+            return TYPE_MATCH_SUCCESS;
+
+        } else if (true_success == TYPE_MATCH_FAILED || false_success == TYPE_MATCH_FAILED) {
+            return TYPE_MATCH_FAILED;
 
         } else {
-            return 0;
+            return TYPE_MATCH_YIELD;
         }
     }
 
@@ -692,7 +697,7 @@ b32 unify_node_and_type_(AstTyped** pnode, Type* type, b32 permanent) {
         return unify_node_and_type_(&alias->alias, type, permanent);
     }
 
-    return 0;
+    return TYPE_MATCH_FAILED;
 }
 
 Type* resolve_expression_type(AstTyped* node) {
index 8be7267d7470ba4e71d2af0c98523e838ffcbb36..cecf4f97194605df866d6415da12611f71638adb 100644 (file)
     return Check_Error; \
     } while (0)
 
+#define TYPE_CHECK_(expr, type, type_name)                                                      \
+    TypeMatch type_name;                                                                        \
+    type_name = unify_node_and_type(expr, type);                                                \
+    if (type_name == TYPE_MATCH_YIELD) YIELD((*expr)->token->pos, "Waiting on type checking."); \
+    if (type_name == TYPE_MATCH_FAILED)
+
+#define CONCAT(a, b) a##_##b
+#define DEFER_LINE(a, line) CONCAT(a, line)
+#define TYPE_CHECK(expr, type) TYPE_CHECK_(expr, type, DEFER_LINE(tc, __LINE__))
+
 typedef enum CheckStatus {
     Check_Success,  // The node was successfully checked with out errors
     Check_Complete, // The node is done processing
@@ -77,6 +87,7 @@ CheckStatus check_global(AstGlobal* global);
 CheckStatus check_function(AstFunction* func);
 CheckStatus check_overloaded_function(AstOverloadedFunction* func);
 CheckStatus check_struct(AstStructType* s_node);
+CheckStatus check_temp_function_header(AstFunction* func);
 CheckStatus check_function_header(AstFunction* func);
 CheckStatus check_memres_type(AstMemRes* memres);
 CheckStatus check_memres(AstMemRes* memres);
@@ -116,7 +127,7 @@ CheckStatus check_return(AstReturn* retnode) {
             return Check_Success;
         }
 
-        if (!unify_node_and_type(&retnode->expr, *expected_return_type)) {
+        TYPE_CHECK(&retnode->expr, *expected_return_type) {
             ERROR_(retnode->token->pos,
                     "Expected to return a value of type '%s', returning value of type '%s'.",
                     type_get_name(*expected_return_type),
@@ -334,7 +345,7 @@ CheckStatus check_switch(AstSwitch* switchnode) {
                 continue;
             }
 
-            if (!unify_node_and_type(value, resolved_expr_type)) {
+            TYPE_CHECK(value, resolved_expr_type) {
                 OnyxToken* tkn = sc->block->token;
                 if ((*value)->token) tkn = (*value)->token;
 
@@ -566,12 +577,15 @@ CheckStatus check_call(AstCall** pcall) {
     }
 
     OnyxError error;
-    if (!check_arguments_against_type(&call->args, &callee->type->Function, &call->va_kind,
-            call->token, get_function_name(callee), &error)) {
+    TypeMatch tm = check_arguments_against_type(&call->args, &callee->type->Function, &call->va_kind,
+                                                call->token, get_function_name(callee), &error);
+    if (tm == TYPE_MATCH_FAILED) {
         onyx_submit_error(error);
         return Check_Error;
     }
 
+    if (tm == TYPE_MATCH_YIELD) YIELD(call->token->pos, "Waiting on argument type checking.");
+
     call->flags   |= Ast_Flag_Has_Been_Checked;
     callee->flags |= Ast_Flag_Function_Used;
 
@@ -726,7 +740,7 @@ CheckStatus check_binaryop_assignment(AstBinaryOp** pbinop) {
         }
     }
 
-    if (!unify_node_and_type(&binop->right, binop->left->type)) {
+    TYPE_CHECK(&binop->right, binop->left->type) {
         ERROR_(binop->token->pos,
                 "Cannot assign value of type '%s' to a '%s'.",
                 node_get_type_name(binop->right),
@@ -812,8 +826,8 @@ CheckStatus check_binaryop_compare(AstBinaryOp** pbinop) {
         b32 right_ac = node_is_auto_cast((AstNode *) binop->right);
 
         if (left_ac && right_ac) ERROR(binop->token->pos, "Cannot have auto cast on both sides of binary operator.");
-        else if (unify_node_and_type(&binop->left, rtype));
-        else if (unify_node_and_type(&binop->right, ltype));
+        else if (unify_node_and_type(&binop->left, rtype) == TYPE_MATCH_SUCCESS);  // @TODO: Should check for yield
+        else if (unify_node_and_type(&binop->right, ltype) == TYPE_MATCH_SUCCESS); // @TODO: Should check for yield
         else {
             ERROR_(binop->token->pos,
                     "Cannot compare '%s' to '%s'.",
@@ -903,8 +917,8 @@ CheckStatus check_binaryop(AstBinaryOp** pbinop) {
 
     // :UnaryFieldAccessIsGross
     if (binop->left->kind == Ast_Kind_Unary_Field_Access || binop->right->kind == Ast_Kind_Unary_Field_Access) {
-        if      (unify_node_and_type(&binop->left, binop->right->type));
-        else if (unify_node_and_type(&binop->right, binop->left->type));
+        if      (unify_node_and_type(&binop->left, binop->right->type) == TYPE_MATCH_SUCCESS); // @TODO: Should check for yield.
+        else if (unify_node_and_type(&binop->right, binop->left->type) == TYPE_MATCH_SUCCESS); // @TODO: Should check for yield.
         else {
             report_bad_binaryop(binop);
             return Check_Error;
@@ -973,8 +987,8 @@ CheckStatus check_binaryop(AstBinaryOp** pbinop) {
         if (left_ac && right_ac) {
             ERROR(binop->token->pos, "Cannot have auto cast on both sides of binary operator.");
         }
-        else if (unify_node_and_type(&binop->left, binop->right->type));
-        else if (unify_node_and_type(&binop->right, binop->left->type));
+        else if (unify_node_and_type(&binop->left, binop->right->type) == TYPE_MATCH_SUCCESS); // @TODO: Should check for yield.
+        else if (unify_node_and_type(&binop->right, binop->left->type) == TYPE_MATCH_SUCCESS); // @TODO: Should check for yield.
         else {
             ERROR_(binop->token->pos,
                     "Mismatched types for binary operation '%s'. left: '%s', right: '%s'.",
@@ -1130,7 +1144,7 @@ CheckStatus check_struct_literal(AstStructLiteral* sl) {
             YIELD_((*actual)->token->pos, "Trying to resolve type of expression for member '%s'.", smem.name);
         }
 
-        if (!unify_node_and_type(actual, formal)) {
+        TYPE_CHECK(actual, formal) {
             ERROR_(sl->token->pos,
                     "Mismatched types for %d%s member named '%s', expected '%s', got '%s'.",
                     i + 1, bh_num_suffix(i + 1),
@@ -1187,7 +1201,7 @@ CheckStatus check_array_literal(AstArrayLiteral* al) {
 
         al->flags &= ((*expr)->flags & Ast_Flag_Comptime) | (al->flags &~ Ast_Flag_Comptime);
 
-        if (!unify_node_and_type(expr, elem_type)) {
+        TYPE_CHECK(expr, elem_type) {
             ERROR_((*expr)->token->pos, "Mismatched types for value of in array, expected '%s', got '%s'.",
                 type_get_name(elem_type),
                 node_get_type_name(*expr));
@@ -1206,14 +1220,14 @@ CheckStatus check_range_literal(AstRangeLiteral** prange) {
     StructMember smem;
 
     type_lookup_member(expected_range_type, "low", &smem);
-    if (!unify_node_and_type(&range->low, smem.type)) {
+    TYPE_CHECK(&range->low, smem.type) {
         ERROR_(range->token->pos,
             "Expected left side of range to be a 32-bit integer, got '%s'.",
             node_get_type_name(range->low));
     }
 
     type_lookup_member(expected_range_type, "high", &smem);
-    if (!unify_node_and_type(&range->high, smem.type)) {
+    TYPE_CHECK(&range->high, smem.type) {
         ERROR_(range->token->pos,
             "Expected right side of range to be a 32-bit integer, got '%s'.",
             node_get_type_name(range->high));
@@ -1244,7 +1258,7 @@ CheckStatus check_if_expression(AstIfExpression* if_expr) {
     CHECK(expression, &if_expr->true_expr);
     CHECK(expression, &if_expr->false_expr);
 
-    if (!unify_node_and_type(&if_expr->cond, &basic_types[Basic_Kind_Bool])) {
+    TYPE_CHECK(&if_expr->cond, &basic_types[Basic_Kind_Bool]) {
         ERROR_(if_expr->token->pos, "If-expression expected boolean for condition, got '%s'.",
             type_get_name(if_expr->cond->type));
     }
@@ -1746,7 +1760,7 @@ CheckStatus check_insert_directive(AstDirectiveInsert** pinsert) {
 
     Type* code_type = type_build_from_ast(context.ast_alloc, builtin_code_type);
 
-    if (!unify_node_and_type(&insert->code_expr, code_type)) {
+    TYPE_CHECK(&insert->code_expr, code_type) {
         ERROR_(insert->token->pos, "#insert expected a value of type 'Code', got '%s'.",
             type_get_name(insert->code_expr->type));
     }
@@ -1976,7 +1990,7 @@ CheckStatus check_struct_defaults(AstStructType* s_node) {
         if ((*smem)->initial_value && *(*smem)->initial_value) {
             CHECK(expression, (*smem)->initial_value);
 
-            if (!unify_node_and_type((*smem)->initial_value, (*smem)->type)) {
+            TYPE_CHECK((*smem)->initial_value, (*smem)->type) {
                 ERROR_((*(*smem)->initial_value)->token->pos,
                         "Mismatched type for initial value, expected '%s', got '%s'.",
                         type_get_name((*smem)->type),
@@ -2002,6 +2016,11 @@ CheckStatus check_struct_defaults(AstStructType* s_node) {
     return Check_Success;
 }
 
+CheckStatus check_temp_function_header(AstFunction* func) {
+    CHECK(function_header, func);
+    return Check_Complete;
+}
+
 CheckStatus check_function_header(AstFunction* func) {
     //if (func->entity_body && func->entity_body->state < Entity_State_Check_Types)
     //    YIELD(func->token->pos, "Waiting for function body to complete symbol resolution to check header.");
@@ -2116,7 +2135,7 @@ CheckStatus check_memres(AstMemRes* memres) {
 
         if (memres->type != NULL) {
             Type* memres_type = memres->type;
-            if (!unify_node_and_type(&memres->initial_value, memres_type)) {
+            TYPE_CHECK(&memres->initial_value, memres_type) {
                 ERROR_(memres->token->pos,
                         "Cannot assign value of type '%s' to a '%s'.",
                         node_get_type_name(memres->initial_value),
@@ -2357,6 +2376,7 @@ void check_entity(Entity* ent) {
     switch (ent->type) {
         case Entity_Type_Foreign_Function_Header:
         case Entity_Type_Function_Header:          cs = check_function_header(ent->function); break;
+        case Entity_Type_Temp_Function_Header:     cs = check_temp_function_header(ent->function); break;
         case Entity_Type_Function:                 cs = check_function(ent->function); break;
         case Entity_Type_Overloaded_Function:      cs = check_overloaded_function(ent->overloaded_function); break;
         case Entity_Type_Global:                   cs = check_global(ent->global); break;
index 2390071ec67caa7746fd2373609d282b54f52996..f98c45be6d2afcccba29e33cbfb4aecf9345ca46 100644 (file)
@@ -106,9 +106,6 @@ static b32 add_solidified_function_entities(AstSolidifiedFunction solidified_fun
         .scope = solidified_func.func->poly_scope,
     };
 
-    entity_bring_to_state(&func_header_entity, Entity_State_Code_Gen);
-    if (onyx_has_errors()) return 0;
-
     Entity func_entity = {
         .state = Entity_State_Resolve_Symbols,
         .type = Entity_Type_Function,
@@ -120,6 +117,7 @@ static b32 add_solidified_function_entities(AstSolidifiedFunction solidified_fun
     Entity* entity_header = entity_heap_insert(&context.entities, func_header_entity);
     Entity* entity_body   = entity_heap_insert(&context.entities, func_entity);
 
+    solidified_func.func_header_entity  = entity_header;
     solidified_func.func->entity_header = entity_header;
     solidified_func.func->entity_body   = entity_body;
 
@@ -137,7 +135,7 @@ static AstSolidifiedFunction generate_solidified_function(
     b32 header_only) {
 
     AstSolidifiedFunction solidified_func;
-    solidified_func.header_complete = 0;
+    solidified_func.func_header_entity = NULL;
 
     // NOTE: Use the position of token if one was provided, otherwise just use NULL.
     OnyxFilePos poly_scope_pos = { 0 };
@@ -502,7 +500,8 @@ static void solve_for_polymorphic_param_value(PolySolveResult* resolved, AstPoly
             value_to_use = (AstTyped *) get_function_from_node((AstNode *) value);
         }
 
-        if (!unify_node_and_type(&value_to_use, param->type)) {
+        TypeMatch tm = unify_node_and_type(&value_to_use, param->type);
+        if (tm == TYPE_MATCH_FAILED) {
             if (err_msg) *err_msg = bh_aprintf(global_scratch_allocator,
                     "The procedure '%s' expects a value of type '%s' for baked %d%s parameter, got '%s'.",
                     get_function_name(pp->base_func),
@@ -513,6 +512,8 @@ static void solve_for_polymorphic_param_value(PolySolveResult* resolved, AstPoly
             return;
         }
 
+        if (tm == TYPE_MATCH_YIELD) flag_to_yield = 1;
+
         *resolved = ((PolySolveResult) { PSK_Value, value });
     }
 
@@ -605,6 +606,7 @@ AstFunction* polymorphic_proc_lookup(AstPolyProc* pp, PolyProcLookupMethod pp_lo
     if (slns == NULL) {
         if (flag_to_yield) {
             flag_to_yield = 0;
+            bh_arr_free(slns);
             return (AstFunction *) &node_that_signals_a_yield;
         }
 
@@ -647,12 +649,9 @@ AstFunction* polymorphic_proc_solidify(AstPolyProc* pp, bh_arr(AstPolySolution)
     // NOTE: Cache the function for later use, reducing duplicate functions.
     bh_table_put(AstSolidifiedFunction, pp->concrete_funcs, unique_key, solidified_func);
 
-    if (!add_solidified_function_entities(solidified_func, 0)) {
-        onyx_report_error(tkn->pos, "Error in polymorphic procedure header generated from this call site.");
-        return NULL;
-    }
+    add_solidified_function_entities(solidified_func, 0);
 
-    return solidified_func.func;
+    return (AstFunction *) &node_that_signals_a_yield;
 }
 
 // NOTE: This can return either a AstFunction or an AstPolyProc, depending if enough parameters were
@@ -712,6 +711,10 @@ AstFunction* polymorphic_proc_build_only_header(AstPolyProc* pp, PolyProcLookupM
 
     ensure_polyproc_cache_is_created(pp);
 
+    return polymorphic_proc_build_only_header_with_slns(pp, slns);
+}
+
+AstFunction* polymorphic_proc_build_only_header_with_slns(AstPolyProc* pp, bh_arr(AstPolySolution) slns) {
     AstSolidifiedFunction solidified_func;
 
     char* unique_key = build_poly_slns_unique_key(slns);
@@ -725,36 +728,23 @@ AstFunction* polymorphic_proc_build_only_header(AstPolyProc* pp, PolyProcLookupM
         solidified_func = generate_solidified_function(pp, slns, NULL, 1);
     }
 
-    if (solidified_func.header_complete) return solidified_func.func;
+    if (solidified_func.func_header_entity && solidified_func.func_header_entity->state == Entity_State_Finalized) return solidified_func.func;
 
     Entity func_header_entity = {
         .state = Entity_State_Resolve_Symbols,
-        .type = Entity_Type_Function_Header,
+        .type = Entity_Type_Temp_Function_Header,
         .function = solidified_func.func,
         .package = NULL,
         .scope = solidified_func.func->poly_scope,
     };
 
-    // HACK: Everything with entity_bring_to_state is a big hack...
-    // The idea is that instead of making the caller yield for a simple procedure header,
-    // do a single pass of trying to solve for the parameter types and return types.
-    // The big missing piece of the entity pumping system is that once an entity is
-    // entered into the system, it cannot be removed and it is assumed it is going to
-    // be used in the final binary. This is obviously not always the case, but that
-    // is how the system currently works.
-    b32 successful = entity_bring_to_state(&func_header_entity, Entity_State_Code_Gen);
-    if (onyx_has_errors()) {
-        onyx_errors_print();
-        onyx_clear_errors();
-        return NULL;
-    }
-
-    solidified_func.header_complete = successful;
+    Entity* func_header_entity_ptr = entity_heap_insert(&context.entities, func_header_entity);
+    solidified_func.func_header_entity = func_header_entity_ptr;
 
-    // NOTE: Cache the function for later use, only if it didn't have errors in its header.
+    // NOTE: Cache the function for later use.
     bh_table_put(AstSolidifiedFunction, pp->concrete_funcs, unique_key, solidified_func);
     
-    return solidified_func.func;
+    return (AstFunction *) &node_that_signals_a_yield;
 }
 
 //
index 0b2d427aa4df43628d26f610e0e4ddbc42dd1aad..38e5937637bec2b5c20806df8c31174a9e3d3b66 100644 (file)
@@ -751,6 +751,10 @@ static SymresStatus symres_directive_solidify(AstDirectiveSolidify** psolid) {
     }
 
     solid->resolved_proc = polymorphic_proc_try_solidify(solid->poly_proc, solid->known_polyvars, solid->token);
+    if (solid->resolved_proc == (AstFunction *) &node_that_signals_a_yield) {
+        solid->resolved_proc = NULL;
+        return Symres_Yield_Macro;
+    }
 
     // NOTE: Not a DirectiveSolidify.
     *psolid = (AstDirectiveSolidify *) solid->resolved_proc;
@@ -1241,6 +1245,7 @@ void symres_entity(Entity* ent) {
         case Entity_Type_Static_If:               ss = symres_static_if(ent->static_if); break;
 
         case Entity_Type_Foreign_Function_Header:
+        case Entity_Type_Temp_Function_Header:
         case Entity_Type_Function_Header:         ss = symres_function_header(ent->function); break;
         case Entity_Type_Function:                ss = symres_function(ent->function);        break;
 
index 537044b3632e7cd342311e46f811bf1c4798227b..82a438680f90db774b3ef25d22cfcab55fc246ec 100644 (file)
@@ -364,6 +364,13 @@ 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 == (AstFunction *) &node_that_signals_a_yield) {
+            // 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 NULL;
+        }
         if (overload->kind != Ast_Kind_Function) continue;
         if (overload->type == NULL) {
             // If it was not possible to create the type for this procedure, tell the
@@ -383,10 +390,16 @@ AstTyped* find_matching_overload_by_arguments(bh_arr(OverloadOption) overloads,
         if (!fill_in_arguments(&args, (AstNode *) overload, NULL)) continue;
         
         VarArgKind va_kind;
-        if (check_arguments_against_type(&args, &overload->type->Function, &va_kind, NULL, NULL, NULL)) {
+        TypeMatch tm = check_arguments_against_type(&args, &overload->type->Function, &va_kind, NULL, NULL, NULL);
+        if (tm == TYPE_MATCH_SUCCESS) {
             matched_overload = node;
             break;
         }
+
+        if (tm == TYPE_MATCH_YIELD) {
+            if (should_yield) *should_yield = 1;
+            return NULL;
+        }
     }
 
     bh_imap_free(&all_overloads);
@@ -407,10 +420,15 @@ AstTyped* find_matching_overload_by_type(bh_arr(OverloadOption) overloads, Type*
         AstTyped* node = (AstTyped *) entry->key;
         if (node->kind == Ast_Kind_Overloaded_Function) continue;
 
-        if (unify_node_and_type(&node, type)) {
+        TypeMatch tm = unify_node_and_type(&node, type);
+        if (tm == TYPE_MATCH_SUCCESS) {
             matched_overload = node;
             break;
         }
+
+        if (tm == TYPE_MATCH_YIELD) {
+            return (AstTyped *) &node_that_signals_a_yield;
+        }
     }
     
     bh_imap_free(&all_overloads);
@@ -527,38 +545,7 @@ AstFunction* macro_resolve_header(AstMacro* macro, Arguments* args, OnyxToken* c
             }
 
             // CLEANUP Copy'n'pasted from polymorphic_proc_build_only_header
-            AstSolidifiedFunction solidified_func;
-
-            char* unique_key = build_poly_slns_unique_key(slns);
-            if (bh_table_has(AstSolidifiedFunction, pp->concrete_funcs, unique_key)) {
-                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, callsite, 1);
-            }
-
-            if (solidified_func.header_complete) return solidified_func.func;
-
-            Entity func_header_entity = {
-                .state = Entity_State_Resolve_Symbols,
-                .type = Entity_Type_Function_Header,
-                .function = solidified_func.func,
-                .package = NULL,
-                .scope = solidified_func.func->poly_scope,
-            };
-
-            b32 successful = entity_bring_to_state(&func_header_entity, Entity_State_Code_Gen);
-            if (onyx_has_errors()) return NULL;
-
-            solidified_func.header_complete = successful;
-
-            bh_table_put(AstSolidifiedFunction, pp->concrete_funcs, unique_key, solidified_func);
-            if (!successful) return (AstFunction *) &node_that_signals_a_yield;
-
-            return solidified_func.func;
+            return polymorphic_proc_build_only_header_with_slns(pp, slns);
         }
 
         default: assert(("Bad macro body type.", 0));
@@ -567,27 +554,6 @@ AstFunction* macro_resolve_header(AstMacro* macro, Arguments* args, OnyxToken* c
     return NULL;
 }
 
-b32 entity_bring_to_state(Entity* ent, EntityState state) {
-    EntityState last_state = ent->state;
-
-    while (ent->state != state) {
-        switch (ent->state) {
-            case Entity_State_Resolve_Symbols: symres_entity(ent); break;
-            case Entity_State_Check_Types:     check_entity(ent);  break;
-            case Entity_State_Code_Gen:        emit_entity(ent);   break;
-
-            default: return 0;
-        }
-
-        if (ent->state == last_state) return 0;
-        last_state = ent->state;
-
-        if (onyx_has_errors()) return 0;
-    }
-
-    return 1;
-}
-
 
 //
 // Arguments resolving
@@ -788,8 +754,8 @@ typedef enum ArgState {
     AS_Expecting_Untyped_VA,
 } ArgState;
 
-b32 check_arguments_against_type(Arguments* args, TypeFunction* func_type, VarArgKind* va_kind,
-                                 OnyxToken* location, char* func_name, OnyxError* error) {
+TypeMatch check_arguments_against_type(Arguments* args, TypeFunction* func_type, VarArgKind* va_kind,
+                                       OnyxToken* location, char* func_name, OnyxError* error) {
     b32 permanent = location != NULL;
     if (func_name == NULL) func_name = "UNKNOWN FUNCTION";
 
@@ -821,7 +787,9 @@ b32 check_arguments_against_type(Arguments* args, TypeFunction* func_type, VarAr
                 if (arg_pos >= (u32) bh_arr_length(arg_arr)) goto type_checking_done;
 
                 assert(arg_arr[arg_pos]->kind == Ast_Kind_Argument);
-                if (!unify_node_and_type_(&arg_arr[arg_pos]->value, formal_params[arg_pos], permanent)) {
+                TypeMatch tm = unify_node_and_type_(&arg_arr[arg_pos]->value, formal_params[arg_pos], permanent);
+                if (tm == TYPE_MATCH_YIELD) return tm;
+                if (tm == TYPE_MATCH_FAILED) {
                     if (error != NULL) {
                         error->pos = arg_arr[arg_pos]->token->pos,
                         error->text = bh_aprintf(global_heap_allocator,
@@ -832,7 +800,7 @@ b32 check_arguments_against_type(Arguments* args, TypeFunction* func_type, VarAr
                                 bh_num_suffix(arg_pos + 1),
                                 node_get_type_name(arg_arr[arg_pos]->value));
                     }
-                    return 0;
+                    return tm;
                 }
 
                 if (arg_arr[arg_pos]->value->type && arg_arr[arg_pos]->value->type->id != any_type_id && formal_params[arg_pos]->id == any_type_id) {
@@ -856,7 +824,7 @@ b32 check_arguments_against_type(Arguments* args, TypeFunction* func_type, VarAr
                             error->pos = arg_arr[arg_pos]->token->pos;
                             error->text = "Unable to resolve type of argument.";
                         }
-                        return 0;
+                        return TYPE_MATCH_FAILED;
                     }
 
                     arg_arr[arg_pos]->va_kind = VA_Kind_Any; 
@@ -866,7 +834,9 @@ b32 check_arguments_against_type(Arguments* args, TypeFunction* func_type, VarAr
                 *va_kind = VA_Kind_Typed;
 
                 assert(arg_arr[arg_pos]->kind == Ast_Kind_Argument);
-                if (!unify_node_and_type_(&arg_arr[arg_pos]->value, variadic_type, permanent)) {
+                TypeMatch tm = unify_node_and_type_(&arg_arr[arg_pos]->value, variadic_type, permanent);
+                if (tm == TYPE_MATCH_YIELD) return tm;
+                if (tm == TYPE_MATCH_FAILED) {
                     if (error != NULL) {
                         error->pos = arg_arr[arg_pos]->token->pos,
                         error->text = bh_aprintf(global_heap_allocator,
@@ -875,7 +845,7 @@ b32 check_arguments_against_type(Arguments* args, TypeFunction* func_type, VarAr
                             type_get_name(variadic_type),
                             node_get_type_name(arg_arr[arg_pos]->value));
                     }
-                    return 0;
+                    return tm;
                 }
 
                 arg_arr[arg_pos]->va_kind = VA_Kind_Typed;
@@ -894,7 +864,7 @@ b32 check_arguments_against_type(Arguments* args, TypeFunction* func_type, VarAr
                         error->pos = arg_arr[arg_pos]->token->pos;
                         error->text = "Unable to resolve type for argument.";
                     }
-                    return 0;
+                    return TYPE_MATCH_FAILED;
                 }
 
                 arg_arr[arg_pos]->va_kind = VA_Kind_Untyped;
@@ -911,7 +881,7 @@ type_checking_done:
             error->pos = location->pos;
             error->text = "Too few arguments to function call.";
         }
-        return 0;
+        return TYPE_MATCH_FAILED;
     }
 
     if (arg_pos < (u32) arg_count) {
@@ -919,10 +889,10 @@ type_checking_done:
             error->pos = location->pos;
             error->text = bh_aprintf(global_heap_allocator, "Too many arguments to function call. %d %d", arg_pos, arg_count);
         }
-        return 0;
+        return TYPE_MATCH_FAILED;
     }
 
-    return 1;
+    return TYPE_MATCH_SUCCESS;
 }