2023-09-17 19:36:58 +00:00
|
|
|
#include "Compiler.hpp"
|
2023-09-18 17:08:32 +00:00
|
|
|
#include "Node.hpp"
|
|
|
|
#include "Program.hpp"
|
|
|
|
#include "NativeMacro.hpp"
|
2023-09-17 19:36:58 +00:00
|
|
|
|
|
|
|
namespace zn
|
|
|
|
{
|
2023-09-18 15:33:04 +00:00
|
|
|
/*explicit*/ Compiler::Compiler(Logger& logger, SymTable& sym)
|
2023-09-17 19:36:58 +00:00
|
|
|
: m_logger { logger }
|
2023-09-18 15:33:04 +00:00
|
|
|
, m_sym { sym }
|
2023-09-17 19:36:58 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/*virtual*/ Compiler::~Compiler()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2023-09-18 17:08:32 +00:00
|
|
|
void Compiler::add_macro(std::shared_ptr<NativeMacro> macro)
|
|
|
|
{
|
|
|
|
m_macros.push_back(macro);
|
|
|
|
}
|
|
|
|
|
2023-09-17 19:36:58 +00:00
|
|
|
void Compiler::compile(Node const& node, Program& program)
|
|
|
|
{
|
|
|
|
switch (node.type())
|
|
|
|
{
|
2023-09-18 15:33:04 +00:00
|
|
|
// MODULES
|
|
|
|
// =======
|
2023-09-17 19:36:58 +00:00
|
|
|
case NODE_MODULE: {
|
|
|
|
for (size_t i=0; i<node.size(); i++)
|
|
|
|
{
|
|
|
|
compile(*node.child_at(i), program);
|
|
|
|
program.append(OPCODE_POP);
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
2023-09-18 15:33:04 +00:00
|
|
|
// FUNCTION STUFF
|
|
|
|
// ==============
|
|
|
|
case NODE_CALL: {
|
2023-09-18 17:08:32 +00:00
|
|
|
std::string ident = node.child_at(0)->repr();
|
|
|
|
auto sym = m_sym.find(ident);
|
|
|
|
|
|
|
|
if (sym)
|
2023-09-18 15:33:04 +00:00
|
|
|
{
|
2023-09-18 17:08:32 +00:00
|
|
|
for (size_t i=0; i<node.size(); i++)
|
|
|
|
{
|
|
|
|
compile(*node.child_at(i), program);
|
|
|
|
}
|
|
|
|
|
|
|
|
program.append(OPCODE_CALL_NATIVE, node.size() - 1);
|
2023-09-18 15:33:04 +00:00
|
|
|
}
|
2023-09-18 17:08:32 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
bool found_macro = false;
|
|
|
|
|
|
|
|
for (auto macro: m_macros)
|
|
|
|
{
|
|
|
|
if (macro->name() == ident)
|
|
|
|
{
|
|
|
|
auto res = macro->execute(node, *this,
|
|
|
|
program, m_sym);
|
|
|
|
size_t addr = program.add_constant(res);
|
|
|
|
program.append(OPCODE_LOAD_CONST, addr);
|
|
|
|
found_macro = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2023-09-18 15:33:04 +00:00
|
|
|
|
2023-09-18 17:08:32 +00:00
|
|
|
if (!found_macro)
|
|
|
|
{
|
|
|
|
std::stringstream ss;
|
|
|
|
ss << "cannot call undefined function '"
|
|
|
|
<< ident
|
|
|
|
<< "'";
|
|
|
|
|
|
|
|
m_logger.log<compile_error>(LOG_ERROR,
|
|
|
|
node.loc(),
|
|
|
|
ss.str());
|
|
|
|
}
|
|
|
|
}
|
2023-09-18 15:33:04 +00:00
|
|
|
} break;
|
|
|
|
|
|
|
|
// VALUES
|
|
|
|
// ======
|
|
|
|
case NODE_IDENT: {
|
|
|
|
std::string ident = node.repr();
|
|
|
|
auto sym = m_sym.find(ident);
|
2023-09-18 17:08:32 +00:00
|
|
|
|
|
|
|
if (!sym)
|
|
|
|
{
|
|
|
|
std::stringstream ss;
|
|
|
|
ss << "cannot use undefined variable '"
|
|
|
|
<< ident
|
|
|
|
<< "'";
|
|
|
|
|
|
|
|
m_logger.log<compile_error>(LOG_ERROR,
|
|
|
|
node.loc(),
|
|
|
|
ss.str());
|
|
|
|
}
|
2023-09-18 15:33:04 +00:00
|
|
|
|
|
|
|
if (sym->prototype)
|
|
|
|
{
|
|
|
|
auto ref = std::make_shared<Constant>(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;
|
|
|
|
|
2023-09-17 19:36:58 +00:00
|
|
|
case NODE_INT: {
|
|
|
|
size_t addr = program
|
|
|
|
.add_constant(std::make_shared<Constant>
|
2023-09-18 15:33:04 +00:00
|
|
|
(TYPE_INT, node.loc(),
|
|
|
|
std::stoi(node.repr())));
|
2023-09-17 19:36:58 +00:00
|
|
|
program.append(OPCODE_LOAD_CONST, addr);
|
|
|
|
} break;
|
|
|
|
|
|
|
|
default: {
|
|
|
|
std::cerr << "cannot compile node '"
|
|
|
|
<< node.string() << "'" << std::endl;
|
|
|
|
abort();
|
|
|
|
} break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|