From: Brendan Hansen Date: Wed, 19 Apr 2023 21:48:35 +0000 (-0500) Subject: changed: capture syntax and location X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=682e45b8977fd9469e6ec54d52a8a7cc6be71eab;p=onyx.git changed: capture syntax and location --- diff --git a/compiler/include/astnodes.h b/compiler/include/astnodes.h index 654ef4d6..beeb1ad7 100644 --- a/compiler/include/astnodes.h +++ b/compiler/include/astnodes.h @@ -1354,8 +1354,6 @@ struct AstCaptureBlock { bh_arr(AstCaptureLocal *) captures; u32 total_size_in_bytes; - - b32 is_legal : 1; }; struct AstCaptureLocal { diff --git a/compiler/src/astnodes.c b/compiler/src/astnodes.c index 5730ca4c..c68ad574 100644 --- a/compiler/src/astnodes.c +++ b/compiler/src/astnodes.c @@ -696,7 +696,7 @@ TypeMatch unify_node_and_type_(AstTyped** pnode, Type* type, b32 permanent) { node = *pnode; } - if (node->kind == Ast_Kind_Function) { + if (node->kind == Ast_Kind_Function && permanent) { if (maybe_create_capture_builder_for_function_expression(pnode)) { return TYPE_MATCH_SPECIAL; } diff --git a/compiler/src/checker.c b/compiler/src/checker.c index 874a69f2..217e3788 100644 --- a/compiler/src/checker.c +++ b/compiler/src/checker.c @@ -2241,6 +2241,7 @@ CheckStatus check_expression(AstTyped** pexpr) { case Ast_Kind_Capture_Builder: { AstCaptureBuilder *builder = (void *) expr; + builder->type = get_expression_type(builder->func); fori (i, 0, bh_arr_length(builder->capture_values)) { if (!builder->captures->captures[i]->type) { diff --git a/compiler/src/clone.c b/compiler/src/clone.c index d21f0e18..a689d74c 100644 --- a/compiler/src/clone.c +++ b/compiler/src/clone.c @@ -467,6 +467,7 @@ AstNode* ast_clone(bh_allocator a, void* n) { df->return_type = (AstType *) ast_clone(a, sf->return_type); df->body = (AstBlock *) ast_clone(a, sf->body); + df->captures = (AstCaptureBlock *) ast_clone(a, sf->captures); df->nodes_that_need_entities_after_clone = captured_entities; captured_entities = NULL; @@ -607,8 +608,6 @@ AstNode* ast_clone(bh_allocator a, void* n) { bh_arr_each(AstCaptureLocal *, expr, cs->captures) { bh_arr_push(cd->captures, (AstCaptureLocal *) ast_clone(a, (AstNode *) *expr)); } - - cd->is_legal = 0; break; } diff --git a/compiler/src/parser.c b/compiler/src/parser.c index d1af248e..4fad3901 100644 --- a/compiler/src/parser.c +++ b/compiler/src/parser.c @@ -1709,34 +1709,6 @@ static AstNode* parse_statement(OnyxParser* parser) { break; } - if (parse_possible_directive(parser, "capture")) { - // :LinearTokenDependent - AstCaptureBlock *captures = make_node(AstCaptureBlock, Ast_Kind_Capture_Block); - captures->token = parser->curr - 2; - - bh_arr_new(global_heap_allocator, captures->captures, 2); - - expect_token(parser, '{'); - while (!consume_token_if_next(parser, '}')) { - if (parser->hit_unexpected_token) break; - - AstCaptureLocal *capture = make_node(AstCaptureLocal, Ast_Kind_Capture_Local); - capture->token = expect_token(parser, Token_Type_Symbol); - - expect_token(parser, ':'); - capture->type_node = parse_type(parser); - - bh_arr_push(captures->captures, capture); - - if (peek_token(0)->type != '}') - expect_token(parser, ','); - } - - retval = (AstNode *) captures; - needs_semicolon = 0; - break; - } - if (next_tokens_are(parser, 2, '#', Token_Type_Symbol)) { retval = (AstNode *) parse_factor(parser); break; @@ -2415,6 +2387,31 @@ static void parse_constraints(OnyxParser* parser, ConstraintContext *out_constra } while (consume_token_if_next(parser, ',')); } +static AstCaptureBlock *parse_capture_list(OnyxParser* parser, TokenType end_token) { + // :LinearTokenDependent + AstCaptureBlock *captures = make_node(AstCaptureBlock, Ast_Kind_Capture_Block); + captures->token = parser->curr - 1; + + bh_arr_new(global_heap_allocator, captures->captures, 2); + + while (!consume_token_if_next(parser, end_token)) { + if (parser->hit_unexpected_token) break; + + AstCaptureLocal *capture = make_node(AstCaptureLocal, Ast_Kind_Capture_Local); + capture->token = expect_token(parser, Token_Type_Symbol); + + expect_token(parser, ':'); + capture->type_node = parse_type(parser); + + bh_arr_push(captures->captures, capture); + + if (peek_token(0)->type != end_token) + expect_token(parser, ','); + } + + return captures; +} + static void parse_function_params(OnyxParser* parser, AstFunction* func) { expect_token(parser, '('); @@ -2428,6 +2425,12 @@ static void parse_function_params(OnyxParser* parser, AstFunction* func) { OnyxToken* symbol; while (!consume_token_if_next(parser, ')')) { + if (consume_token_if_next(parser, '|') && !func->captures) { + func->captures = parse_capture_list(parser, '|'); + consume_token_if_next(parser, ','); + continue; + } + do { if (parser->hit_unexpected_token) return; @@ -2725,14 +2728,28 @@ static b32 parse_possible_function_definition_no_consume(OnyxParser* parser) { b32 is_params = (parser->curr + 1) == matching_paren; OnyxToken* tmp_token = parser->curr; while (!is_params && tmp_token < matching_paren) { + if (tmp_token->type == '|') { + tmp_token++; + while (tmp_token->type != '|' && tmp_token < matching_paren) { + tmp_token++; + } + tmp_token++; + } + if (tmp_token->type == ':') is_params = 1; tmp_token++; } - if (!is_params) return 0; + if (peek_token(1)->type == '|' && (matching_paren - 1)->type == '|') { + OnyxToken* tmp_token = parser->curr + 1; + while (!is_params && tmp_token < matching_paren - 1) { + if (tmp_token->type == ':') is_params = 1; + tmp_token++; + } + } - return 1; + return is_params; } return 0; @@ -2780,7 +2797,9 @@ static b32 parse_possible_quick_function_definition(OnyxParser* parser, AstTyped bh_arr(QuickParam) params=NULL; bh_arr_new(global_heap_allocator, params, 4); + OnyxToken* proc_token; + AstCaptureBlock *captures = NULL; if (parser->curr->type == Token_Type_Symbol) { QuickParam param = { 0 }; @@ -2790,21 +2809,24 @@ static b32 parse_possible_quick_function_definition(OnyxParser* parser, AstTyped } else { proc_token = expect_token(parser, '('); - while (parser->curr->type != ')') { + while (!consume_token_if_next(parser, ')')) { if (parser->hit_unexpected_token) return 0; - QuickParam param = { 0 }; - if (consume_token_if_next(parser, '$')) param.is_baked = 1; - param.token = expect_token(parser, Token_Type_Symbol); + if (consume_token_if_next(parser, '|') && !captures) { + captures = parse_capture_list(parser, '|'); - bh_arr_push(params, param); + } else { + QuickParam param = { 0 }; + if (consume_token_if_next(parser, '$')) param.is_baked = 1; + param.token = expect_token(parser, Token_Type_Symbol); + + bh_arr_push(params, param); + } if (parser->curr->type != ')') { expect_token(parser, ','); } } - - expect_token(parser, ')'); } expect_token(parser, '='); @@ -2881,8 +2903,8 @@ static b32 parse_possible_quick_function_definition(OnyxParser* parser, AstTyped poly_proc->token = proc_token; poly_proc->body = body_block; poly_proc->return_type = (AstType *) return_type; + poly_proc->captures = captures; - poly_proc->token = proc_token; bh_arr_new(global_heap_allocator, poly_proc->poly_params, bh_arr_length(params)); fori (i, 0, bh_arr_length(params)) { bh_arr_push(poly_proc->poly_params, ((AstPolyParam) { diff --git a/compiler/src/symres.c b/compiler/src/symres.c index 0d9b6dbd..20fe2b36 100644 --- a/compiler/src/symres.c +++ b/compiler/src/symres.c @@ -841,11 +841,6 @@ static SymresStatus symres_directive_insert(AstDirectiveInsert* insert) { } static SymresStatus symres_capture_block(AstCaptureBlock *block) { - if (!block->is_legal) { - onyx_report_error(block->token->pos, Error_Critical, "#capture block is not allowed here."); - return Symres_Error; - } - bh_arr_each(AstCaptureLocal *, capture, block->captures) { SYMRES(type, &(*capture)->type_node); } @@ -901,12 +896,6 @@ static SymresStatus symres_statement(AstNode** stmt, b32 *remove) { if (remove) *remove = 1; break; - case Ast_Kind_Capture_Block: - SYMRES(capture_block, (AstCaptureBlock *) *stmt); - - if (remove) *remove = 1; - break; - default: SYMRES(expression, (AstTyped **) stmt); break; } @@ -1047,6 +1036,15 @@ SymresStatus symres_function_header(AstFunction* func) { bh_arr_set_length(func->nodes_that_need_entities_after_clone, 0); } + if (func->captures) { + if (!(func->flags & Ast_Flag_Function_Is_Lambda)) { + onyx_report_error(func->captures->token->pos, Error_Critical, "This procedure cannot capture values as it is not defined in an expression."); + return Symres_Error; + } + + SYMRES(capture_block, func->captures); + } + SYMRES(type, &func->return_type); if (func->deprecated_warning) { @@ -1134,14 +1132,6 @@ SymresStatus symres_function(AstFunction* func) { func->flags |= Ast_Flag_Has_Been_Symres; } - if (func->body && func->body->body && func->body->body->kind == Ast_Kind_Capture_Block) { - func->captures = (void *) func->body->body; - - if (func->flags & Ast_Flag_Function_Is_Lambda) { - ((AstCaptureBlock *) func->body->body)->is_legal = 1; - } - } - SYMRES(block, func->body); scope_leave(); diff --git a/compiler/src/utils.c b/compiler/src/utils.c index fc00cea5..bcec4ead 100644 --- a/compiler/src/utils.c +++ b/compiler/src/utils.c @@ -1494,7 +1494,7 @@ b32 maybe_create_capture_builder_for_function_expression(AstTyped **pexpr) { builder->token = func->captures->token - 1; builder->func = (void *) func; - builder->type = builder->func->type; + // builder->type = builder->func->type; builder->captures = func->captures; bh_arr_new(context.ast_alloc, builder->capture_values, bh_arr_length(builder->captures->captures));