81 lines
1.9 KiB
C++
81 lines
1.9 KiB
C++
|
#include "Compiler.hpp"
|
||
|
#include "lib/Opcodes.hpp"
|
||
|
#include "Code.hpp"
|
||
|
|
||
|
namespace jk
|
||
|
{
|
||
|
/*explicit*/ Compiler::Compiler(std::shared_ptr<SymTable> sym,
|
||
|
Logger& logger)
|
||
|
: m_sym { sym }
|
||
|
, m_logger(logger)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
/*virtual*/ Compiler::~Compiler()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void Compiler::compile(std::shared_ptr<Node> node,
|
||
|
std::shared_ptr<Program> program)
|
||
|
{
|
||
|
switch (node->type())
|
||
|
{
|
||
|
case NODE_PROG: {
|
||
|
for (size_t i=0; i<node->size(); i++)
|
||
|
{
|
||
|
compile(node->child(i).lock(), program);
|
||
|
}
|
||
|
} break;
|
||
|
|
||
|
case NODE_FUNCALL: {
|
||
|
for (size_t i=0; i<node->size(); i++)
|
||
|
{
|
||
|
compile(node->child(i).lock(), program);
|
||
|
}
|
||
|
|
||
|
program->push_instr(OPCODE_CALL, node->size() - 1);
|
||
|
} break;
|
||
|
|
||
|
case NODE_IDENT: {
|
||
|
std::string ident = node->repr();
|
||
|
auto sym = m_sym->find(ident);
|
||
|
|
||
|
if (!sym)
|
||
|
{
|
||
|
m_logger.log<compile_error>(LOG_ERROR, node->loc(),
|
||
|
std::string()
|
||
|
+ "'"
|
||
|
+ ident
|
||
|
+ "' is undefined");
|
||
|
}
|
||
|
|
||
|
OpcodeType op_load = OPCODE_LOAD;
|
||
|
|
||
|
if (sym->is_global)
|
||
|
{
|
||
|
op_load = OPCODE_LOAD_GLOBAL;
|
||
|
}
|
||
|
|
||
|
if (sym->type->type() == TYPE_FUNCTION)
|
||
|
{
|
||
|
program->push_instr(op_load, sym->addr);
|
||
|
}
|
||
|
|
||
|
} break;
|
||
|
|
||
|
case NODE_INT: {
|
||
|
auto value = Value::make_int(std::stoi(node->repr()));
|
||
|
size_t addr = program->push_constant(value);
|
||
|
program->push_instr(OPCODE_PUSH_CONST, addr);
|
||
|
} break;
|
||
|
|
||
|
default:
|
||
|
std::cerr << "cannot compile unknown node '"
|
||
|
<< NodeTypeStr[node->type()] << "'" << std::endl;
|
||
|
abort();
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|