#include "Compiler.hpp" #include "lib/opcodes.hpp" namespace roza { /*explicit*/ Compiler::Compiler(StatusLog& log) : m_log { log } { } /*virtual*/ Compiler::~Compiler() { } std::shared_ptr Compiler::compile(std::shared_ptr root) { auto program = std::make_shared(); compile_node(root, program); return program; } void Compiler::compile_node(std::shared_ptr root, std::shared_ptr prog) { switch (root->type()) { case NODE_INT: { auto value = std::make_shared(std::stoi(root->repr()), root->loc()); prog->push_instr(OP_PUSH_CONST, prog->push_value(value)); } break; case NODE_BOOL: { auto value = std::make_shared(root->repr() == "true", root->loc()); prog->push_instr(OP_PUSH_CONST, prog->push_value(value)); } break; case NODE_EQ: { compile_children(root, prog); prog->push_instr(OP_EQ); } break; case NODE_NE: { compile_children(root, prog); prog->push_instr(OP_EQ); prog->push_instr(OP_NOT); } break; case NODE_LT: { compile_children(root, prog); prog->push_instr(OP_ILT); } break; case NODE_GT: { compile_children(root, prog); prog->push_instr(OP_IGT); } break; case NODE_LE: { compile_children(root, prog); prog->push_instr(OP_IGT); prog->push_instr(OP_NOT); } break; case NODE_GE: { compile_children(root, prog); prog->push_instr(OP_ILT); prog->push_instr(OP_NOT); } break; case NODE_IMP: { compile_children(root, prog); prog->push_instr(OP_IMP); } break; case NODE_AND: { compile_children(root, prog); prog->push_instr(OP_AND); } break; case NODE_OR: { compile_children(root, prog); prog->push_instr(OP_OR); } break; case NODE_NOT: { compile_children(root, prog); prog->push_instr(OP_NOT); } break; case NODE_ADD: { compile_children(root, prog); prog->push_instr(OP_IADD); } break; case NODE_SUB: { compile_children(root, prog); prog->push_instr(OP_ISUB); } break; case NODE_MUL: { compile_children(root, prog); prog->push_instr(OP_IMUL); } break; case NODE_DIV: { compile_children(root, prog); prog->push_instr(OP_IDIV); } break; case NODE_MOD: { compile_children(root, prog); prog->push_instr(OP_IMOD); } break; case NODE_POW: { compile_children(root, prog); prog->push_instr(OP_IPOW); } break; case NODE_UADD: { compile_children(root, prog); prog->push_instr(OP_IUADD); } break; case NODE_USUB: { compile_children(root, prog); prog->push_instr(OP_IUSUB); } break; case NODE_PROG: { compile_children(root, prog); } break; default: m_log.fatal(root->loc(), "cannot compile node '" + root->string() + "'."); } } void Compiler::compile_children(std::shared_ptr root, std::shared_ptr prog) { for (size_t i=0; isize(); i++) { compile_node(root->child(i), prog); } } }