From: Brendan Hansen Date: Thu, 27 Jan 2022 05:16:45 +0000 (-0600) Subject: static ifs in procedure are much better now X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=5abb2c72939b38f0c6062ad65fb94f6841cce77a;p=onyx.git static ifs in procedure are much better now --- diff --git a/core/container/map.onyx b/core/container/map.onyx index c8801769..e72a46cd 100644 --- a/core/container/map.onyx +++ b/core/container/map.onyx @@ -38,6 +38,7 @@ Map :: struct (Key_Type: type_expr, Value_Type: type_expr) where ValidKey(Key_Ty value : V; } + init :: init has :: has get :: get get_ptr :: get_ptr diff --git a/include/astnodes.h b/include/astnodes.h index 521952f8..0354c0e8 100644 --- a/include/astnodes.h +++ b/include/astnodes.h @@ -271,6 +271,8 @@ typedef enum AstFlags { Ast_Flag_Decl_Followed_By_Init = BH_BIT(20), Ast_Flag_Param_Symbol_Dirty = BH_BIT(21), + + Ast_Flag_Dead = BH_BIT(22), } AstFlags; typedef enum UnaryOp { @@ -1178,6 +1180,8 @@ struct AstFunction { Table(AstSolidifiedFunction) concrete_funcs; bh_imap active_queries; + bh_arr(AstNode *) nodes_that_need_entities_after_clone; + b32 is_exported : 1; b32 is_foreign : 1; b32 is_intrinsic : 1; diff --git a/include/parser.h b/include/parser.h index 2f48c483..70a35b96 100644 --- a/include/parser.h +++ b/include/parser.h @@ -25,6 +25,7 @@ typedef struct OnyxParser { PolymorphicContext polymorph_context; + bh_arr(AstFunction *) current_function_stack; Scope *current_scope; bh_arr(bh_arr(Entity *) *) alternate_entity_placement_stack; bh_arr(OnyxToken *) current_symbol_stack; diff --git a/src/clone.c b/src/clone.c index db7215a5..d7b7d26c 100644 --- a/src/clone.c +++ b/src/clone.c @@ -109,6 +109,7 @@ static inline i32 ast_kind_to_size(AstNode* node) { 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_Directive_Defined: return sizeof(AstDirectiveDefined); case Ast_Kind_Do_Block: return sizeof(AstDoBlock); case Ast_Kind_Constraint: return sizeof(AstConstraint); case Ast_Kind_Count: return 0; @@ -135,6 +136,14 @@ AstNode* ast_clone_list(bh_allocator a, void* n) { return root; } +static bh_arr(AstNode *) captured_entities=NULL; +#define E(ent) do { \ + assert(captured_entities); \ + ent->entity = NULL; \ + bh_arr_push(captured_entities, (AstNode *) ent); \ + } while (0); + + #define C(nt, mname) ((nt *) nn)->mname = (void *) ast_clone(a, ((nt *) node)->mname); // NOTE: Using void* to avoid a lot of unnecessary casting @@ -257,13 +266,23 @@ AstNode* ast_clone(bh_allocator a, void* n) { case Ast_Kind_If: case Ast_Kind_While: ((AstIfWhile *) nn)->initialization = ast_clone_list(a, ((AstIfWhile *) node)->initialization); - - C(AstIfWhile, cond); //fallthrough case Ast_Kind_Static_If: + C(AstIfWhile, cond); + C(AstIfWhile, true_stmt); C(AstIfWhile, false_stmt); + + if (nn->kind == Ast_Kind_Static_If) { + ((AstIfWhile *) node)->flags |= Ast_Flag_Dead; + ((AstIfWhile *) node)->flags |= Ast_Flag_Static_If_Resolved; + + ((AstIfWhile *) nn)->flags &= ~Ast_Flag_Dead; + ((AstIfWhile *) nn)->flags &= ~Ast_Flag_Static_If_Resolved; + E(nn); + } + break; case Ast_Kind_Switch_Case: { @@ -421,9 +440,16 @@ AstNode* ast_clone(bh_allocator a, void* n) { if (sf->is_foreign) return node; assert(df->scope == NULL); + df->nodes_that_need_entities_after_clone = NULL; + bh_arr_new(global_heap_allocator, df->nodes_that_need_entities_after_clone, 1); + captured_entities = df->nodes_that_need_entities_after_clone; + df->return_type = (AstType *) ast_clone(a, sf->return_type); df->body = (AstBlock *) ast_clone(a, sf->body); + df->nodes_that_need_entities_after_clone = captured_entities; + captured_entities = NULL; + df->params = NULL; bh_arr_new(global_heap_allocator, df->params, bh_arr_length(sf->params)); @@ -522,6 +548,11 @@ AstNode* ast_clone(bh_allocator a, void* n) { C(AstDirectiveInsert, code_expr); break; + case Ast_Kind_Directive_Defined: + C(AstDirectiveDefined, expr); + ((AstDirectiveDefined *) nn)->is_defined = 0; + break; + case Ast_Kind_Typeof: C(AstTypeOf, expr); ((AstTypeOf *) nn)->resolved_type = NULL; @@ -586,5 +617,12 @@ void clone_function_body(bh_allocator a, AstFunction* dest, AstFunction* source) if (dest->kind != Ast_Kind_Function) return; if (source->kind != Ast_Kind_Polymorphic_Proc && source->kind != Ast_Kind_Function) return; + dest->nodes_that_need_entities_after_clone = NULL; + bh_arr_new(global_heap_allocator, dest->nodes_that_need_entities_after_clone, 1); + captured_entities = dest->nodes_that_need_entities_after_clone; + dest->body = (AstBlock *) ast_clone(a, source->body); + + dest->nodes_that_need_entities_after_clone = captured_entities; + captured_entities = NULL; } diff --git a/src/parser.c b/src/parser.c index 9345a005..5d52cf82 100644 --- a/src/parser.c +++ b/src/parser.c @@ -1507,7 +1507,9 @@ static AstNode* parse_statement(OnyxParser* parser) { if (next_tokens_are(parser, 2, '#', Token_Type_Keyword_If)) { AstIf* static_if = parse_static_if_stmt(parser, 1); - ENTITY_SUBMIT(static_if); + + assert(parser->current_function_stack && bh_arr_length(parser->current_function_stack) > 0); + bh_arr_push(bh_arr_last(parser->current_function_stack)->nodes_that_need_entities_after_clone, (AstNode *) static_if); needs_semicolon = 0; retval = (AstNode *) static_if; @@ -2305,6 +2307,7 @@ static AstOverloadedFunction* parse_overloaded_function(OnyxParser* parser, Onyx static AstFunction* parse_function_definition(OnyxParser* parser, OnyxToken* token) { AstFunction* func_def = make_node(AstFunction, Ast_Kind_Function); func_def->token = token; + bh_arr_push(parser->current_function_stack, func_def); bh_arr_new(global_heap_allocator, func_def->params, 4); @@ -2400,6 +2403,7 @@ function_defined: bh_arr_free(polymorphic_vars); } + bh_arr_pop(parser->current_function_stack); return func_def; } @@ -2547,6 +2551,7 @@ static b32 parse_possible_quick_function_definition(OnyxParser* parser, AstTyped AstBlock* body_block; AstType* return_type; + bh_arr_push(parser->current_function_stack, poly_proc); if (parser->curr->type == '{') { char* name = NULL; @@ -2597,6 +2602,7 @@ static b32 parse_possible_quick_function_definition(OnyxParser* parser, AstTyped *ret = (AstTyped *) poly_proc; + bh_arr_pop(parser->current_function_stack); bh_arr_free(params); bh_arr_free(poly_params); return 1; @@ -3264,6 +3270,7 @@ OnyxParser onyx_parser_create(bh_allocator alloc, OnyxTokenizer *tokenizer) { parser.current_scope = NULL; parser.alternate_entity_placement_stack = NULL; parser.current_symbol_stack = NULL; + parser.current_function_stack = NULL; parser.scope_flags = NULL; parser.parse_calls = 1; diff --git a/src/symres.c b/src/symres.c index 41bee0a0..7a4175b4 100644 --- a/src/symres.c +++ b/src/symres.c @@ -288,7 +288,7 @@ static SymresStatus symres_field_access(AstFieldAccess** fa) { AstTyped* expr = (AstTyped *) strip_aliases((AstNode *) (*fa)->expr); b32 force_a_lookup = 0; - if (expr->kind == Ast_Kind_Enum_Type) { + if (expr->kind == Ast_Kind_Enum_Type || expr->kind == Ast_Kind_Type_Raw_Alias) { force_a_lookup = 1; } @@ -568,7 +568,12 @@ static SymresStatus symres_return(AstReturn* ret) { static SymresStatus symres_if(AstIfWhile* ifnode) { if (ifnode->kind == Ast_Kind_Static_If) { if ((ifnode->flags & Ast_Flag_Static_If_Resolved) == 0) { - return Symres_Yield_Macro; + if (context.cycle_detected) { + onyx_report_error(ifnode->token->pos, Error_Waiting_On, "Waiting on static if resolution."); + return Symres_Error; + } else { + return Symres_Yield_Macro; + } } if (static_if_resolution(ifnode)) { @@ -799,8 +804,9 @@ static SymresStatus symres_directive_defined(AstDirectiveDefined** pdefined) { b32 use_package_count = (context.entities.type_count[Entity_Type_Use_Package] == 0); + resolved_a_symbol = 0; SymresStatus ss = symres_expression(&defined->expr); - if (use_package_count && ss != Symres_Success) { + if (use_package_count && ss != Symres_Success && !resolved_a_symbol) { // The symbol definitely was not found and there is no chance that it could be found. defined->is_defined = 0; return Symres_Success; @@ -949,6 +955,15 @@ SymresStatus symres_function_header(AstFunction* func) { return Symres_Complete; } + if (func->nodes_that_need_entities_after_clone && bh_arr_length(func->nodes_that_need_entities_after_clone) > 0) { + bh_arr_each(AstNode *, node, func->nodes_that_need_entities_after_clone) { + // Need to curr_scope->parent because curr_scope is the function body scope. + add_entities_for_node(NULL, *node, curr_scope->parent, func->entity->package); + } + + bh_arr_set_length(func->nodes_that_need_entities_after_clone, 0); + } + SYMRES(type, &func->return_type); if (func->constraints.constraints != NULL) { @@ -1198,6 +1213,8 @@ static SymresStatus symres_polyproc(AstFunction* pp) { } static SymresStatus symres_static_if(AstIf* static_if) { + if (static_if->flags & Ast_Flag_Dead) return Symres_Complete; + SYMRES(expression, &static_if->cond); return Symres_Success; } diff --git a/src/utils.c b/src/utils.c index efc77b50..c06a25b7 100644 --- a/src/utils.c +++ b/src/utils.c @@ -211,7 +211,19 @@ all_types_peeled_off: case Ast_Kind_Struct_Type: { AstStructType* stype = (AstStructType *) node; - AstNode* result = symbol_raw_resolve(stype->scope, symbol); + + // HACK HACK + // Temporarily disable the parent scope so that you can't access things + // "above" the structures scope. This leads to unintended behavior, as when + // you are accessing a static element on a structure, you don't expect to + // bleed to the top level scope. + AstNode *result = NULL; + if (stype->scope) { + Scope *tmp_parent = stype->scope->parent; + stype->scope->parent = NULL; + result = symbol_raw_resolve(stype->scope, symbol); + stype->scope->parent = tmp_parent; + } if (result == NULL && stype->stcache != NULL) { Type* struct_type = stype->stcache;