added static if statements in procedures; a little limited at the moment
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 1 Jun 2021 14:10:28 +0000 (09:10 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 1 Jun 2021 14:10:28 +0000 (09:10 -0500)
bin/onyx
include/onyxastnodes.h
src/onyxastnodes.c
src/onyxchecker.c
src/onyxentities.c
src/onyxparser.c
src/onyxsymres.c
src/onyxwasm.c

index b1a21794a5d9904d15aaab88e570ade524a0fc65..e4eccdcb078803ccbc87908f29c76b0f263e93cf 100755 (executable)
Binary files a/bin/onyx and b/bin/onyx differ
index 4db208e99032a724781f4db926a1ee8918ba0987..87c20fa2738a3f756ac504381771955086a77d7b 100644 (file)
@@ -30,7 +30,6 @@
     NODE(Compound)             \
                                \
     NODE(DirectiveSolidify)    \
-    NODE(StaticIf)             \
     NODE(DirectiveError)       \
     NODE(DirectiveAddOverload) \
     NODE(DirectiveOperator)    \
@@ -626,7 +625,14 @@ struct AstIfWhile {
 
     AstBlock *true_stmt;
     AstBlock *false_stmt;
+
+    // Used by Static_If
+    bh_arr(struct Entity *) true_entities;
+    bh_arr(struct Entity *) false_entities;
 };
+typedef struct AstIfWhile AstIf;
+typedef struct AstIfWhile AstWhile;
+
 struct AstSwitchCase {
     // NOTE: All expressions that end up in this block
     bh_arr(AstTyped *) values;
@@ -882,15 +888,6 @@ struct AstPolyProc {
 };
 
 
-struct AstStaticIf {
-    AstNode_base;
-
-    AstTyped* cond;
-
-    bh_arr(struct Entity *) true_entities;
-    bh_arr(struct Entity *) false_entities;
-};
-
 struct AstDirectiveError {
     AstNode_base;
 
@@ -991,7 +988,7 @@ typedef struct Entity {
         AstDirectiveError     *error;
         AstInclude            *include;
         AstBinding            *binding;
-        AstStaticIf           *static_if;
+        AstIf                 *static_if;
         AstFunction           *function;
         AstOverloadedFunction *overloaded_function;
         AstGlobal             *global;
@@ -1202,6 +1199,8 @@ void arguments_remove_baked(Arguments* args);
 // GROSS: Using void* to avoid having to cast everything.
 const char* node_get_type_name(void* node);
 
+b32 static_if_resolution(AstIf* static_if);
+
 typedef enum PolyProcLookupMethod {
     PPLM_By_Arguments,
     PPLM_By_Function_Type,
index aa711518af55da4a0bb4555e7ce66412c3f00f6c..4db5c8f50861aa4d263800664880ab6f833a444a 100644 (file)
@@ -859,3 +859,12 @@ const char* node_get_type_name(void* node) {
 
     return type_get_name(((AstTyped *) node)->type);
 }
+
+b32 static_if_resolution(AstIf* static_if) {
+    if (static_if->kind != Ast_Kind_Static_If) return 0;
+
+    AstNumLit* condition_value = (AstNumLit *) static_if->cond;
+    assert(condition_value->kind == Ast_Kind_NumLit); // This should be right, right?
+
+    return condition_value->value.i != 0;
+}
\ No newline at end of file
index 7e4ab81e03d542afa3a5e35d2624e2e553655ceb..333b75b49ebf0a80c4e6d735a62a8cf4a5f29d6f 100644 (file)
@@ -125,15 +125,25 @@ CheckStatus check_return(AstReturn* retnode) {
 CheckStatus check_if(AstIfWhile* ifnode) {
     if (ifnode->assignment != NULL) CHECK(statement, (AstNode **) &ifnode->assignment);
 
-    CHECK(expression, &ifnode->cond);
+    if (ifnode->kind == Ast_Kind_Static_If) {
+        if (static_if_resolution(ifnode)) {
+            if (ifnode->true_stmt != NULL) CHECK(statement, (AstNode **) &ifnode->true_stmt);
+            
+        } else {
+            if (ifnode->false_stmt != NULL) CHECK(statement, (AstNode **) &ifnode->false_stmt);
+        }
 
-    if (!type_is_bool(ifnode->cond->type)) {
-        onyx_report_error(ifnode->cond->token->pos, "expected boolean type for condition");
-        return Check_Error;
-    }
+    } else {
+        CHECK(expression, &ifnode->cond);
 
-    if (ifnode->true_stmt)  CHECK(statement, (AstNode **) &ifnode->true_stmt);
-    if (ifnode->false_stmt) CHECK(statement, (AstNode **) &ifnode->false_stmt);
+        if (!type_is_bool(ifnode->cond->type)) {
+            onyx_report_error(ifnode->cond->token->pos, "expected boolean type for condition");
+            return Check_Error;
+        }
+
+        if (ifnode->true_stmt)  CHECK(statement, (AstNode **) &ifnode->true_stmt);
+        if (ifnode->false_stmt) CHECK(statement, (AstNode **) &ifnode->false_stmt);
+    }
 
     return Check_Success;
 }
@@ -1488,6 +1498,7 @@ CheckStatus check_statement(AstNode** pstmt) {
 
         case Ast_Kind_Return:     return check_return((AstReturn *) stmt);
         case Ast_Kind_If:         return check_if((AstIfWhile *) stmt);
+        case Ast_Kind_Static_If:  return check_if((AstIfWhile *) stmt);
         case Ast_Kind_While:      return check_while((AstIfWhile *) stmt);
         case Ast_Kind_For:        return check_for((AstFor *) stmt);
         case Ast_Kind_Switch:     return check_switch((AstSwitch *) stmt);
@@ -1778,7 +1789,7 @@ CheckStatus check_type(AstType* type) {
     return Check_Success;
 }
 
-CheckStatus check_static_if(AstStaticIf* static_if) {
+CheckStatus check_static_if(AstIf* static_if) {
     CheckStatus result = check_expression(&static_if->cond);
 
     if (result > Check_Errors_Start || !(static_if->cond->flags & Ast_Flag_Comptime)) {
@@ -1791,17 +1802,16 @@ CheckStatus check_static_if(AstStaticIf* static_if) {
         return Check_Error;
     }
 
-    AstNumLit* condition_value = (AstNumLit *) static_if->cond;
-    assert(condition_value->kind == Ast_Kind_NumLit); // This should be right, right?
+    b32 resolution = static_if_resolution(static_if);
 
     if (context.options->print_static_if_results)
         bh_printf("Static if statement at %s:%d:%d resulted in %s\n",
             static_if->token->pos.filename,
             static_if->token->pos.line,
             static_if->token->pos.column,
-            condition_value->value.i ? "true" : "false");
+            resolution ? "true" : "false");
 
-    if (condition_value->value.i) {
+    if (resolution) {
         bh_arr_each(Entity *, ent, static_if->true_entities) {
             entity_heap_insert_existing(&context.entities, *ent);
         }
@@ -1822,6 +1832,7 @@ CheckStatus check_node(AstNode* node) {
         case Ast_Kind_Block:                return check_block((AstBlock *) node);
         case Ast_Kind_Return:               return check_return((AstReturn *) 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_Binary_Op:            return check_binaryop((AstBinaryOp **) &node, 1);
index c5b1972e7ee1d366a37ae3910b582b8932c6e86a..410d13ae3ef8f4d1024f70ccdd6acef4d53d51d2 100644 (file)
@@ -290,7 +290,7 @@ void add_entities_for_node(bh_arr(Entity *) *target_arr, AstNode* node, Scope* s
         case Ast_Kind_Static_If: {
             ent.state = Entity_State_Comptime_Resolve_Symbols;
             ent.type = Entity_Type_Static_If;
-            ent.static_if = (AstStaticIf *) node;
+            ent.static_if = (AstIf *) node;
             ENTITY_INSERT(ent);
             break;
         }
index 007d3ac431e8d2c683cff2f9ecc7d9bfbe0ae719..43de83c034f0c0fb961b2c82aa1319f0f83e0e2a 100644 (file)
@@ -64,7 +64,7 @@ static b32            parse_possible_function_definition(OnyxParser* parser, Ast
 static AstFunction*   parse_function_definition(OnyxParser* parser, OnyxToken* token);
 static AstTyped*      parse_global_declaration(OnyxParser* parser);
 static AstEnumType*   parse_enum_declaration(OnyxParser* parser);
-static AstStaticIf*   parse_static_if_stmt(OnyxParser* parser);
+static AstIf*         parse_static_if_stmt(OnyxParser* parser, b32 parse_block_as_statements);
 static AstTyped*      parse_top_level_expression(OnyxParser* parser);
 static AstBinding*    parse_top_level_binding(OnyxParser* parser, OnyxToken* symbol);
 static void           parse_top_level_statement(OnyxParser* parser);
@@ -1320,16 +1320,16 @@ static AstNode* parse_statement(OnyxParser* parser) {
             This is in theory where the static if in procedures will be parsed. However,
             this breaks many things because static if statements currently only parse top
             level expressions in them, not general statements.
+            */
 
             if (next_tokens_are(parser, 2, '#', Token_Type_Keyword_If)) {
-                AstStaticIf* static_if = parse_static_if_stmt(parser);
+                AstIf* static_if = parse_static_if_stmt(parser, 1);
                 ENTITY_SUBMIT(static_if);
 
                 needs_semicolon = 0;
                 retval = (AstNode *) static_if;
                 break;
             }
-            */
         }
 
         default:
@@ -2072,8 +2072,8 @@ static AstEnumType* parse_enum_declaration(OnyxParser* parser) {
     return enum_node;
 }
 
-static AstStaticIf* parse_static_if_stmt(OnyxParser* parser) {
-    AstStaticIf* static_if_node = make_node(AstStaticIf, Ast_Kind_Static_If);
+static AstIf* parse_static_if_stmt(OnyxParser* parser, b32 parse_block_as_statements) {
+    AstIf* static_if_node = make_node(AstIf, Ast_Kind_Static_If);
     static_if_node->token = expect_token(parser, '#');
     expect_token(parser, Token_Type_Keyword_If);
 
@@ -2082,11 +2082,16 @@ static AstStaticIf* parse_static_if_stmt(OnyxParser* parser) {
     bh_arr_new(global_heap_allocator, static_if_node->true_entities, 2);
     bh_arr_push(parser->alternate_entity_placement_stack, &static_if_node->true_entities);
 
-    expect_token(parser, '{');
-    while (!consume_token_if_next(parser, '}')) {
-        if (parser->hit_unexpected_token) return static_if_node;
+    if (parse_block_as_statements) {
+        static_if_node->true_stmt = parse_block(parser);
 
-        parse_top_level_statement(parser);
+    } else {
+        expect_token(parser, '{');
+        while (!consume_token_if_next(parser, '}')) {
+            if (parser->hit_unexpected_token) return static_if_node;
+
+            parse_top_level_statement(parser);
+        }
     }
 
     bh_arr_pop(parser->alternate_entity_placement_stack);
@@ -2095,11 +2100,16 @@ static AstStaticIf* parse_static_if_stmt(OnyxParser* parser) {
         bh_arr_new(global_heap_allocator, static_if_node->false_entities, 2);
         bh_arr_push(parser->alternate_entity_placement_stack, &static_if_node->false_entities);
 
-        expect_token(parser, '{');
-        while (!consume_token_if_next(parser, '}')) {
-            if (parser->hit_unexpected_token) return static_if_node;
+        if (parse_block_as_statements) {
+            static_if_node->false_stmt = parse_block(parser);
 
-            parse_top_level_statement(parser);
+        } else {
+            expect_token(parser, '{');
+            while (!consume_token_if_next(parser, '}')) {
+                if (parser->hit_unexpected_token) return static_if_node;
+
+                parse_top_level_statement(parser);
+            }
         }
 
         bh_arr_pop(parser->alternate_entity_placement_stack);
@@ -2234,7 +2244,7 @@ static void parse_top_level_statement(OnyxParser* parser) {
 
         case '#': {
             if (next_tokens_are(parser, 2, '#', Token_Type_Keyword_If)) {
-                AstStaticIf* static_if = parse_static_if_stmt(parser);
+                AstIf* static_if = parse_static_if_stmt(parser, 0);
                 ENTITY_SUBMIT(static_if);
                 return;
             }
index e6bbc20c69201c79b197f52f39e9b49a251db042..fefc9295cebc2dfe9c5d4319b6cffc1c8be44669 100644 (file)
@@ -55,7 +55,7 @@ static SymresStatus symres_enum(AstEnumType* enum_node);
 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(AstStaticIf* static_if);
+static SymresStatus symres_static_if(AstIf* static_if);
 
 static void scope_enter(Scope* new_scope) {
     curr_scope = new_scope;
@@ -498,12 +498,22 @@ static SymresStatus symres_if(AstIfWhile* ifnode) {
         SYMRES(statement, (AstNode **) &ifnode->assignment, NULL);
     }
 
-    SYMRES(expression, &ifnode->cond);
+    if (ifnode->kind == Ast_Kind_Static_If) {
+        if (static_if_resolution(ifnode)) {
+            if (ifnode->true_stmt != NULL)  SYMRES(statement, (AstNode **) &ifnode->true_stmt, NULL);
+            
+        } else {
+            if (ifnode->false_stmt != NULL) SYMRES(statement, (AstNode **) &ifnode->false_stmt, NULL);
+        }
 
-    if (ifnode->true_stmt != NULL)  SYMRES(statement, (AstNode **) &ifnode->true_stmt, NULL);
-    if (ifnode->false_stmt != NULL) SYMRES(statement, (AstNode **) &ifnode->false_stmt, NULL);
+    } else {
+        SYMRES(expression, &ifnode->cond);
+
+        if (ifnode->true_stmt != NULL)  SYMRES(statement, (AstNode **) &ifnode->true_stmt, NULL);
+        if (ifnode->false_stmt != NULL) SYMRES(statement, (AstNode **) &ifnode->false_stmt, NULL);
 
-    if (ifnode->assignment != NULL) scope_leave();
+        if (ifnode->assignment != NULL) scope_leave();
+    }
 
     return Symres_Success;
 }
@@ -717,6 +727,7 @@ static SymresStatus symres_statement(AstNode** stmt, b32 *remove) {
     switch ((*stmt)->kind) {
         case Ast_Kind_Return:      SYMRES(return, (AstReturn *) *stmt);                  break;
         case Ast_Kind_If:          SYMRES(if, (AstIfWhile *) *stmt);                     break;
+        case Ast_Kind_Static_If:   SYMRES(if, (AstIfWhile *) *stmt);                     break;
         case Ast_Kind_While:       SYMRES(while, (AstIfWhile *) *stmt);                  break;
         case Ast_Kind_For:         SYMRES(for, (AstFor *) *stmt);                        break;
         case Ast_Kind_Switch:      SYMRES(switch, (AstSwitch *) *stmt);                  break;
@@ -993,7 +1004,7 @@ static SymresStatus symres_polyproc(AstPolyProc* pp) {
     return Symres_Success;
 }
 
-static SymresStatus symres_static_if(AstStaticIf* static_if) {
+static SymresStatus symres_static_if(AstIf* static_if) {
     SYMRES(expression, &static_if->cond);
     return Symres_Success;
 }
index 851c744458be46cd18451ed370703e5883ca8973..8f40cce895622da1037ca67c90408930f303d796 100644 (file)
@@ -387,6 +387,7 @@ EMIT_FUNC(statement, AstNode* stmt) {
     switch (stmt->kind) {
         case Ast_Kind_Return:     emit_return(mod, &code, (AstReturn *) stmt); break;
         case Ast_Kind_If:         emit_if(mod, &code, (AstIfWhile *) stmt); break;
+        case Ast_Kind_Static_If:  emit_if(mod, &code, (AstIfWhile *) stmt); break;
         case Ast_Kind_While:      emit_while(mod, &code, (AstIfWhile *) stmt); break;
         case Ast_Kind_For:        emit_for(mod, &code, (AstFor *) stmt); break;
         case Ast_Kind_Switch:     emit_switch(mod, &code, (AstSwitch *) stmt); break;
@@ -662,6 +663,17 @@ EMIT_FUNC(if, AstIfWhile* if_node) {
         emit_assignment(mod, &code, if_node->assignment);
     }
 
+    if (if_node->kind == Ast_Kind_Static_If) {
+        if (static_if_resolution(if_node)) {
+            if (if_node->true_stmt) emit_block(mod, &code, if_node->true_stmt, 1);
+        } else {
+            if (if_node->false_stmt) emit_block(mod, &code, if_node->false_stmt, 1);
+        }
+
+        *pcode = code;
+        return;
+    }
+
     emit_expression(mod, &code, if_node->cond);
 
     emit_enter_structured_block(mod, &code, SBT_Basic_If);