CheckStatus check_method_call(AstBinaryOp** pmcall) {
AstBinaryOp* mcall = *pmcall;
- CHECK(expression, &mcall->left);
- if (mcall->left->type == NULL) YIELD(mcall->token->pos, "Trying to resolve type of left hand side.");
-
- AstTyped* implicit_argument = mcall->left;
-
- // Symbol resolution should have ensured that this is call node.
- AstCall* call_node = (AstCall *) mcall->right;
- assert(call_node->kind == Ast_Kind_Call);
// :Idempotency
if ((mcall->flags & Ast_Flag_Has_Been_Checked) == 0) {
+ CHECK(expression, &mcall->left);
+ if (mcall->left->type == NULL) YIELD(mcall->token->pos, "Trying to resolve type of left hand side.");
+
+ AstTyped* implicit_argument = mcall->left;
+ AstCall* call_node = (AstCall *) mcall->right;
+
+ // Symbol resolution should have ensured that this is call node.
+ assert(call_node->kind == Ast_Kind_Call);
+
// Implicitly take the address of the value if it is not already a pointer type.
// This could be weird to think about semantically so some testing with real code
// would be good. - brendanfh 2020/02/05
*pmcall = (AstBinaryOp *) mcall->right;
mcall->right->next = mcall->next;
+ mcall->flags |= Ast_Flag_Has_Been_Checked;
}
- mcall->flags |= Ast_Flag_Has_Been_Checked;
CHECK(call, (AstCall **) pmcall);
return Check_Success;
case PSK_Value:
// CLEANUP: Maybe clone this?
- assert(sln->value->flags & Ast_Flag_Comptime);
+ // assert(sln->value->flags & Ast_Flag_Comptime);
+ if ((sln->value->flags & Ast_Flag_Comptime) == 0) {
+ onyx_report_error(sln->value->token->pos, Error_Critical, "Expected value to be compile time known.");
+ return;
+ }
+
node = (AstNode *) sln->value;
break;
}
// the type that the parameter but be.
static void solve_for_polymorphic_param_type(PolySolveResult* resolved, AstFunction* func, AstPolyParam* param, PolyProcLookupMethod pp_lookup, ptr actual, char** err_msg) {
Type* actual_type = NULL;
+ b32 can_strip_pointer = 0;
switch (pp_lookup) {
case PPLM_By_Arguments: {
if (typed_param->kind != Ast_Kind_Argument) goto skip_nested_polymorph_case;
AstTyped* potential = ((AstArgument *) typed_param)->value;
+
+ if (potential->kind == Ast_Kind_Address_Of) {
+ AstAddressOf *aof = (AstAddressOf *) potential;
+ if (aof->can_be_removed) {
+ can_strip_pointer = 1;
+ }
+ }
+
if (potential->kind != Ast_Kind_Polymorphic_Proc) goto skip_nested_polymorph_case;
if (param->idx >= (u32) bh_arr_length(func->params)) goto skip_nested_polymorph_case;
}
PolySolveResult res = solve_poly_type(param->poly_sym, param->type_expr, actual_type);
+
+ // If we are trying to match against an "address of" node that was
+ // placed because of a method call, there's a small change that the
+ // address of is unnecessary and can be removed. This happens in
+ // unify_node_and_type, but because that relies on knowning the type,
+ // it cannot happen until after polymorphic arguments are determined.
+ // This case simply tries matching everything again, but without the
+ // outer most pointer node. If everything succeeds, the pointer node
+ // will be removed when the actual value is checked later.
+ if (res.kind == PSK_Undefined && can_strip_pointer) {
+ res = solve_poly_type(param->poly_sym, param->type_expr, actual_type->Pointer.elem);
+ }
+
if (res.kind == PSK_Undefined) {
*err_msg = bh_aprintf(global_scratch_allocator,
"Unable to solve for polymorphic variable '%b', given the type '%s'.",
//
// foo->member_function(...)
static SymresStatus symres_method_call(AstBinaryOp** mcall) {
- SYMRES(expression, &(*mcall)->left);
- if ((*mcall)->left == NULL) return Symres_Error;
-
// :EliminatingSymres
if (((*mcall)->flags & Ast_Flag_Has_Been_Symres) == 0) {
+ SYMRES(expression, &(*mcall)->left);
+ if ((*mcall)->left == NULL) return Symres_Error;
+
if ((*mcall)->right->kind != Ast_Kind_Call) {
onyx_report_error((*mcall)->token->pos, Error_Critical, "'->' expected procedure call on right side.");
return Symres_Error;
AstNode* subst = (AstNode *) expansion;
if (template->type->Function.return_type != &basic_types[Basic_Kind_Void]) {
+ expansion->rules = Block_Rule_Do_Block;
+
AstDoBlock* doblock = (AstDoBlock *) onyx_ast_node_new(context.ast_alloc, sizeof(AstDoBlock), Ast_Kind_Do_Block);
doblock->token = expansion->token;
doblock->block = expansion;
return new_list;
}
+find :: #match #local {}
+
+#overload
find :: (arr: [] $T, value: T) -> i32 {
for i: arr.count {
if value == arr.data[i] do return i;
return -1;
}
+#overload
+find :: macro (arr: [] $T, pred: Code) -> i32 {
+ for i: arr.count {
+ it := ^arr[i];
+ if #unquote pred do return i;
+ }
+
+ return -1;
+}
+
find_ptr :: (arr: [] $T, value: T) -> ^T {
for ^it: arr {
if value == *it do return it;