feat(furc): introduce while loop statement

Refs: #2
This commit is contained in:
2026-06-12 23:10:26 +02:00
parent 97c01bc96c
commit 767970c69b
11 changed files with 151 additions and 24 deletions
+32 -3
View File
@@ -4,8 +4,10 @@
#include "furc/ast/expression.hpp" // IWYU pragma: keep
#include "furc/ast/literal.hpp" // IWYU pragma: keep
#include "furc/ast/statement.hpp" // IWYU pragma: keep
#include "furlang/ir/instruction.hpp"
#include <cassert>
#include <memory>
namespace furc::front {
@@ -55,6 +57,33 @@ void ir_generator::visit(const ast::if_statement_node& node) {
push_block(); // merge block
}
void ir_generator::visit(const ast::while_statement_node& node) {
node.condition()->accept(*this);
ir_register cond = m_registerCounter - 1;
std::shared_ptr<ir::block> entry = m_currentBlock;
ir::block_index headerIdx = m_currentFunction->blocks().size();
push_block(false); // loop header
push<ir::branch_instruction>(m_currentFunction->blocks().size());
push_block(); // loop condition
node.condition()->accept(*this);
std::shared_ptr<ir::block> condBlock = m_currentBlock;
ir_register cond2 = m_registerCounter - 1;
push_block(false); // loop body
node.body()->accept(*this);
push<ir::branch_instruction>(headerIdx);
entry->emplace<ir::branch_cond_instruction>(ir::operand::new_reg(cond),
headerIdx,
m_currentFunction->blocks().size());
condBlock->emplace<ir::branch_cond_instruction>(ir::operand::new_reg(cond2),
m_currentFunction->blocks().size() - 1,
m_currentFunction->blocks().size());
push_block(); // merge block
}
void ir_generator::visit(const ast::compound_statement_node& node) {
for (const auto& stmt : node.body().statements) {
stmt.value()->accept(*this);
@@ -138,8 +167,8 @@ void ir_generator::visit(const ast::var_assign_expression_node& node) {
}
}
furlang::ir::block_index ir_generator::push_block() {
if (!m_currentFunction->blocks().empty() && !m_currentFunction->blocks().back()->has_exit()) {
furlang::ir::block_index ir_generator::push_block(bool validate) {
if (validate && !m_currentFunction->blocks().empty() && !m_currentFunction->blocks().back()->has_exit()) {
throw std::runtime_error(
"block " + std::to_string(m_currentFunction->blocks().size() - 1) + " is lacking an exit");
}
@@ -148,4 +177,4 @@ furlang::ir::block_index ir_generator::push_block() {
return index;
}
} // namespace furc::front
} // namespace furc::front