This repository has been archived on 2023-09-10. You can view files and clone it, but cannot push or open issues/pull-requests.
joko/core/core.cpp

167 lines
3.8 KiB
C++

#include <cmath>
#include "lib/Function.hpp"
#include "lib/Loader.hpp"
#include "lib/Node.hpp"
#include "lib/Opcodes.hpp"
#include "lib/SymTable.hpp"
#include "lib/Value.hpp"
extern "C" void num_arith(jk::Loader& loader)
{
loader.declare("+", [](auto args){
int res = 0;
for (auto arg: args)
{
res += arg->as_int();
}
return jk::Value::make_int(res);
});
loader.declare("-", [](auto args){
int res = args[0]->as_int();
for (size_t i=1; i<args.size(); i++)
{
res -= args[i]->as_int();
}
return jk::Value::make_int(res);
});
loader.declare("*", [](auto args){
int res = 1;
for (auto arg: args)
{
res *= arg->as_int();
}
return jk::Value::make_int(res);
});
loader.declare("/", [](auto args){
int res = args[0]->as_int();
for (size_t i=1; i<args.size(); i++)
{
res /= args[i]->as_int();
}
return jk::Value::make_int(res);
});
loader.declare("^", [](auto args){
int res = args[0]->as_int();
for (size_t i=1; i<args.size(); i++)
{
res = std::pow(res, args[i]->as_int());
}
return jk::Value::make_int(res);
});
loader.declare("%", [](auto args){
int res = args[0]->as_int();
for (size_t i=1; i<args.size(); i++)
{
res %= args[i]->as_int();
}
return jk::Value::make_int(res);
});
}
extern "C" void bool_arith(jk::Loader& loader)
{
loader.declare_static("and", [loader](std::shared_ptr<jk::Node> node,
std::shared_ptr<jk::Program> program,
std::shared_ptr<jk::SymTable> sym) {
std::vector<size_t> to_false;
for (size_t i=1; i<node->size(); i++)
{
loader.compiler()->compile(node->child(i).lock(), program, sym);
to_false.push_back(program->size());
program->push_instr(jk::OPCODE_BRF, 0);
}
program->push_instr(jk::OPCODE_PUSH_CONST,
program->push_constant(jk::Value::make_bool(true)));
size_t end = program->size();
program->push_instr(jk::OPCODE_BR, 0);
for (auto addr: to_false)
{
program->set_param(addr, program->size());
}
program->push_instr(jk::OPCODE_PUSH_CONST,
program->push_constant(jk::Value::make_bool(false)));
program->set_param(end, program->size());
});
loader.declare_static("or", [loader](std::shared_ptr<jk::Node> node,
std::shared_ptr<jk::Program> program,
std::shared_ptr<jk::SymTable> sym) {
std::vector<size_t> to_false;
for (size_t i=1; i<node->size(); i++)
{
loader.compiler()->compile(node->child(i).lock(), program, sym);
program->push_instr(jk::OPCODE_NOT);
to_false.push_back(program->size());
program->push_instr(jk::OPCODE_BRF, 0);
}
program->push_instr(jk::OPCODE_PUSH_CONST,
program->push_constant(jk::Value::make_bool(false)));
size_t end = program->size();
program->push_instr(jk::OPCODE_BR, 0);
for (auto addr: to_false)
{
program->set_param(addr, program->size());
}
program->push_instr(jk::OPCODE_PUSH_CONST,
program->push_constant(jk::Value::make_bool(true)));
program->set_param(end, program->size());
});
loader.declare("not", [](auto args){
auto value = args[0]->as_bool();
return jk::Value::make_bool(!value);
});
}
extern "C" void lib(jk::Loader& loader)
{
num_arith(loader);
bool_arith(loader);
loader.declare("dump", [](auto args){
std::string sep;
for (auto arg: args)
{
std::cout << sep << arg->string();
sep = " ";
}
if (args.empty() == false)
{
std::cout << std::endl;
}
return jk::Value::make_nil();
});
}