};
struct AstSolidifiedFunction {
- AstFunction* func;
-
- b32 header_complete: 1;
+ AstFunction *func;
+ struct Entity *func_header_entity;
};
struct AstPolyProc {
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,
// 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);
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);
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);
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);
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) {
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)
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;
// 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:
&& 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
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;
}
}
*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;
}
}
return unify_node_and_type_(&alias->alias, type, permanent);
}
- return 0;
+ return TYPE_MATCH_FAILED;
}
Type* resolve_expression_type(AstTyped* node) {
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
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);
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),
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;
}
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;
}
}
- 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),
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'.",
// :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;
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'.",
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),
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));
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));
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));
}
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));
}
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),
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.");
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),
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;
.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,
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;
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 };
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),
return;
}
+ if (tm == TYPE_MATCH_YIELD) flag_to_yield = 1;
+
*resolved = ((PolySolveResult) { PSK_Value, value });
}
if (slns == NULL) {
if (flag_to_yield) {
flag_to_yield = 0;
+ bh_arr_free(slns);
return (AstFunction *) &node_that_signals_a_yield;
}
// 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
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);
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;
}
//
}
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;
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;
// 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
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);
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);
}
// 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));
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
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";
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,
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) {
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;
*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,
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;
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;
error->pos = location->pos;
error->text = "Too few arguments to function call.";
}
- return 0;
+ return TYPE_MATCH_FAILED;
}
if (arg_pos < (u32) arg_count) {
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;
}