From 583579c548a175dc02a81d98ae5531668474e297 Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Fri, 21 Apr 2023 20:27:17 -0500 Subject: [PATCH] added: closure by reference (very succeptible to dangling pointers) --- compiler/include/astnodes.h | 1 + compiler/src/checker.c | 15 +++++++++++++-- compiler/src/parser.c | 3 +++ compiler/src/wasm_emit.c | 10 ++++++++-- 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/compiler/include/astnodes.h b/compiler/include/astnodes.h index ef896aa6..2f2f7488 100644 --- a/compiler/include/astnodes.h +++ b/compiler/include/astnodes.h @@ -1362,6 +1362,7 @@ struct AstCaptureLocal { AstTyped *captured_value; u32 offset; + b32 by_reference: 1; }; struct AstPolyQuery { diff --git a/compiler/src/checker.c b/compiler/src/checker.c index b1ccbed3..1011e8a0 100644 --- a/compiler/src/checker.c +++ b/compiler/src/checker.c @@ -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; diff --git a/compiler/src/parser.c b/compiler/src/parser.c index f74622be..7f4e5a5f 100644 --- a/compiler/src/parser.c +++ b/compiler/src/parser.c @@ -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); diff --git a/compiler/src/wasm_emit.c b/compiler/src/wasm_emit.c index 4a5273d9..f1d18d9b 100644 --- a/compiler/src/wasm_emit.c +++ b/compiler/src/wasm_emit.c @@ -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); -- 2.25.1