added: closure by reference (very succeptible to dangling pointers)
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 22 Apr 2023 01:27:17 +0000 (20:27 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 22 Apr 2023 01:27:17 +0000 (20:27 -0500)
compiler/include/astnodes.h
compiler/src/checker.c
compiler/src/parser.c
compiler/src/wasm_emit.c

index ef896aa624b4e8a57571a44a9a48343d95191c76..2f2f7488613b8fe02f5ddd1c565e5d0e26f28c4c 100644 (file)
@@ -1362,6 +1362,7 @@ struct AstCaptureLocal {
     AstTyped *captured_value;
 
     u32 offset;
+    b32 by_reference: 1;
 };
 
 struct AstPolyQuery {
index b1ccbed394ce7d400503d9c960705abbda705cdc..1011e8a0e86fd0052d645c3db32150e28e75ec95 100644 (file)
@@ -2225,9 +2225,20 @@ CheckStatus check_expression(AstTyped** pexpr) {
             YIELD(expr->token->pos, "Waiting to resolve #this_package.");
             break;
 
-        case Ast_Kind_Capture_Local:
-            expr->type = ((AstCaptureLocal *) expr)->captured_value->type;
+        case Ast_Kind_Capture_Local: {
+            AstCaptureLocal *cl = (AstCaptureLocal *) expr;
+            if (cl->by_reference) {
+                if (!is_lval((AstNode *) cl->captured_value)) {
+                    ERROR_(cl->token->pos, "Cannot pass '%b' by pointer because it is not an l-value.", cl->token->text, cl->token->length);
+                }
+
+                expr->type = type_make_pointer(context.ast_alloc, cl->captured_value->type);
+
+            } else {
+                expr->type = cl->captured_value->type;
+            }
             break;
+        }
 
         case Ast_Kind_File_Contents: break;
         case Ast_Kind_Overloaded_Function: break;
index f74622be4a10f700dba82611a9d5831eb74284f7..7f4e5a5fa95d3cda0606642af0b7b0c0e25a1911 100644 (file)
@@ -2400,6 +2400,9 @@ static AstCaptureBlock *parse_capture_list(OnyxParser* parser, TokenType end_tok
         if (parser->hit_unexpected_token) break;
 
         AstCaptureLocal *capture = make_node(AstCaptureLocal, Ast_Kind_Capture_Local);
+
+        if (consume_token_if_next(parser, '&')) capture->by_reference = 1;
+
         capture->token = expect_token(parser, Token_Type_Symbol);
 
         bh_arr_push(captures->captures, capture);
index 4a5273d948fc27e5b8b0ed4b849ffdc087343988..f1d18d9bd783c96d94a06f308ebbc8d62c89797c 100644 (file)
@@ -3418,8 +3418,14 @@ EMIT_FUNC(expression, AstTyped* expr) {
             // Populate the block
             bh_arr_each(AstCaptureLocal *, capture, func->captures->captures) {
                 WIL(NULL, WI_LOCAL_GET, capture_block_ptr);
-                emit_expression(mod, &code, (*capture)->captured_value);
-                emit_store_instruction(mod, &code, (*capture)->captured_value->type, (*capture)->offset);
+
+                if ((*capture)->by_reference) {
+                    emit_location(mod, &code, (*capture)->captured_value);
+                } else {
+                    emit_expression(mod, &code, (*capture)->captured_value);
+                }
+
+                emit_store_instruction(mod, &code, (*capture)->type, (*capture)->offset);
             }
             
             local_raw_free(mod->local_alloc, WASM_TYPE_PTR);