2023-09-20 11:31:35 +00:00
|
|
|
#include "Compiler.hpp"
|
|
|
|
|
|
|
|
namespace fk
|
|
|
|
{
|
2023-09-20 15:17:13 +00:00
|
|
|
/*explicit*/ Compiler::Compiler(std::shared_ptr<SymTable> sym)
|
|
|
|
: m_sym { sym }
|
2023-09-20 11:31:35 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/*virtual*/ Compiler::~Compiler()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2023-09-20 19:21:51 +00:00
|
|
|
void Compiler::add_macro(std::string const& name,
|
|
|
|
std::shared_ptr<NativeMacro> macro)
|
|
|
|
{
|
|
|
|
m_macros[name] = macro;
|
|
|
|
}
|
|
|
|
|
2023-09-20 11:31:35 +00:00
|
|
|
std::shared_ptr<Program> Compiler::compile(std::shared_ptr<Node> node)
|
|
|
|
{
|
|
|
|
auto prog = std::make_shared<Program>();
|
2023-09-20 15:17:13 +00:00
|
|
|
compile_prog(node, prog);
|
2023-09-20 11:31:35 +00:00
|
|
|
return prog;
|
|
|
|
}
|
|
|
|
|
2023-09-20 15:17:13 +00:00
|
|
|
void Compiler::compile_prog(std::shared_ptr<Node> node,
|
|
|
|
std::shared_ptr<Program> prog)
|
2023-09-20 11:31:35 +00:00
|
|
|
{
|
|
|
|
switch (node->type())
|
|
|
|
{
|
|
|
|
case NODE_MODULE: {
|
|
|
|
for (size_t i=0; i<node->size(); i++)
|
|
|
|
{
|
2023-09-20 15:17:13 +00:00
|
|
|
compile_prog(node->child(i), prog);
|
2023-09-20 11:31:35 +00:00
|
|
|
prog->add(OP_POP);
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
2023-09-20 15:17:13 +00:00
|
|
|
case NODE_CALL: {
|
|
|
|
std::string ident = node->child(0)->repr();
|
2023-09-20 19:21:51 +00:00
|
|
|
|
|
|
|
if (auto itr=m_macros.find(ident);
|
|
|
|
itr != std::end(m_macros))
|
2023-09-20 15:17:13 +00:00
|
|
|
{
|
2023-09-20 19:21:51 +00:00
|
|
|
auto macro = itr->second;
|
|
|
|
macro->call(*this, node, prog);
|
2023-09-20 15:17:13 +00:00
|
|
|
}
|
2023-09-20 19:21:51 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
for (size_t i=0; i<node->size(); i++)
|
|
|
|
{
|
|
|
|
compile_prog(node->child(i), prog);
|
|
|
|
}
|
2023-09-20 15:17:13 +00:00
|
|
|
|
2023-09-20 19:21:51 +00:00
|
|
|
prog->add(OP_CALL_NATIVE, node->size() - 1);
|
|
|
|
}
|
2023-09-20 15:17:13 +00:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case NODE_IDENT: {
|
|
|
|
auto entry = m_sym->find(node->repr());
|
|
|
|
|
|
|
|
if (!entry)
|
|
|
|
{
|
|
|
|
std::stringstream ss;
|
|
|
|
ss << "'"
|
|
|
|
<< node->repr()
|
|
|
|
<< "' is undefined";
|
|
|
|
|
|
|
|
node->loc().error<compile_error>(LOG_ERROR, ss.str());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!entry->is_global())
|
|
|
|
{
|
2023-09-21 13:59:46 +00:00
|
|
|
prog->add(OP_LOAD_LOCAL, entry->addr());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
prog->add(OP_LOAD_GLOBAL, entry->addr());
|
2023-09-20 15:17:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
} break;
|
|
|
|
|
2023-09-20 11:31:35 +00:00
|
|
|
case NODE_INT: {
|
|
|
|
prog->load_const(std::make_shared<Constant>(TYPE_INT,
|
|
|
|
stoi(node->repr()),
|
|
|
|
node->loc()));
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case NODE_FLOAT: {
|
|
|
|
prog->load_const(std::make_shared<Constant>(TYPE_FLOAT,
|
|
|
|
stof(node->repr()),
|
|
|
|
node->loc()));
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case NODE_BOOL: {
|
|
|
|
prog->load_const(std::make_shared<Constant>(TYPE_BOOL,
|
|
|
|
node->repr() == "true",
|
|
|
|
node->loc()));
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case NODE_STRING: {
|
|
|
|
std::string str = node->repr();
|
|
|
|
prog->load_const(std::make_shared<Constant>(TYPE_STRING,
|
|
|
|
str.substr(1, str.size() - 2),
|
|
|
|
node->loc()));
|
|
|
|
} break;
|
|
|
|
|
|
|
|
default: {
|
|
|
|
std::stringstream ss;
|
|
|
|
ss << "cannot compile expression '"
|
|
|
|
<< (NodeTypeStr[node->type()] + strlen("NODE_"))
|
|
|
|
<< "'";
|
|
|
|
|
|
|
|
node->loc().error<compile_error>(LOG_ERROR, ss.str());
|
|
|
|
} break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|