ADD: bool arith core functions.
parent
05ba4cb99c
commit
b1085992c8
|
@ -1,6 +1,9 @@
|
|||
#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)
|
||||
|
@ -72,9 +75,78 @@ extern "C" void num_arith(jk::Loader& loader)
|
|||
});
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "Compiler.hpp"
|
||||
#include "lib/Opcodes.hpp"
|
||||
#include "Code.hpp"
|
||||
#include "StaticFunction.hpp"
|
||||
|
||||
namespace jk
|
||||
{
|
||||
|
@ -28,12 +29,21 @@ namespace jk
|
|||
} break;
|
||||
|
||||
case NODE_FUNCALL: {
|
||||
if (auto itr=m_statics.find(node->child(0).lock()->repr());
|
||||
itr != std::end(m_statics))
|
||||
{
|
||||
itr->second->call(node, program, sym);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i=0; i<node->size(); i++)
|
||||
{
|
||||
compile(node->child(i).lock(), program, sym);
|
||||
}
|
||||
|
||||
program->push_instr(OPCODE_CALL, node->size() - 1);
|
||||
}
|
||||
|
||||
} break;
|
||||
|
||||
case NODE_VARDECL: {
|
||||
|
@ -104,4 +114,9 @@ namespace jk
|
|||
}
|
||||
}
|
||||
|
||||
void Compiler::declare_static(std::string const& name,
|
||||
std::shared_ptr<StaticFunction> fun)
|
||||
{
|
||||
m_statics[name] = fun;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@ namespace jk
|
|||
{
|
||||
JK_ERROR(compile_error);
|
||||
|
||||
class StaticFunction;
|
||||
|
||||
class Compiler
|
||||
{
|
||||
public:
|
||||
|
@ -22,8 +24,13 @@ namespace jk
|
|||
std::shared_ptr<Program> program,
|
||||
std::shared_ptr<SymTable> sym);
|
||||
|
||||
void declare_static(std::string const& name,
|
||||
std::shared_ptr<StaticFunction> fun);
|
||||
|
||||
private:
|
||||
Logger& m_logger;
|
||||
std::unordered_map<std::string,
|
||||
std::shared_ptr<StaticFunction>> m_statics;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
#include "Loader.hpp"
|
||||
#include "lib/Function.hpp"
|
||||
#include "lib/StaticFunction.hpp"
|
||||
#include "lib/config.in.hpp"
|
||||
#include <dlfcn.h>
|
||||
|
||||
namespace jk
|
||||
{
|
||||
/*explicit*/ Loader::Loader(std::shared_ptr<VM> vm,
|
||||
std::shared_ptr<StaticPass> static_pass,
|
||||
std::shared_ptr<Compiler> compiler,
|
||||
std::shared_ptr<SymTable> sym)
|
||||
: m_vm { vm }
|
||||
, m_static_pass { static_pass }
|
||||
, m_compiler { compiler }
|
||||
, m_sym { sym }
|
||||
{
|
||||
}
|
||||
|
@ -47,4 +52,10 @@ namespace jk
|
|||
m_vm->set_global(global_addr, ref);
|
||||
}
|
||||
|
||||
void Loader::declare_static(std::string const& name, static_fun_t body)
|
||||
{
|
||||
m_static_pass->add_static(name);
|
||||
auto fun = std::make_shared<StaticFunction>(body);
|
||||
m_compiler->declare_static(name, fun);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
#include "VM.hpp"
|
||||
#include "SymTable.hpp"
|
||||
#include "Function.hpp"
|
||||
#include "StaticFunction.hpp"
|
||||
#include "Compiler.hpp"
|
||||
#include "StaticPass.hpp"
|
||||
|
||||
namespace jk
|
||||
{
|
||||
|
@ -12,14 +15,21 @@ namespace jk
|
|||
{
|
||||
public:
|
||||
explicit Loader(std::shared_ptr<VM> vm,
|
||||
std::shared_ptr<StaticPass> static_pass,
|
||||
std::shared_ptr<Compiler> compiler,
|
||||
std::shared_ptr<SymTable> sym);
|
||||
virtual ~Loader();
|
||||
|
||||
std::shared_ptr<Compiler> compiler() const { return m_compiler; }
|
||||
|
||||
void load();
|
||||
void declare(std::string const& name, foreign_t body);
|
||||
void declare_static(std::string const& name, static_fun_t body);
|
||||
|
||||
private:
|
||||
std::shared_ptr<VM> m_vm;
|
||||
std::shared_ptr<StaticPass> m_static_pass;
|
||||
std::shared_ptr<Compiler> m_compiler;
|
||||
std::shared_ptr<SymTable> m_sym;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
G(OPCODE_STORE), \
|
||||
G(OPCODE_LOAD_GLOBAL), \
|
||||
G(OPCODE_RET), \
|
||||
G(OPCODE_BRF), \
|
||||
G(OPCODE_BR), \
|
||||
G(OPCODE_NOT), \
|
||||
G(OPCODE_MK_FUNCTION)
|
||||
|
||||
namespace jk
|
||||
|
|
|
@ -22,6 +22,12 @@ namespace jk
|
|||
m_instrs.push_back(Instr { opcode, param });
|
||||
}
|
||||
|
||||
void Program::set_param(size_t index, param_t param)
|
||||
{
|
||||
assert(index < size());
|
||||
m_instrs[index].param = param;
|
||||
}
|
||||
|
||||
std::string Program::string() const
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
|
|
@ -27,6 +27,8 @@ namespace jk
|
|||
void push_instr(OpcodeType opcode,
|
||||
std::optional<param_t> param = std::nullopt);
|
||||
|
||||
void set_param(size_t index, param_t param);
|
||||
|
||||
size_t push_constant(std::shared_ptr<Value> value);
|
||||
std::shared_ptr<Value> constant(size_t index) const;
|
||||
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
#include "StaticFunction.hpp"
|
||||
|
||||
namespace jk
|
||||
{
|
||||
/*explicit*/ StaticFunction::StaticFunction(static_fun_t fun)
|
||||
: m_fun { fun }
|
||||
{
|
||||
}
|
||||
|
||||
/*virtual*/ StaticFunction::~StaticFunction()
|
||||
{
|
||||
}
|
||||
|
||||
void StaticFunction::call(std::shared_ptr<Node> node,
|
||||
std::shared_ptr<Program> program,
|
||||
std::shared_ptr<SymTable> sym)
|
||||
{
|
||||
m_fun(node, program, sym);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
#ifndef jk_STATICFUNCTION_HPP
|
||||
#define jk_STATICFUNCTION_HPP
|
||||
|
||||
#include "commons.hpp"
|
||||
#include "Program.hpp"
|
||||
#include "SymTable.hpp"
|
||||
#include "Node.hpp"
|
||||
|
||||
namespace jk
|
||||
{
|
||||
using static_fun_t =
|
||||
std::function<void
|
||||
(std::shared_ptr<Node>,
|
||||
std::shared_ptr<Program>,
|
||||
std::shared_ptr<SymTable>)>;
|
||||
|
||||
class StaticFunction
|
||||
{
|
||||
public:
|
||||
explicit StaticFunction(static_fun_t fun);
|
||||
virtual ~StaticFunction();
|
||||
|
||||
void call(std::shared_ptr<Node> node,
|
||||
std::shared_ptr<Program> program,
|
||||
std::shared_ptr<SymTable> sym);
|
||||
|
||||
private:
|
||||
static_fun_t m_fun;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -19,6 +19,7 @@ namespace jk
|
|||
{
|
||||
case NODE_PROG:
|
||||
case NODE_BODY: {
|
||||
|
||||
for (size_t i=0; i<node->size(); i++)
|
||||
{
|
||||
pass(node->child(i).lock());
|
||||
|
@ -56,7 +57,9 @@ namespace jk
|
|||
std::string ident = node->repr();
|
||||
auto entry = m_sym->find(ident);
|
||||
|
||||
if (!entry)
|
||||
if (!entry
|
||||
&& std::find(std::begin(m_statics), std::end(m_statics),
|
||||
ident) == std::end(m_statics))
|
||||
{
|
||||
m_logger.log<symbolic_error>(LOG_ERROR, node->loc(),
|
||||
std::string()
|
||||
|
@ -65,7 +68,10 @@ namespace jk
|
|||
+ "' is undefined");
|
||||
}
|
||||
|
||||
if (entry)
|
||||
{
|
||||
push(entry->type);
|
||||
}
|
||||
} break;
|
||||
|
||||
case NODE_VARDECL: {
|
||||
|
@ -77,13 +83,22 @@ namespace jk
|
|||
} break;
|
||||
|
||||
case NODE_FUNCALL: {
|
||||
auto is_static = std::find(std::begin(m_statics),
|
||||
std::end(m_statics),
|
||||
node->child(0).lock()->repr())
|
||||
!= std::end(m_statics);
|
||||
|
||||
if (!is_static)
|
||||
{
|
||||
for (size_t i=0; i<node->size(); i++)
|
||||
{
|
||||
pass(node->child(i).lock());
|
||||
pop();
|
||||
}
|
||||
// TODO find actual returned type
|
||||
}
|
||||
|
||||
push(std::make_shared<Type>(TYPE_NIL));
|
||||
|
||||
} break;
|
||||
|
||||
default:
|
||||
|
@ -93,6 +108,11 @@ namespace jk
|
|||
}
|
||||
}
|
||||
|
||||
void StaticPass::add_static(std::string const& name)
|
||||
{
|
||||
m_statics.push_back(name);
|
||||
}
|
||||
|
||||
void StaticPass::push(std::shared_ptr<Type> type)
|
||||
{
|
||||
m_types.push_back(type);
|
||||
|
|
|
@ -15,10 +15,13 @@ namespace jk
|
|||
|
||||
void pass(std::shared_ptr<Node> node);
|
||||
|
||||
void add_static(std::string const& name);
|
||||
|
||||
private:
|
||||
std::shared_ptr<SymTable> m_sym;
|
||||
Logger& m_logger;
|
||||
std::vector<std::shared_ptr<Type>> m_types;
|
||||
std::vector<std::string> m_statics;
|
||||
|
||||
void push(std::shared_ptr<Type> type);
|
||||
std::shared_ptr<Type> pop();
|
||||
|
|
25
lib/VM.cpp
25
lib/VM.cpp
|
@ -29,6 +29,31 @@ namespace jk
|
|||
|
||||
switch (instr.opcode)
|
||||
{
|
||||
case OPCODE_BRF: {
|
||||
auto value = program()->constant(pop());
|
||||
|
||||
if (!value->as_bool())
|
||||
{
|
||||
m_pc = *instr.param;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pc++;
|
||||
}
|
||||
|
||||
} break;
|
||||
|
||||
case OPCODE_BR: {
|
||||
m_pc = *instr.param;
|
||||
} break;
|
||||
|
||||
case OPCODE_NOT: {
|
||||
bool value = program()->constant(pop())->as_bool();
|
||||
push(program()->push_constant(Value::make_bool(!value)));
|
||||
|
||||
m_pc++;
|
||||
} break;
|
||||
|
||||
case OPCODE_MK_FUNCTION: {
|
||||
auto code = program()->constant(pop());
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ joko_lib = static_library(
|
|||
'lib/Type.cpp',
|
||||
'lib/Value.cpp',
|
||||
'lib/Function.cpp',
|
||||
'lib/StaticFunction.cpp',
|
||||
'lib/Code.cpp',
|
||||
'lib/SymTable.cpp',
|
||||
'lib/StaticPass.cpp',
|
||||
|
|
|
@ -85,12 +85,15 @@ int main(int argc, char** argv)
|
|||
|
||||
|
||||
auto compiler = std::make_shared<jk::Compiler>(logger);
|
||||
auto static_pass = std::make_shared<jk::StaticPass>(sym, logger);
|
||||
auto program = std::make_shared<jk::Program>();
|
||||
auto vm = std::make_shared<jk::VM>();
|
||||
auto loader = std::make_shared<jk::Loader>(vm, sym);
|
||||
|
||||
auto loader = std::make_shared<jk::Loader>(vm, static_pass,
|
||||
compiler, sym);
|
||||
loader->load();
|
||||
|
||||
auto static_pass = std::make_shared<jk::StaticPass>(sym, logger);
|
||||
|
||||
static_pass->pass(ast);
|
||||
|
||||
compiler->compile(ast, program, sym);
|
||||
|
|
Reference in New Issue