code and '#insert' blocks can be expressions
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 5 Aug 2021 15:54:10 +0000 (10:54 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 5 Aug 2021 15:54:10 +0000 (10:54 -0500)
bin/onyx
include/onyxastnodes.h
src/onyxchecker.c
src/onyxparser.c
src/onyxsymres.c

index 8ce676ff2e15c3b515b8dac99265da83c2afdff1..569f3fa03ceb384e9583567668ba5de7d7d92e46 100755 (executable)
Binary files a/bin/onyx and b/bin/onyx differ
index ba0adc27974e64987f5288e948156a95f1c74780..9a3911d3e172df7b2a37303c99c2af580f3de151 100644 (file)
@@ -1015,7 +1015,7 @@ struct AstCallSite {
 struct AstCodeBlock {
     AstTyped_base;
 
-    AstBlock *code;
+    AstNode *code;
 };
 
 struct AstDirectiveInsert {
index 2d4620c2739146e8c35ba9030c8f5760f1c687b5..3bf1c7465205eaf3599408d07cd7b1c5cffb227f 100644 (file)
@@ -53,6 +53,7 @@ CheckStatus check_function_header(AstFunction* func);
 CheckStatus check_memres_type(AstMemRes* memres);
 CheckStatus check_memres(AstMemRes* memres);
 CheckStatus check_type(AstType* type);
+CheckStatus check_insert_directive(AstDirectiveInsert** pinsert);
 
 
 // HACK HACK HACK
@@ -1661,6 +1662,10 @@ CheckStatus check_expression(AstTyped** pexpr) {
             expr->type = ((AstAlias *) expr)->alias->type;
             break;
 
+        case Ast_Kind_Directive_Insert:
+            retval = check_insert_directive((AstDirectiveInsert **) pexpr);
+            break;
+
         case Ast_Kind_Code_Block:
             expr->flags |= Ast_Flag_Comptime;
             fill_in_type(expr);
@@ -1702,7 +1707,8 @@ CheckStatus check_global(AstGlobal* global) {
     return Check_Success;
 }
 
-CheckStatus check_insert_directive(AstDirectiveInsert* insert) {
+CheckStatus check_insert_directive(AstDirectiveInsert** pinsert) {
+    AstDirectiveInsert* insert = *pinsert;
     if (insert->flags & Ast_Flag_Has_Been_Checked) return Check_Success;
 
     CHECK(expression, &insert->code_expr);
@@ -1724,14 +1730,19 @@ CheckStatus check_insert_directive(AstDirectiveInsert* insert) {
 
     assert(code_block->kind == Ast_Kind_Code_Block);
 
-    AstBlock* cloned_block = (AstBlock *) ast_clone(context.ast_alloc, code_block->code);
+    AstNode* cloned_block = ast_clone(context.ast_alloc, code_block->code);
+
+    if (cloned_block->kind == Ast_Kind_Block) {
+        AstNode* next = insert->next;
+        insert->next = (AstNode *) ((AstBlock *) cloned_block)->body;
 
-    AstNode* next = insert->next;
-    insert->next = (AstNode *) cloned_block->body;
+        AstNode* last_stmt = insert->next;
+        while (last_stmt->next != NULL) last_stmt = last_stmt->next;
+        last_stmt->next = next;
 
-    AstNode* last_stmt = insert->next;
-    while (last_stmt->next != NULL) last_stmt = last_stmt->next;
-    last_stmt->next = next;
+    } else {
+        *(AstNode **) pinsert = cloned_block;
+    }
 
     insert->flags |= Ast_Flag_Has_Been_Checked;
 
@@ -1753,8 +1764,6 @@ CheckStatus check_statement(AstNode** pstmt) {
         case Ast_Kind_Block:      return check_block((AstBlock *) stmt);
         case Ast_Kind_Defer:      return check_statement(&((AstDefer *) stmt)->stmt);
 
-        case Ast_Kind_Directive_Insert: return check_insert_directive((AstDirectiveInsert *) stmt);
-
         case Ast_Kind_Binary_Op:
             CHECK(binaryop, (AstBinaryOp **) pstmt, 1);
             (*pstmt)->flags |= Ast_Flag_Expr_Ignored;
index 0b796c01edebd9a85f268d248f106034a3bd4f55..36f3a78350e535bfed75dbf226aae66e2e5d8f7e 100644 (file)
@@ -607,7 +607,6 @@ static AstTyped* parse_factor(OnyxParser* parser) {
             }
             else if (parse_possible_directive(parser, "code")) {
                 OnyxToken* code_token = parser->curr - 1;
-                // expect_token(parser, '{');
 
                 AstCodeBlock* code_block = make_node(AstCodeBlock, Ast_Kind_Code_Block);
                 code_block->token = code_token;
@@ -615,11 +614,24 @@ static AstTyped* parse_factor(OnyxParser* parser) {
                 assert(builtin_code_type != NULL);
                 code_block->type_node = builtin_code_type;
 
-                code_block->code = parse_block(parser, 1);
+                if (parser->curr->type == '{') {
+                    code_block->code = (AstNode *) parse_block(parser, 1);
+
+                } else {
+                    code_block->code = (AstNode *) parse_expression(parser, 0);
+                }
 
                 retval = (AstTyped *) code_block;
                 break;
             }
+            else if (parse_possible_directive(parser, "insert")) {
+                AstDirectiveInsert* insert = make_node(AstDirectiveInsert, Ast_Kind_Directive_Insert);
+                insert->token = parser->curr - 1;
+                insert->code_expr = parse_expression(parser, 0);
+
+                retval = (AstTyped *) insert;
+                break;
+            }
 
             onyx_report_error(parser->curr->pos, "Invalid directive in expression.");
             return NULL;
@@ -1406,12 +1418,8 @@ static AstNode* parse_statement(OnyxParser* parser) {
                 break;
             }
 
-            if (parse_possible_directive(parser, "insert")) {
-                AstDirectiveInsert* insert = make_node(AstDirectiveInsert, Ast_Kind_Directive_Insert);
-                insert->token = parser->curr - 1;
-                insert->code_expr = parse_expression(parser, 0);
-
-                retval = (AstNode *) insert;
+            if (next_tokens_are(parser, 2, '#', Token_Type_Symbol)) {
+                retval = (AstNode *) parse_factor(parser);
                 break;
             }
         }
index e130e50c2c2f74279285d27e332a2323d3cace1e..592029796c101cc17ea87867b71a19f024be31ac 100644 (file)
@@ -43,6 +43,7 @@ static SymresStatus symres_switch(AstSwitch* switchnode);
 static SymresStatus symres_use(AstUse* use);
 static SymresStatus symres_directive_solidify(AstDirectiveSolidify** psolid);
 static SymresStatus symres_directive_defined(AstDirectiveDefined** pdefined);
+static SymresStatus symres_directive_insert(AstDirectiveInsert* insert);
 static SymresStatus symres_statement_chain(AstNode** walker);
 static SymresStatus symres_statement(AstNode** stmt, b32 *remove);
 static SymresStatus symres_block(AstBlock* block);
@@ -480,6 +481,11 @@ static SymresStatus symres_expression(AstTyped** expr) {
             SYMRES(if_expression, (AstIfExpression *) *expr);
             break;
 
+        case Ast_Kind_Directive_Insert:
+            SYMRES(directive_insert, (AstDirectiveInsert *) *expr);
+            break;
+
+
         default: break;
     }
 
@@ -778,8 +784,6 @@ static SymresStatus symres_statement(AstNode** stmt, b32 *remove) {
         case Ast_Kind_Defer:       SYMRES(statement, &((AstDefer *) *stmt)->stmt, NULL); break;
         case Ast_Kind_Jump:        break;
 
-        case Ast_Kind_Directive_Insert: SYMRES(directive_insert, (AstDirectiveInsert *) *stmt); break;
-
         case Ast_Kind_Local:
             // if (remove) *remove = 1;
             SYMRES(local, (AstLocal **) stmt);