changed: capture syntax and location
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 19 Apr 2023 21:48:35 +0000 (16:48 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 19 Apr 2023 21:48:35 +0000 (16:48 -0500)
compiler/include/astnodes.h
compiler/src/astnodes.c
compiler/src/checker.c
compiler/src/clone.c
compiler/src/parser.c
compiler/src/symres.c
compiler/src/utils.c

index 654ef4d6407808dcd0867c37e710c885a7506919..beeb1ad70773a36819fbe83b8f84b18e60b7a804 100644 (file)
@@ -1354,8 +1354,6 @@ struct AstCaptureBlock {
     bh_arr(AstCaptureLocal *) captures;
 
     u32 total_size_in_bytes;
-
-    b32 is_legal : 1;
 };
 
 struct AstCaptureLocal {
index 5730ca4c4f48ab96a817af191d3bf1f6ed8aa1b0..c68ad57486d078a6fbd46258b2a366e9125aece3 100644 (file)
@@ -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;
         }
index 874a69f299ce9b19ca00a400dbf54523f558f4f5..217e3788f0036f2abc3ff331a76015e59f944bdb 100644 (file)
@@ -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) {
index d21f0e182ce033c483a4d63ff3f0e8bcb7e8369e..a689d74cfbdabf742d4bb6fa5b66f8a19d931ed8 100644 (file)
@@ -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;
         }
 
index d1af248e50437591925404b7e61a2756fba50a4c..4fad39013bdf5b2256b82abc1b068f4f2347bc78 100644 (file)
@@ -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) {
index 0d9b6dbd3c450026092c7c4e312fd0fa3d80dc2f..20fe2b3636e25902af9c62a8e90e9c60e5d64fb8 100644 (file)
@@ -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();
index fc00cea5aae7936149e18492ecf2f2cb2d123a59..bcec4eadba61df477128727d82b2fcd702592d30 100644 (file)
@@ -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));