+13
-1
@@ -186,6 +186,18 @@ bool compound_statement_node::equal(const node& rhs) const {
|
||||
return statement_node::equal(rhs) && m_body == dynamic_cast<const compound_statement_node&>(rhs).m_body;
|
||||
}
|
||||
|
||||
void while_statement_node::accept(visitor& visitor) const {
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
std::ostream& while_statement_node::print(std::ostream& os) const {
|
||||
return os << m_body;
|
||||
}
|
||||
|
||||
bool while_statement_node::equal(const node& rhs) const {
|
||||
return statement_node::equal(rhs) && m_body == dynamic_cast<const while_statement_node&>(rhs).m_body;
|
||||
}
|
||||
|
||||
void program_node::accept(visitor& visitor) const {
|
||||
for (const auto& decl : m_declarations) {
|
||||
decl->accept(visitor);
|
||||
@@ -212,4 +224,4 @@ std::ostream& operator<<(std::ostream& os, const body& body) {
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace furc::ast
|
||||
} // namespace furc::ast
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "furc/front/lexer.hpp"
|
||||
|
||||
#include "furc/front/token.hpp"
|
||||
|
||||
#include <cctype>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
@@ -97,6 +99,7 @@ token_r lexer::next_token() {
|
||||
{ "return", keyword_token::Return },
|
||||
{ "if", keyword_token::If },
|
||||
{ "else", keyword_token::Else },
|
||||
{ "while", keyword_token::While },
|
||||
};
|
||||
|
||||
if (auto it = s_keywords.find(value); it != s_keywords.end()) return { location, it->second };
|
||||
@@ -185,4 +188,4 @@ location lexer::current_location() {
|
||||
return { m_filename, m_row, m_cursor - m_lineStart };
|
||||
}
|
||||
|
||||
} // namespace furc::front
|
||||
} // namespace furc::front
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
|
||||
#include "furc/ast/declaration.hpp" // IWYU pragma: keep
|
||||
#include "furc/ast/expression.hpp" // IWYU pragma: keep
|
||||
#include "furc/ast/literal.hpp" // IWYU pragma: keep
|
||||
#include "furc/ast/program.hpp" // IWYU pragma: keep
|
||||
#include "furc/ast/statement.hpp" // IWYU pragma: keep
|
||||
#include "furc/ast/fwd.hpp"
|
||||
#include "furc/ast/literal.hpp" // IWYU pragma: keep
|
||||
#include "furc/ast/program.hpp" // IWYU pragma: keep
|
||||
#include "furc/ast/statement.hpp" // IWYU pragma: keep
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
@@ -145,6 +146,24 @@ ast::statement_node_r parser::parse_statement() {
|
||||
std::move(cond.value()),
|
||||
std::move(then.value()));
|
||||
}
|
||||
case keyword_token::While: {
|
||||
auto tok = next_token();
|
||||
auto err = eat_token(token_t::LParen);
|
||||
if (err.has_error()) return ast::statement_node_r(ast::error{ err.error().location });
|
||||
|
||||
auto cond = parse_expression();
|
||||
if (cond.has_error()) return ast::statement_node_r(ast::error{ cond.error().location });
|
||||
|
||||
err = eat_token(token_t::RParen);
|
||||
if (err.has_error()) return ast::statement_node_r(ast::error{ err.error().location });
|
||||
|
||||
auto body = parse_statement();
|
||||
if (body.has_error()) return ast::statement_node_r(ast::error{ body.error().location });
|
||||
|
||||
return m_arena.allocate_shared<ast::while_statement_node>(location,
|
||||
std::move(cond.value()),
|
||||
std::move(body.value()));
|
||||
}
|
||||
case keyword_token::None:
|
||||
case keyword_token::Func:
|
||||
default: break;
|
||||
@@ -438,4 +457,4 @@ token_r parser::eat_token(token_t type) {
|
||||
return token;
|
||||
}
|
||||
|
||||
} // namespace furc::front
|
||||
} // namespace furc::front
|
||||
|
||||
+5
-9
@@ -11,16 +11,12 @@ int main(void) {
|
||||
try {
|
||||
std::string programStr = R"(
|
||||
func main() {
|
||||
x = 5;
|
||||
x -= 3;
|
||||
if (x < 3) {
|
||||
y = x * 2;
|
||||
w = y;
|
||||
} else {
|
||||
y = x - 3;
|
||||
x = 0;
|
||||
y = 10;
|
||||
z = 1;
|
||||
while (x < y) {
|
||||
x = x + z;
|
||||
}
|
||||
w = x - y;
|
||||
z = x + y;
|
||||
}
|
||||
)";
|
||||
furc::front::parser parser("<TEMP>", programStr);
|
||||
|
||||
Reference in New Issue
Block a user