From ac2306f4515d4782390157ecf585408c753157f1 Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Wed, 6 Apr 2022 11:28:03 -0500 Subject: [PATCH] '->' no longer requires an address of --- include/astnodes.h | 7 +++++++ src/astnodes.c | 13 +++++++++++++ src/checker.c | 13 +++++++++++-- src/parser.c | 13 ++++++++++++- src/symres.c | 5 +++++ 5 files changed, 48 insertions(+), 3 deletions(-) diff --git a/include/astnodes.h b/include/astnodes.h index 94ea66f5..a38da2c0 100644 --- a/include/astnodes.h +++ b/include/astnodes.h @@ -610,6 +610,13 @@ struct AstAddressOf { AstTyped *expr; AstBinaryOp *potential_substitute; + + // This is set by check_method_call. + // If set, the address of node can be removed if the + // type checking does not pass for it. This makes it + // possible to have something that will optionally + // have its address taken, if necessary. + b32 can_be_removed : 1; }; struct AstArgument { AstTyped_base; diff --git a/src/astnodes.c b/src/astnodes.c index 9a3819a8..cac8babd 100644 --- a/src/astnodes.c +++ b/src/astnodes.c @@ -735,6 +735,19 @@ TypeMatch unify_node_and_type_(AstTyped** pnode, Type* type, b32 permanent) { return unify_node_and_type_(&alias->alias, type, permanent); } + else if (node->kind == Ast_Kind_Address_Of) { + AstAddressOf *address_of = (AstAddressOf *) node; + if (address_of->can_be_removed) { + if (!permanent) { + return unify_node_and_type_(&address_of->expr, type, permanent); + + } else { + *pnode = (AstTyped *) address_of->expr; + return unify_node_and_type_(pnode, type, permanent); + } + } + } + return TYPE_MATCH_FAILED; } diff --git a/src/checker.c b/src/checker.c index 089ee568..611f6537 100644 --- a/src/checker.c +++ b/src/checker.c @@ -1489,6 +1489,12 @@ CheckStatus check_address_of(AstAddressOf** paof) { && expr->kind != Ast_Kind_Local && expr->kind != Ast_Kind_Constraint_Sentinel) || (expr->flags & Ast_Flag_Cannot_Take_Addr) != 0) { + + if (aof->can_be_removed) { + *(AstTyped **) paof = aof->expr; + return Check_Yield_Macro; + } + ERROR_(aof->token->pos, "Cannot take the address of something that is not an l-value. %s", onyx_ast_node_kind_string(expr->kind)); } @@ -1691,8 +1697,11 @@ CheckStatus check_method_call(AstBinaryOp** pmcall) { // 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 - if (implicit_argument->type->kind != Type_Kind_Pointer) - implicit_argument = (AstTyped *) make_address_of(context.ast_alloc, implicit_argument); + if (implicit_argument->type->kind != Type_Kind_Pointer) { + AstAddressOf *address_of = make_address_of(context.ast_alloc, implicit_argument); + address_of->can_be_removed = 1; + implicit_argument = (AstTyped *) address_of; + } implicit_argument = (AstTyped *) make_argument(context.ast_alloc, implicit_argument); diff --git a/src/parser.c b/src/parser.c index 59afebc7..45eb8769 100644 --- a/src/parser.c +++ b/src/parser.c @@ -781,7 +781,16 @@ static AstTyped* parse_factor(OnyxParser* parser) { method_call->left = retval; method_call->right = parse_factor(parser); - retval = (AstTyped *) method_call; + if (method_call->right->kind == Ast_Kind_Method_Call) { + AstBinaryOp *inner_method_call = (AstBinaryOp *) method_call->right; + method_call->right = inner_method_call->left; + inner_method_call->left = (AstTyped *) method_call; + + retval = (AstTyped *) inner_method_call; + + } else { + retval = (AstTyped *) method_call; + } break; } @@ -1267,7 +1276,9 @@ static i32 parse_possible_symbol_declaration(OnyxParser* parser, AstNode** ret) expect_token(parser, ':'); if (parser->curr->type == ':') { + bh_arr_push(parser->current_symbol_stack, symbol); AstBinding* binding = parse_top_level_binding(parser, symbol); + bh_arr_pop(parser->current_symbol_stack); if (parser->hit_unexpected_token) return 2; ENTITY_SUBMIT(binding); diff --git a/src/symres.c b/src/symres.c index 9b501aca..c4f6659e 100644 --- a/src/symres.c +++ b/src/symres.c @@ -391,6 +391,11 @@ static SymresStatus symres_method_call(AstBinaryOp** mcall) { return Symres_Error; } + // AstAlias *left_alias = onyx_ast_node_new(context.ast_alloc, sizeof(AstAlias), Ast_Kind_Alias); + // left_alias->token = (*mcall)->left->token; + // left_alias->alias = (*mcall)->left; + // (*mcall)->left = (AstTyped *) left_alias; + AstFieldAccess* implicit_field_access = make_field_access(context.ast_alloc, (*mcall)->left, NULL); implicit_field_access->token = ((AstCall *) (*mcall)->right)->callee->token; ((AstCall *) (*mcall)->right)->callee = (AstTyped *) implicit_field_access; -- 2.25.1