NODE(Compound) \
\
NODE(DirectiveSolidify) \
- NODE(StaticIf) \
NODE(DirectiveError) \
NODE(DirectiveAddOverload) \
NODE(DirectiveOperator) \
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;
};
-struct AstStaticIf {
- AstNode_base;
-
- AstTyped* cond;
-
- bh_arr(struct Entity *) true_entities;
- bh_arr(struct Entity *) false_entities;
-};
-
struct AstDirectiveError {
AstNode_base;
AstDirectiveError *error;
AstInclude *include;
AstBinding *binding;
- AstStaticIf *static_if;
+ AstIf *static_if;
AstFunction *function;
AstOverloadedFunction *overloaded_function;
AstGlobal *global;
// 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,
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
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;
}
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);
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)) {
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);
}
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);
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;
}
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);
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:
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);
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);
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);
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;
}
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;
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;
}
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;
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;
}
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;
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);