'->' no longer requires an address of
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 6 Apr 2022 16:28:03 +0000 (11:28 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 6 Apr 2022 16:28:03 +0000 (11:28 -0500)
include/astnodes.h
src/astnodes.c
src/checker.c
src/parser.c
src/symres.c

index 94ea66f581c25e73f2df2a6814568b5ec7010ac0..a38da2c0757a879e6ca0d0ffd3a399bf5f90f30c 100644 (file)
@@ -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;
index 9a3819a88d658c1854a006d092d84390dff3d5ea..cac8babd1adfb17a1e28bc9e10411ddb04dd4282 100644 (file)
@@ -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;
 }
 
index 089ee5689801b9dd0ddf5589cbfc3fd3d370c8cb..611f6537d49781f60d634d611eecdc1471a88344 100644 (file)
@@ -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);
 
index 59afebc7e2c4dd671e050c27419ed622aa1d2ba2..45eb876948cbb0709146a21c372ab43482c7281d 100644 (file)
@@ -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);
index 9b501acab32f5d89a2e89ec11167eeb367c37fa3..c4f6659e4c06404642b30b7357ffdd30beee2652 100644 (file)
@@ -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;