data: rawptr;
type: type_expr;
}
+
+
+// Represents a code block. Not constructable outside of using a '#{}' block.
+Code :: struct {}
\ No newline at end of file
NODE(Note) \
NODE(CallSite) \
\
+ NODE(CodeBlock) \
+ NODE(DirectiveInsert) \
+ \
NODE(Package)
#define NODE(name) typedef struct Ast ## name Ast ## name;
Ast_Kind_Directive_Defined,
Ast_Kind_Call_Site,
+ Ast_Kind_Code_Block,
+ Ast_Kind_Directive_Insert,
+
Ast_Kind_Note,
Ast_Kind_Count
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,
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 {
} 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);
"DEFINED",
"CALL SITE",
+ "CODE BLOCK",
+ "DIRECTIVE INSERT"
+
"NOTE",
"AST_NODE_KIND_COUNT",
AstType *builtin_iterator_type;
AstType *builtin_callsite_type;
AstType *builtin_any_type;
+AstType *builtin_code_type;
AstTyped *type_table_node = NULL;
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");
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;
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;
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;
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;
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;
case Ast_Kind_Overloaded_Function:
case Ast_Kind_Polymorphic_Proc:
case Ast_Kind_Alias:
+ case Ast_Kind_Code_Block:
return 0;
default: return 1;
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;
}
((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;
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;
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:
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;
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);
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;
}