diff options
| author | gingerBill <bill@gingerbill.org> | 2023-07-19 12:55:44 +0100 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2023-07-19 12:55:44 +0100 |
| commit | 32ac319525832794f3758daf3a08869deca30770 (patch) | |
| tree | f8a2778fa527a5d7bb70ca25f1f23217c7506871 /src/tilde_stmt.cpp | |
| parent | 569397bd7eeb8db7aeff0033b3d8cb79af2c9893 (diff) | |
Implement if statements
Diffstat (limited to 'src/tilde_stmt.cpp')
| -rw-r--r-- | src/tilde_stmt.cpp | 58 |
1 files changed, 56 insertions, 2 deletions
diff --git a/src/tilde_stmt.cpp b/src/tilde_stmt.cpp index ff4c007ea..bd856e542 100644 --- a/src/tilde_stmt.cpp +++ b/src/tilde_stmt.cpp @@ -852,6 +852,57 @@ gb_internal void cg_build_return_stmt(cgProcedure *p, Slice<Ast *> const &return } } +gb_internal void cg_build_if_stmt(cgProcedure *p, Ast *node) { + ast_node(is, IfStmt, node); + cg_scope_open(p, is->scope); // Scope #1 + defer (cg_scope_close(p, cgDeferExit_Default, nullptr)); + + if (is->init != nullptr) { + TB_Node *init = tb_inst_region_with_name(p->func, -1, "if_init"); + tb_inst_goto(p->func, init); + tb_inst_set_control(p->func, init); + cg_build_stmt(p, is->init); + } + + TB_Node *then = tb_inst_region_with_name(p->func, -1, "if_then"); + TB_Node *done = tb_inst_region_with_name(p->func, -1, "if_done"); + TB_Node *else_ = done; + if (is->else_stmt != nullptr) { + else_ = tb_inst_region_with_name(p->func, -1, "if_else"); + } + + cgValue cond = cg_build_cond(p, is->cond, then, else_); + gb_unused(cond); + + if (is->label != nullptr) { + cgTargetList *tl = cg_push_target_list(p, is->label, done, nullptr, nullptr); + tl->is_block = true; + } + + // TODO(bill): should we do a constant check? + // Which philosophy are we following? + // - IR represents what the code represents (probably this) + // - IR represents what the code executes + + tb_inst_set_control(p->func, then); + + cg_build_stmt(p, is->body); + + tb_inst_goto(p->func, done); + + if (is->else_stmt != nullptr) { + tb_inst_set_control(p->func, else_); + + cg_scope_open(p, scope_of_node(is->else_stmt)); + cg_build_stmt(p, is->else_stmt); + cg_scope_close(p, cgDeferExit_Default, nullptr); + + tb_inst_goto(p->func, done); + } + + tb_inst_set_control(p->func, done); +} + gb_internal void cg_build_stmt(cgProcedure *p, Ast *node) { Ast *prev_stmt = p->curr_stmt; @@ -907,8 +958,7 @@ gb_internal void cg_build_stmt(cgProcedure *p, Ast *node) { case_ast_node(bs, BlockStmt, node); TB_Node *done = nullptr; if (bs->label != nullptr) { - done = tb_inst_region(p->func); - tb_inst_set_region_name(done, -1, "block.done"); + done = tb_inst_region_with_name(p->func, -1, "block_done"); cgTargetList *tl = cg_push_target_list(p, bs->label, done, nullptr, nullptr); tl->is_block = true; } @@ -1040,6 +1090,10 @@ gb_internal void cg_build_stmt(cgProcedure *p, Ast *node) { cg_build_return_stmt(p, rs->results); case_end; + case_ast_node(is, IfStmt, node); + cg_build_if_stmt(p, node); + case_end; + default: GB_PANIC("TODO cg_build_stmt %.*s", LIT(ast_strings[node->kind])); break; |