From: Brendan Hansen Date: Tue, 1 Jun 2021 14:10:28 +0000 (-0500) Subject: added static if statements in procedures; a little limited at the moment X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=6580bf426160ad852abcf136a9dee1c793cd4a1d;p=onyx.git added static if statements in procedures; a little limited at the moment --- diff --git a/bin/onyx b/bin/onyx index b1a21794..e4eccdcb 100755 Binary files a/bin/onyx and b/bin/onyx differ diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index 4db208e9..87c20fa2 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -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, diff --git a/src/onyxastnodes.c b/src/onyxastnodes.c index aa711518..4db5c8f5 100644 --- a/src/onyxastnodes.c +++ b/src/onyxastnodes.c @@ -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 diff --git a/src/onyxchecker.c b/src/onyxchecker.c index 7e4ab81e..333b75b4 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -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); diff --git a/src/onyxentities.c b/src/onyxentities.c index c5b1972e..410d13ae 100644 --- a/src/onyxentities.c +++ b/src/onyxentities.c @@ -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; } diff --git a/src/onyxparser.c b/src/onyxparser.c index 007d3ac4..43de83c0 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -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; } diff --git a/src/onyxsymres.c b/src/onyxsymres.c index e6bbc20c..fefc9295 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -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; } diff --git a/src/onyxwasm.c b/src/onyxwasm.c index 851c7444..8f40cce8 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -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);