#include "Compiler.hpp" #include "Node.hpp" #include "Program.hpp" #include "NativeMacro.hpp" namespace zn { /*explicit*/ Compiler::Compiler(Logger& logger, SymTable& sym) : m_logger { logger } , m_sym { sym } { } /*virtual*/ Compiler::~Compiler() { } void Compiler::add_macro(std::shared_ptr macro) { m_macros.push_back(macro); } void Compiler::compile(Node const& node, Program& program) { switch (node.type()) { // MODULES // ======= case NODE_MODULE: { for (size_t i=0; irepr(); auto sym = m_sym.find(ident); if (sym) { for (size_t i=0; iname() == ident) { macro->execute(node, *this, program, m_sym); found_macro = true; break; } } if (!found_macro) { std::stringstream ss; ss << "cannot call undefined function '" << ident << "'"; m_logger.log(LOG_ERROR, node.loc(), ss.str()); } } } break; // VALUES // ====== case NODE_IDENT: { std::string ident = node.repr(); auto sym = m_sym.find(ident); if (!sym) { std::stringstream ss; ss << "cannot use undefined variable '" << ident << "'"; m_logger.log(LOG_ERROR, node.loc(), ss.str()); } if (sym->prototype) { auto ref = std::make_shared(TYPE_REF, node.loc(), (int) sym->addr); size_t val = program.add_constant(ref); program.append(OPCODE_LOAD_CONST, val); } else { program.append(OPCODE_LOAD_LOCAL, sym->addr); } } break; case NODE_INT: { size_t addr = program .add_constant(std::make_shared (TYPE_INT, node.loc(), std::stoi(node.repr()))); program.append(OPCODE_LOAD_CONST, addr); } break; default: { std::cerr << "cannot compile node '" << node.string() << "'" << std::endl; abort(); } break; } } }