From: Brendan Hansen Date: Thu, 5 Aug 2021 15:54:10 +0000 (-0500) Subject: code and '#insert' blocks can be expressions X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=f948725b8c40e7903d953e12d255a13e8c02cb61;p=onyx.git code and '#insert' blocks can be expressions --- diff --git a/bin/onyx b/bin/onyx index 8ce676ff..569f3fa0 100755 Binary files a/bin/onyx and b/bin/onyx differ diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index ba0adc27..9a3911d3 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -1015,7 +1015,7 @@ struct AstCallSite { struct AstCodeBlock { AstTyped_base; - AstBlock *code; + AstNode *code; }; struct AstDirectiveInsert { diff --git a/src/onyxchecker.c b/src/onyxchecker.c index 2d4620c2..3bf1c746 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -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; diff --git a/src/onyxparser.c b/src/onyxparser.c index 0b796c01..36f3a783 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -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; } } diff --git a/src/onyxsymres.c b/src/onyxsymres.c index e130e50c..59202979 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -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);