static ifs in procedure are much better now
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 27 Jan 2022 05:16:45 +0000 (23:16 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 27 Jan 2022 05:16:45 +0000 (23:16 -0600)
core/container/map.onyx
include/astnodes.h
include/parser.h
src/clone.c
src/parser.c
src/symres.c
src/utils.c

index c88017691a0ce263f09a9754dd3c663ad44d432c..e72a46cd478b88551cfc9e280893b34b9bae3392 100644 (file)
@@ -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
index 521952f8ac53c39e27de225bc44e1e5fb3080788..0354c0e873b53ef3fec2e93d2cf467640af44ff8 100644 (file)
@@ -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;
index 2f48c4833330e4f28b1abec33da910fd258b1874..70a35b96f66a6d3e92b3bf8ff25415757f838f1f 100644 (file)
@@ -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;
index db7215a5fcdf2785898d9613e767e6af9593beb9..d7b7d26c131cee9d43034a7c191d35c63ff952e4 100644 (file)
@@ -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;
 }
index 9345a00541b4c11a1fad8c40602f28daca50a356..5d52cf8254bdfcdd9c8d68319e0febf098f7c53e 100644 (file)
@@ -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;
 
index 41bee0a0cfcae0b90dc937dbbebf7d936f042f2c..7a4175b4f5528f313c7be7a4bd5a60c6bd157690 100644 (file)
@@ -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;
 }
index efc77b5087c87b51a7709ee61f31233cd9afd8b7..c06a25b7d3e09c4cd82be455c9c11ccd266d5f29 100644 (file)
@@ -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;