From: Brendan Hansen Date: Tue, 3 Aug 2021 16:11:04 +0000 (-0500) Subject: added paste-able code blocks with '#insert' and '#{}' X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=7e492e978ae66ea7f7341b7fa2340c3b3186dd7d;p=onyx.git added paste-able code blocks with '#insert' and '#{}' --- diff --git a/bin/onyx b/bin/onyx index b6eb5837..e51b1df8 100755 Binary files a/bin/onyx and b/bin/onyx differ diff --git a/core/builtin.onyx b/core/builtin.onyx index 2b3aa3e1..0787429b 100644 --- a/core/builtin.onyx +++ b/core/builtin.onyx @@ -187,3 +187,7 @@ any :: struct { data: rawptr; type: type_expr; } + + +// Represents a code block. Not constructable outside of using a '#{}' block. +Code :: struct {} \ No newline at end of file diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index 6273059a..ba0adc27 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -85,6 +85,9 @@ NODE(Note) \ NODE(CallSite) \ \ + NODE(CodeBlock) \ + NODE(DirectiveInsert) \ + \ NODE(Package) #define NODE(name) typedef struct Ast ## name Ast ## name; @@ -186,6 +189,9 @@ typedef enum AstKind { Ast_Kind_Directive_Defined, Ast_Kind_Call_Site, + Ast_Kind_Code_Block, + Ast_Kind_Directive_Insert, + Ast_Kind_Note, Ast_Kind_Count @@ -1005,6 +1011,19 @@ struct AstCallSite { AstNumLit* column; }; +// Represents a "pastable" block of code. +struct AstCodeBlock { + AstTyped_base; + + AstBlock *code; +}; + +struct AstDirectiveInsert { + AstNode_base; + + AstTyped *code_expr; +}; + typedef enum EntityState { Entity_State_Error, @@ -1233,6 +1252,7 @@ extern AstType *builtin_allocator_type; extern AstType *builtin_iterator_type; extern AstType *builtin_callsite_type; extern AstType *builtin_any_type; +extern AstType *builtin_code_type; extern AstTyped *type_table_node; typedef struct BuiltinSymbol { diff --git a/include/onyxwasm.h b/include/onyxwasm.h index 9f0cfffb..29dc274c 100644 --- a/include/onyxwasm.h +++ b/include/onyxwasm.h @@ -585,7 +585,6 @@ typedef struct OnyxWasmModule { } OnyxWasmModule; OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc); -void onyx_wasm_module_compile(OnyxWasmModule* module); void onyx_wasm_module_free(OnyxWasmModule* module); void onyx_wasm_module_write_to_file(OnyxWasmModule* module, bh_file file); diff --git a/src/onyxastnodes.c b/src/onyxastnodes.c index 1b4d186d..9944f63a 100644 --- a/src/onyxastnodes.c +++ b/src/onyxastnodes.c @@ -87,6 +87,9 @@ static const char* ast_node_names[] = { "DEFINED", "CALL SITE", + "CODE BLOCK", + "DIRECTIVE INSERT" + "NOTE", "AST_NODE_KIND_COUNT", diff --git a/src/onyxbuiltins.c b/src/onyxbuiltins.c index 161022fc..e33d011c 100644 --- a/src/onyxbuiltins.c +++ b/src/onyxbuiltins.c @@ -48,6 +48,7 @@ AstType *builtin_allocator_type; AstType *builtin_iterator_type; AstType *builtin_callsite_type; AstType *builtin_any_type; +AstType *builtin_code_type; AstTyped *type_table_node = NULL; @@ -398,6 +399,12 @@ void initialize_builtins(bh_allocator a) { return; } + builtin_code_type = (AstType *) symbol_raw_resolve(p->scope, "Code"); + if (builtin_code_type == NULL) { + onyx_report_error((OnyxFilePos) { 0 }, "'Code' struct not found in builtin package."); + return; + } + p = package_lookup("builtin.type_info"); if (p != NULL) { type_table_node = (AstTyped *) symbol_raw_resolve(p->scope, "type_table"); diff --git a/src/onyxchecker.c b/src/onyxchecker.c index d9367e79..2d4620c2 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -16,6 +16,7 @@ typedef enum CheckStatus { Check_Complete, // The node is done processing Check_Errors_Start, + Check_Return_To_Symres, // Return this node for further symres processing Check_Yield_Macro, Check_Error, // There was an error when checking the node } CheckStatus; @@ -1660,6 +1661,11 @@ CheckStatus check_expression(AstTyped** pexpr) { expr->type = ((AstAlias *) expr)->alias->type; break; + case Ast_Kind_Code_Block: + expr->flags |= Ast_Flag_Comptime; + fill_in_type(expr); + break; + case Ast_Kind_StrLit: break; case Ast_Kind_File_Contents: break; case Ast_Kind_Overloaded_Function: break; @@ -1696,6 +1702,42 @@ CheckStatus check_global(AstGlobal* global) { return Check_Success; } +CheckStatus check_insert_directive(AstDirectiveInsert* insert) { + if (insert->flags & Ast_Flag_Has_Been_Checked) return Check_Success; + + CHECK(expression, &insert->code_expr); + if (insert->code_expr->type == NULL) return Check_Yield_Macro; + + Type* code_type = type_build_from_ast(context.ast_alloc, builtin_code_type); + + if (!type_check_or_auto_cast(&insert->code_expr, code_type)) { + onyx_report_error(insert->token->pos, "#insert expected a value of type 'Code', got '%s'.", + type_get_name(insert->code_expr->type)); + + return Check_Error; + } + + AstCodeBlock* code_block = (AstCodeBlock *) insert->code_expr; + while (code_block->kind == Ast_Kind_Alias) { + code_block = (AstCodeBlock *) ((AstAlias *) code_block)->alias; + } + + assert(code_block->kind == Ast_Kind_Code_Block); + + AstBlock* cloned_block = (AstBlock *) ast_clone(context.ast_alloc, code_block->code); + + 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; + + insert->flags |= Ast_Flag_Has_Been_Checked; + + return Check_Return_To_Symres; +} + CheckStatus check_statement(AstNode** pstmt) { AstNode* stmt = *pstmt; @@ -1711,6 +1753,8 @@ 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; @@ -2148,9 +2192,10 @@ void check_entity(Entity* ent) { default: break; } - if (cs == Check_Success) ent->state = Entity_State_Code_Gen; - if (cs == Check_Complete) ent->state = Entity_State_Finalized; - if (cs == Check_Yield_Macro) ent->macro_attempts++; + if (cs == Check_Success) ent->state = Entity_State_Code_Gen; + if (cs == Check_Complete) ent->state = Entity_State_Finalized; + if (cs == Check_Return_To_Symres) ent->state = Entity_State_Resolve_Symbols; + if (cs == Check_Yield_Macro) ent->macro_attempts++; else { ent->macro_attempts = 0; ent->micro_attempts = 0; diff --git a/src/onyxclone.c b/src/onyxclone.c index 3130808d..e470b57d 100644 --- a/src/onyxclone.c +++ b/src/onyxclone.c @@ -16,6 +16,7 @@ static inline b32 should_clone(AstNode* node) { case Ast_Kind_Overloaded_Function: case Ast_Kind_Polymorphic_Proc: case Ast_Kind_Alias: + case Ast_Kind_Code_Block: return 0; default: return 1; @@ -93,6 +94,7 @@ static inline i32 ast_kind_to_size(AstNode* node) { case Ast_Kind_Call_Site: return sizeof(AstCallSite); case Ast_Kind_Static_If: return sizeof(AstIfWhile); case Ast_Kind_If_Expression: return sizeof(AstIfExpression); + case Ast_Kind_Directive_Insert: return sizeof(AstDirectiveInsert); case Ast_Kind_Count: return 0; } @@ -433,6 +435,11 @@ AstNode* ast_clone(bh_allocator a, void* n) { ((AstIfExpression *) nn)->false_expr = (AstTyped *) ast_clone(a, ((AstIfExpression *) node)->false_expr); break; } + + case Ast_Kind_Directive_Insert: { + ((AstDirectiveInsert *) nn)->code_expr = (AstTyped *) ast_clone(a, ((AstDirectiveInsert *) node)->code_expr); + break; + } } return nn; diff --git a/src/onyxparser.c b/src/onyxparser.c index 93b25c2b..2ae6c8d4 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -605,6 +605,21 @@ static AstTyped* parse_factor(OnyxParser* parser) { retval = (AstTyped *) defined; break; } + else if (next_tokens_are(parser, 2, '#', '{')) { + OnyxToken* code_token = expect_token(parser, '#'); + // expect_token(parser, '{'); + + AstCodeBlock* code_block = make_node(AstCodeBlock, Ast_Kind_Code_Block); + code_block->token = code_token; + + assert(builtin_code_type != NULL); + code_block->type_node = builtin_code_type; + + code_block->code = parse_block(parser, 1); + + retval = (AstTyped *) code_block; + break; + } onyx_report_error(parser->curr->pos, "Invalid directive in expression."); return NULL; @@ -1390,6 +1405,15 @@ static AstNode* parse_statement(OnyxParser* parser) { ENTITY_SUBMIT(binding); 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; + break; + } } default: diff --git a/src/onyxsymres.c b/src/onyxsymres.c index 3934e308..e130e50c 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -757,6 +757,11 @@ static SymresStatus symres_directive_defined(AstDirectiveDefined** pdefined) { return Symres_Success; } +static SymresStatus symres_directive_insert(AstDirectiveInsert* insert) { + SYMRES(expression, &insert->code_expr); + return Symres_Success; +} + static SymresStatus symres_statement(AstNode** stmt, b32 *remove) { if (remove) *remove = 0; @@ -773,6 +778,8 @@ 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); diff --git a/src/onyxwasm.c b/src/onyxwasm.c index 6d90994b..9a6af364 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -400,6 +400,9 @@ EMIT_FUNC(statement, AstNode* stmt) { case Ast_Kind_Block: emit_block(mod, &code, (AstBlock *) stmt, 1); break; case Ast_Kind_Defer: emit_defer(mod, &code, (AstDefer *) stmt); break; case Ast_Kind_Local: emit_local_allocation(mod, &code, (AstTyped *) stmt); break; + + case Ast_Kind_Directive_Insert: break; + default: emit_expression(mod, &code, (AstTyped *) stmt); break; }