From: Brendan Hansen Date: Thu, 12 Aug 2021 12:41:49 +0000 (-0500) Subject: starting to work on macros; not functional yet X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=74c62b330b71ac169accfcd4be410e48753265fb;p=onyx.git starting to work on macros; not functional yet --- diff --git a/bin/onyx b/bin/onyx index 2ec57ae7..16ae4856 100755 Binary files a/bin/onyx and b/bin/onyx differ diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index cda6fcf3..63e52ab3 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -87,6 +87,7 @@ \ NODE(CodeBlock) \ NODE(DirectiveInsert) \ + NODE(Macro) \ \ NODE(Package) @@ -191,6 +192,7 @@ typedef enum AstKind { Ast_Kind_Code_Block, Ast_Kind_Directive_Insert, + Ast_Kind_Macro, Ast_Kind_Note, @@ -481,6 +483,16 @@ typedef enum VarArgKind { VA_Kind_Untyped, } VarArgKind; +typedef enum BlockRule { + Block_Rule_New_Scope = BH_BIT(1), + Block_Rule_New_Binding_Scope = BH_BIT(2), // Unused + Block_Rule_Clear_Defer = BH_BIT(3), + + Block_Rule_Normal = Block_Rule_New_Scope | Block_Rule_New_Binding_Scope | Block_Rule_Clear_Defer, + Block_Rule_Macro = Block_Rule_New_Scope | Block_Rule_New_Binding_Scope, + Block_Rule_Code_Block = Block_Rule_New_Scope, +} BlockRule; + typedef struct Arguments Arguments; struct Arguments { bh_arr(AstTyped *) values; @@ -637,10 +649,12 @@ struct AstUse { // Structure Nodes struct AstBlock { AstNode_base; + AstNode *body; - Scope *scope; + Scope *scope; Scope *binding_scope; + BlockRule rules; }; struct AstDefer { AstNode_base; AstNode *stmt; }; struct AstFor { @@ -1026,6 +1040,12 @@ struct AstDirectiveInsert { AstTyped *code_expr; }; +struct AstMacro { + AstTyped_base; + + AstTyped* body; +}; + typedef enum EntityState { Entity_State_Error, @@ -1061,6 +1081,7 @@ typedef enum EntityType { Entity_Type_Memory_Reservation_Type, Entity_Type_Use, Entity_Type_Polymorphic_Proc, + Entity_Type_Macro, Entity_Type_Foreign_Function_Header, Entity_Type_Foreign_Global_Header, Entity_Type_Function_Header, @@ -1109,6 +1130,7 @@ typedef struct Entity { AstEnumType *enum_type; AstMemRes *mem_res; AstPolyProc *poly_proc; + AstMacro *macro; AstUse *use; }; } Entity; diff --git a/include/onyxlex.h b/include/onyxlex.h index bbb2d9a6..7c4789ae 100644 --- a/include/onyxlex.h +++ b/include/onyxlex.h @@ -37,6 +37,7 @@ typedef enum TokenType { Token_Type_Keyword_Case, Token_Type_Keyword_Switch, Token_Type_Keyword_Fallthrough, + Token_Type_Keyword_Macro, Token_Type_Right_Arrow, Token_Type_Left_Arrow, diff --git a/misc/onyx.sublime-syntax b/misc/onyx.sublime-syntax index 6f7a4d7e..a5666d38 100644 --- a/misc/onyx.sublime-syntax +++ b/misc/onyx.sublime-syntax @@ -26,7 +26,7 @@ contexts: # strings in YAML. When using single quoted strings, only single quotes # need to be escaped: this is done by using two single quotes next to each # other. - - match: '\b(package|struct|use|global|enum|if|elseif|else|for|while|do|break|continue|fallthrough|return|as|cast|sizeof|alignof|defer|switch|case)\b' + - match: '\b(package|struct|use|global|enum|if|elseif|else|for|while|do|break|continue|fallthrough|return|as|cast|sizeof|alignof|defer|switch|case|macro)\b' scope: keyword.control.onyx - match: '\b(bool|void|i8|u8|i16|u16|i32|u32|i64|u64|f32|f64|rawptr|str|cstr|range|type_expr|any)\b' @@ -70,6 +70,11 @@ contexts: 1: entity.name.type 2: keyword.control.onyx + - match: '([a-zA-Z_][a-zA-Z0-9_]*)\s*::\s*(macro)' + captures: + 1: entity.name.function + 2: keyword.control.onyx + - match: '([a-zA-Z_][a-zA-Z0-9_]*)\s*::\s*(enum)' captures: 1: entity.name.enum diff --git a/misc/onyx.vim b/misc/onyx.vim index 08f08910..a6a79a51 100644 --- a/misc/onyx.vim +++ b/misc/onyx.vim @@ -10,7 +10,7 @@ endif let s:cpo_save = &cpo set cpo&vim -syn keyword onyxKeyword package struct enum proc use global +syn keyword onyxKeyword package struct enum proc use global macro syn keyword onyxKeyword if elseif else syn keyword onyxKeyword for while do syn keyword onyxKeyword switch case diff --git a/src/onyxastnodes.c b/src/onyxastnodes.c index 5aef4393..45f4f04c 100644 --- a/src/onyxastnodes.c +++ b/src/onyxastnodes.c @@ -88,7 +88,8 @@ static const char* ast_node_names[] = { "CALL SITE", "CODE BLOCK", - "DIRECTIVE INSERT" + "DIRECTIVE INSERT", + "MACRO", "NOTE", @@ -142,6 +143,7 @@ const char* entity_type_strings[Entity_Type_Count] = { "Memory Reservation Type", "Use", "Polymorphic Proc", + "Macro", "Foreign_Function Header", "Foreign_Global Header", "Function Header", diff --git a/src/onyxchecker.c b/src/onyxchecker.c index b167dd04..6d753d29 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -29,7 +29,7 @@ CheckStatus check_if(AstIfWhile* ifnode); CheckStatus check_while(AstIfWhile* whilenode); CheckStatus check_for(AstFor* fornode); CheckStatus check_switch(AstSwitch* switchnode); -CheckStatus check_call(AstCall* call); +CheckStatus check_call(AstCall** pcall); CheckStatus check_binaryop(AstBinaryOp** pbinop); CheckStatus check_unaryop(AstUnaryOp** punop); CheckStatus check_struct_literal(AstStructLiteral* sl); @@ -413,7 +413,7 @@ typedef enum ArgState { AS_Expecting_Untyped_VA, } ArgState; -CheckStatus check_call(AstCall* call) { +CheckStatus check_call(AstCall** pcall) { // All the things that need to be done when checking a call node. // 1. Ensure the callee is not a symbol // 2. Check the callee expression (since it could be a variable or a field access, etc) @@ -424,11 +424,14 @@ CheckStatus check_call(AstCall* call) { // 7. Fill in arguments // 8. If callee is an intrinsic, turn call into an Intrinsic_Call node // 9. Check types of formal and actual params against each other, handling varargs - + AstCall* call = *pcall; + if (call->flags & Ast_Flag_Has_Been_Checked) return Check_Success; + u32 current_checking_level_store = current_checking_level; CHECK(expression, &call->callee); CHECK(arguments, &call->args); + current_checking_level = current_checking_level_store; // SPEED CLEANUP: Keeping an original copy for basically no reason except that sometimes you // need to know the baked argument values in code generation. @@ -438,11 +441,28 @@ CheckStatus check_call(AstCall* call) { while (call->callee->kind == Ast_Kind_Alias) call->callee = ((AstAlias *) call->callee)->alias; - if (call->callee->kind == Ast_Kind_Overloaded_Function) { + AstTyped *effective_callee = call->callee; + + // If we are "calling" a macro, the callee on the call node should not be replaced + // as then it would remove the macro from the callee, which would turn it into a + // normal function call. + b32 calling_a_macro = 0; + + if (effective_callee->kind == Ast_Kind_Macro) { + calling_a_macro = 1; + if (current_checking_level == EXPRESSION_LEVEL) { + onyx_report_error(call->token->pos, "Macros calls are not allowed at the expression level yet."); + return Check_Error; + } + + effective_callee = ((AstMacro * ) effective_callee)->body; + } + + if (effective_callee->kind == Ast_Kind_Overloaded_Function) { b32 should_yield = 0; - AstTyped* new_callee = find_matching_overload_by_arguments(((AstOverloadedFunction *) call->callee)->overloads, &call->args, &should_yield); + AstTyped* new_callee = find_matching_overload_by_arguments(((AstOverloadedFunction *) effective_callee)->overloads, &call->args, &should_yield); if (new_callee == NULL) { - if (call->callee->entity->state > Entity_State_Check_Types && !should_yield) { + if (effective_callee->entity->state > Entity_State_Check_Types && !should_yield) { report_unable_to_match_overload(call); return Check_Error; @@ -451,19 +471,21 @@ CheckStatus check_call(AstCall* call) { } } - call->callee = new_callee; + effective_callee = new_callee; + if (!calling_a_macro) call->callee = new_callee; } - if (call->callee->kind == Ast_Kind_Polymorphic_Proc) { - AstTyped* new_callee = (AstTyped *) polymorphic_proc_lookup((AstPolyProc *) call->callee, PPLM_By_Arguments, &call->args, call->token); + if (effective_callee->kind == Ast_Kind_Polymorphic_Proc) { + AstTyped* new_callee = (AstTyped *) polymorphic_proc_lookup((AstPolyProc *) effective_callee, PPLM_By_Arguments, &call->args, call->token); if (new_callee == (AstTyped *) &node_that_signals_a_yield) return Check_Yield_Macro; if (new_callee == NULL) return Check_Error; arguments_remove_baked(&call->args); - call->callee = new_callee; + effective_callee = new_callee; + if (!calling_a_macro) call->callee = new_callee; } - AstFunction* callee = (AstFunction *) call->callee; + AstFunction* callee = (AstFunction *) effective_callee; // NOTE: Build callee's type fill_in_type((AstTyped *) callee); @@ -476,7 +498,6 @@ CheckStatus check_call(AstCall* call) { return Check_Error; } - // CLEANUP maybe make function_get_expected_arguments? i32 non_vararg_param_count = (i32) callee->type->Function.param_count; if (non_vararg_param_count > 0 && @@ -644,7 +665,8 @@ CheckStatus check_call(AstCall* call) { } arg_arr[arg_pos]->va_kind = VA_Kind_Untyped; - break; + break;CheckStatus check_compound(AstCompound* compound); + } } @@ -665,7 +687,12 @@ type_checking_done: return Check_Error; } - callee->flags |= Ast_Flag_Function_Used; + if (!calling_a_macro) { + callee->flags |= Ast_Flag_Function_Used; + + } else { + // Macro expansion + } return Check_Success; } @@ -967,7 +994,7 @@ CheckStatus check_binaryop(AstBinaryOp** pbinop) { AstCall *implicit_call = binaryop_try_operator_overload(binop); if (implicit_call != NULL) { - CHECK(call, implicit_call); + CHECK(call, &implicit_call); // NOTE: Not a binary op *pbinop = (AstBinaryOp *) implicit_call; @@ -1365,7 +1392,7 @@ CheckStatus check_subscript(AstSubscript** psub) { AstCall *implicit_call = binaryop_try_operator_overload(binop); if (implicit_call != NULL) { - CHECK(call, implicit_call); + CHECK(call, &implicit_call); // NOTE: Not an array access *psub = (AstSubscript *) implicit_call; @@ -1519,7 +1546,7 @@ CheckStatus check_method_call(AstBinaryOp** mcall) { } (*mcall)->flags |= Ast_Flag_Has_Been_Checked; - CHECK(call, call_node); + CHECK(call, &call_node); call_node->next = (*mcall)->next; *mcall = (AstBinaryOp *) call_node; @@ -1568,6 +1595,10 @@ CheckStatus check_expression(AstTyped** pexpr) { return Check_Success; } + if (expr->kind == Ast_Kind_Macro) { + return Check_Success; + } + fill_in_type(expr); current_checking_level = EXPRESSION_LEVEL; @@ -1576,7 +1607,7 @@ CheckStatus check_expression(AstTyped** pexpr) { case Ast_Kind_Binary_Op: retval = check_binaryop((AstBinaryOp **) pexpr); break; case Ast_Kind_Unary_Op: retval = check_unaryop((AstUnaryOp **) pexpr); break; - case Ast_Kind_Call: retval = check_call((AstCall *) expr); break; + case Ast_Kind_Call: retval = check_call((AstCall **) pexpr); break; case Ast_Kind_Argument: retval = check_argument((AstArgument **) pexpr); break; case Ast_Kind_Block: retval = check_block((AstBlock *) expr); break; @@ -1742,7 +1773,7 @@ CheckStatus check_insert_directive(AstDirectiveInsert** pinsert) { AstNode* cloned_block = ast_clone(context.ast_alloc, code_block->code); cloned_block->next = insert->next; - if (cloned_block->kind == Ast_Kind_Block) { + /*if (cloned_block->kind == Ast_Kind_Block) { AstNode* next = insert->next; insert->next = (AstNode *) ((AstBlock *) cloned_block)->body; @@ -1751,8 +1782,9 @@ CheckStatus check_insert_directive(AstDirectiveInsert** pinsert) { last_stmt->next = next; } else { + */ *(AstNode **) pinsert = cloned_block; - } + //} insert->flags |= Ast_Flag_Has_Been_Checked; @@ -1775,6 +1807,11 @@ CheckStatus check_statement(AstNode** pstmt) { case Ast_Kind_Switch: return check_switch((AstSwitch *) stmt); case Ast_Kind_Block: return check_block((AstBlock *) stmt); case Ast_Kind_Defer: return check_statement(&((AstDefer *) stmt)->stmt); + case Ast_Kind_Call: { + CHECK(call, (AstCall **) pstmt); + stmt->flags |= Ast_Flag_Expr_Ignored; + return Check_Success; + } case Ast_Kind_Binary_Op: CHECK(binaryop, (AstBinaryOp **) pstmt); @@ -2161,6 +2198,14 @@ CheckStatus check_process_directive(AstNode* directive) { return Check_Success; } +CheckStatus check_macro(AstMacro* macro) { + if (macro->body->kind == Ast_Kind_Function) { + CHECK(function_header, (AstFunction *) macro->body); + } + + return Check_Success; +} + CheckStatus check_node(AstNode* node) { switch (node->kind) { case Ast_Kind_Function: return check_function((AstFunction *) node); @@ -2170,7 +2215,7 @@ CheckStatus check_node(AstNode* node) { case Ast_Kind_If: return check_if((AstIfWhile *) node); case Ast_Kind_Static_If: return check_if((AstIfWhile *) node); case Ast_Kind_While: return check_while((AstIfWhile *) node); - case Ast_Kind_Call: return check_call((AstCall *) node); + case Ast_Kind_Call: return check_call((AstCall **) &node); case Ast_Kind_Binary_Op: return check_binaryop((AstBinaryOp **) &node); default: return check_expression((AstTyped **) &node); } @@ -2189,6 +2234,7 @@ void check_entity(Entity* ent) { case Entity_Type_Memory_Reservation_Type: cs = check_memres_type(ent->mem_res); break; case Entity_Type_Memory_Reservation: cs = check_memres(ent->mem_res); break; case Entity_Type_Static_If: cs = check_static_if(ent->static_if); break; + case Entity_Type_Macro: cs = check_macro(ent->macro); case Entity_Type_Expression: cs = check_expression(&ent->expr); diff --git a/src/onyxentities.c b/src/onyxentities.c index 3ba43d56..2c52c1f2 100644 --- a/src/onyxentities.c +++ b/src/onyxentities.c @@ -287,6 +287,13 @@ void add_entities_for_node(bh_arr(Entity *) *target_arr, AstNode* node, Scope* s ENTITY_INSERT(ent); break; } + + case Ast_Kind_Macro: { + ent.type = Entity_Type_Macro; + ent.macro = (AstMacro *) node; + ENTITY_INSERT(ent); + break; + } case Ast_Kind_Polymorphic_Proc: { ent.type = Entity_Type_Polymorphic_Proc; diff --git a/src/onyxerrors.c b/src/onyxerrors.c index 5c25f63e..0dbffbe1 100644 --- a/src/onyxerrors.c +++ b/src/onyxerrors.c @@ -72,7 +72,6 @@ b32 onyx_has_errors() { } void onyx_clear_errors() { - bh_printf("ERRORS WERE CLEARED!!!\n"); bh_arr_set_length(errors.errors, 0); } diff --git a/src/onyxlex.c b/src/onyxlex.c index 59370246..433c3b9d 100644 --- a/src/onyxlex.c +++ b/src/onyxlex.c @@ -35,6 +35,7 @@ static const char* token_type_names[] = { "switch", "case", "fallthrough", + "macro", "->", "<-", @@ -334,6 +335,9 @@ whitespace_skipped: case 'i': LITERAL_TOKEN("if", 1, Token_Type_Keyword_If); break; + case 'm': + LITERAL_TOKEN("macro", 1, Token_Type_Keyword_Macro); + break; case 'p': LITERAL_TOKEN("package", 1, Token_Type_Keyword_Package); LITERAL_TOKEN("proc", 1, Token_Type_Keyword_Proc); diff --git a/src/onyxparser.c b/src/onyxparser.c index 36f3a783..d6e61583 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -469,12 +469,14 @@ static AstTyped* parse_factor(OnyxParser* parser) { break; } + #if 0 case Token_Type_Keyword_Proc: { OnyxToken* proc_token = expect_token(parser, Token_Type_Keyword_Proc); onyx_report_warning(proc_token->pos, "Warning: 'proc' is a deprecated keyword."); retval = (AstTyped *) parse_function_definition(parser, proc_token); break; } + #endif case Token_Type_Keyword_Package: { retval = (AstTyped *) parse_package_expression(parser); @@ -616,6 +618,7 @@ static AstTyped* parse_factor(OnyxParser* parser) { if (parser->curr->type == '{') { code_block->code = (AstNode *) parse_block(parser, 1); + ((AstBlock *) code_block->code)->rules = Block_Rule_Code_Block; } else { code_block->code = (AstNode *) parse_expression(parser, 0); @@ -1435,6 +1438,7 @@ static AstNode* parse_statement(OnyxParser* parser) { static AstBlock* parse_block(OnyxParser* parser, b32 make_a_new_scope) { AstBlock* block = make_node(AstBlock, Ast_Kind_Block); + block->rules = Block_Rule_Normal; // NOTE: --- is for an empty block if (parser->curr->type == Token_Type_Empty_Block) { @@ -2018,11 +2022,6 @@ static AstOverloadedFunction* parse_overloaded_function(OnyxParser* parser, Onyx } static AstFunction* parse_function_definition(OnyxParser* parser, OnyxToken* token) { - // :TemporaryForProcRemoval - if (parser->curr->type == '{') { - return (AstFunction *) parse_overloaded_function(parser, token); - } - AstFunction* func_def = make_node(AstFunction, Ast_Kind_Function); func_def->token = token; @@ -2076,17 +2075,16 @@ static AstFunction* parse_function_definition(OnyxParser* parser, OnyxToken* tok pp->poly_params = polymorphic_vars; pp->base_func = func_def; - ENTITY_SUBMIT(pp); return (AstFunction *) pp; + } else { bh_arr_free(polymorphic_vars); - - ENTITY_SUBMIT(func_def); return func_def; } } static b32 parse_possible_function_definition(OnyxParser* parser, AstTyped** ret) { + #if 0 if (parser->curr->type == Token_Type_Keyword_Proc) { OnyxToken* proc_token = expect_token(parser, Token_Type_Keyword_Proc); onyx_report_warning(proc_token->pos, "Warning: 'proc' is a deprecated keyword."); @@ -2094,6 +2092,7 @@ static b32 parse_possible_function_definition(OnyxParser* parser, AstTyped** ret *ret = (AstTyped *) func_node; return 1; } + #endif if (parser->curr->type == '(') { OnyxToken* matching_paren = find_matching_paren(parser->curr); @@ -2120,6 +2119,7 @@ static b32 parse_possible_function_definition(OnyxParser* parser, AstTyped** ret OnyxToken* proc_token = parser->curr; AstFunction* func_node = parse_function_definition(parser, proc_token); + ENTITY_SUBMIT(func_node); *ret = (AstTyped *) func_node; return 1; } @@ -2251,7 +2251,17 @@ static AstIf* parse_static_if_stmt(OnyxParser* parser, b32 parse_block_as_statem return static_if_node; } +static AstMacro* parse_macro(OnyxParser* parser) { + AstMacro* macro = make_node(AstMacro, Ast_Kind_Macro); + macro->token = expect_token(parser, Token_Type_Keyword_Macro); + macro->body = (AstTyped *) parse_function_definition(parser, macro->token); + + ENTITY_SUBMIT(macro); + return macro; +} + static AstTyped* parse_top_level_expression(OnyxParser* parser) { + #if 0 if (parser->curr->type == Token_Type_Keyword_Proc) { OnyxToken* proc_token = expect_token(parser, Token_Type_Keyword_Proc); onyx_report_warning(proc_token->pos, "Warning: 'proc' is a deprecated keyword."); @@ -2259,10 +2269,12 @@ static AstTyped* parse_top_level_expression(OnyxParser* parser) { return (AstTyped *) func_node; } + #endif if (parser->curr->type == Token_Type_Keyword_Global) return parse_global_declaration(parser); if (parser->curr->type == Token_Type_Keyword_Struct) return (AstTyped *) parse_struct(parser); if (parser->curr->type == Token_Type_Keyword_Enum) return (AstTyped *) parse_enum_declaration(parser); + if (parser->curr->type == Token_Type_Keyword_Macro) return (AstTyped *) parse_macro(parser); if (parse_possible_directive(parser, "type")) { AstTypeAlias* alias = make_node(AstTypeAlias, Ast_Kind_Type_Alias); @@ -2304,6 +2316,15 @@ static AstBinding* parse_top_level_binding(OnyxParser* parser, OnyxToken* symbol proc->base_func->name = symbol; + } else if (node->kind == Ast_Kind_Macro) { + AstMacro* macro = (AstMacro *) node; + + AstFunction* func = (AstFunction *) macro->body; + if (func->kind == Ast_Kind_Polymorphic_Proc) + func = (AstFunction *) ((AstPolyProc *) func)->base_func; + + func->name = symbol; + } else if (node->kind == Ast_Kind_Global) { AstGlobal* global = (AstGlobal *) node; diff --git a/src/onyxsymres.c b/src/onyxsymres.c index 59202979..89b6d488 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -6,7 +6,6 @@ // Variables used during the symbol resolution phase. static Scope* curr_scope = NULL; -bh_arr(AstBlock *) block_stack = NULL; static b32 report_unresolved_symbols = 1; // Everything related to waiting on is imcomplete at the moment. @@ -57,6 +56,7 @@ static SymresStatus symres_memres_type(AstMemRes** memres); static SymresStatus symres_memres(AstMemRes** memres); static SymresStatus symres_struct_defaults(AstType* st); static SymresStatus symres_static_if(AstIf* static_if); +static SymresStatus symres_macro(AstMacro* macro); static void scope_enter(Scope* new_scope) { curr_scope = new_scope; @@ -524,6 +524,7 @@ static SymresStatus symres_if(AstIfWhile* ifnode) { SYMRES(expression, &ifnode->cond); + // NOTE: These are statements because "elseif" means the `false_stmt` has an if node. if (ifnode->true_stmt != NULL) SYMRES(statement, (AstNode **) &ifnode->true_stmt, NULL); if (ifnode->false_stmt != NULL) SYMRES(statement, (AstNode **) &ifnode->false_stmt, NULL); @@ -819,20 +820,22 @@ static SymresStatus symres_statement_chain(AstNode** walker) { } static SymresStatus symres_block(AstBlock* block) { - if (block->scope == NULL) - block->scope = scope_create(context.ast_alloc, curr_scope, block->token->pos); + if (block->rules & Block_Rule_New_Scope) { + if (block->scope == NULL) + block->scope = scope_create(context.ast_alloc, curr_scope, block->token->pos); - scope_enter(block->scope); - bh_arr_push(block_stack, block); + scope_enter(block->scope); + } if (block->binding_scope != NULL) - scope_include(block->scope, block->binding_scope, block->token->pos); + scope_include(curr_scope, block->binding_scope, block->token->pos); if (block->body) SYMRES(statement_chain, &block->body); - bh_arr_pop(block_stack); - scope_leave(); + if (block->rules & Block_Rule_New_Scope) + scope_leave(); + return Symres_Success; } @@ -1151,9 +1154,15 @@ static SymresStatus symres_process_directive(AstNode* directive) { return Symres_Success; } -void symres_entity(Entity* ent) { - if (block_stack == NULL) bh_arr_new(global_heap_allocator, block_stack, 16); +static SymresStatus symres_macro(AstMacro* macro) { + if (macro->body->kind == Ast_Kind_Function) { + SYMRES(function_header, (AstFunction *) macro->body); + } + return Symres_Success; +} + +void symres_entity(Entity* ent) { Scope* old_scope = NULL; if (ent->scope) { old_scope = curr_scope; @@ -1198,8 +1207,8 @@ void symres_entity(Entity* ent) { case Entity_Type_Polymorphic_Proc: ss = symres_polyproc(ent->poly_proc); break; case Entity_Type_String_Literal: ss = symres_expression(&ent->expr); break; case Entity_Type_Struct_Member_Default: ss = symres_struct_defaults((AstType *) ent->type_alias); break; - case Entity_Type_Process_Directive: ss = symres_process_directive((AstNode *) ent->expr); - break; + case Entity_Type_Process_Directive: ss = symres_process_directive((AstNode *) ent->expr); break; + case Entity_Type_Macro: ss = symres_macro(ent->macro); break; default: break; } diff --git a/src/onyxutils.c b/src/onyxutils.c index beedd9d9..3f048d31 100644 --- a/src/onyxutils.c +++ b/src/onyxutils.c @@ -921,7 +921,6 @@ AstNode* polymorphic_proc_try_solidify(AstPolyProc* pp, bh_arr(AstPolySolution) AstPolyProc* new_pp = onyx_ast_node_new(context.ast_alloc, sizeof(AstPolyProc), Ast_Kind_Polymorphic_Proc); new_pp->token = pp->token; // TODO: Change this to be the solidify->token new_pp->base_func = pp->base_func; - new_pp->poly_scope = new_pp->poly_scope; // CLEANUP: This doesn't seem correct?? new_pp->flags = pp->flags; new_pp->poly_params = pp->poly_params; diff --git a/src/onyxwasm.c b/src/onyxwasm.c index 0bc1cb45..1114c59c 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -280,6 +280,8 @@ EMIT_FUNC(function_body, AstFunction* fd) { EMIT_FUNC(block, AstBlock* block, b32 generate_block_headers) { bh_arr(WasmInstruction) code = *pcode; + generate_block_headers = generate_block_headers && (block->rules & Block_Rule_New_Scope); + if (generate_block_headers) emit_enter_structured_block(mod, &code, SBT_Breakable_Block); @@ -287,8 +289,8 @@ EMIT_FUNC(block, AstBlock* block, b32 generate_block_headers) { emit_statement(mod, &code, stmt); } - emit_deferred_stmts(mod, &code); - emit_free_local_allocations(mod, &code); + if (block->rules & Block_Rule_Clear_Defer) emit_deferred_stmts(mod, &code); + if (block->rules & Block_Rule_New_Scope) emit_free_local_allocations(mod, &code); if (generate_block_headers) emit_leave_structured_block(mod, &code); @@ -1200,7 +1202,7 @@ EMIT_FUNC_NO_ARGS(deferred_stmts) { u64 depth = bh_arr_length(mod->structured_jump_target); - while (bh_arr_length(mod->deferred_stmts) > 0 && bh_arr_last(mod->deferred_stmts).depth == depth) { + while (bh_arr_length(mod->deferred_stmts) > 0 && bh_arr_last(mod->deferred_stmts).depth >= depth) { emit_deferred_stmt(mod, pcode, bh_arr_last(mod->deferred_stmts)); bh_arr_pop(mod->deferred_stmts); }