Compare commits
No commits in common. "b1085992c829c9e540ce2b1151450547b35f9f60" and "03cc9b58e229691b995ba54295abdc5d1e34b5bf" have entirely different histories.
b1085992c8
...
03cc9b58e2
144
core/core.cpp
144
core/core.cpp
|
@ -1,152 +1,8 @@
|
||||||
#include <cmath>
|
|
||||||
#include "lib/Function.hpp"
|
#include "lib/Function.hpp"
|
||||||
#include "lib/Loader.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)
|
extern "C" void lib(jk::Loader& loader)
|
||||||
{
|
{
|
||||||
num_arith(loader);
|
|
||||||
bool_arith(loader);
|
|
||||||
|
|
||||||
loader.declare("dump", [](auto args){
|
loader.declare("dump", [](auto args){
|
||||||
std::string sep;
|
std::string sep;
|
||||||
|
|
||||||
|
|
|
@ -11,4 +11,4 @@ BODY ::= expr*
|
||||||
VARDECL ::= opar decl ident EXPR cpar
|
VARDECL ::= opar decl ident EXPR cpar
|
||||||
FUNDECL ::= opar decl opar ident PARAMS cpar EXPR cpar
|
FUNDECL ::= opar decl opar ident PARAMS cpar EXPR cpar
|
||||||
FUNCALL ::= opar ident EXPR* cpar
|
FUNCALL ::= opar ident EXPR* cpar
|
||||||
LITERAL ::= bool | int | ident
|
LITERAL ::= int | ident
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#include "Compiler.hpp"
|
#include "Compiler.hpp"
|
||||||
#include "lib/Opcodes.hpp"
|
#include "lib/Opcodes.hpp"
|
||||||
#include "Code.hpp"
|
#include "Code.hpp"
|
||||||
#include "StaticFunction.hpp"
|
|
||||||
|
|
||||||
namespace jk
|
namespace jk
|
||||||
{
|
{
|
||||||
|
@ -29,21 +28,12 @@ namespace jk
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NODE_FUNCALL: {
|
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++)
|
for (size_t i=0; i<node->size(); i++)
|
||||||
{
|
{
|
||||||
compile(node->child(i).lock(), program, sym);
|
compile(node->child(i).lock(), program, sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
program->push_instr(OPCODE_CALL, node->size() - 1);
|
program->push_instr(OPCODE_CALL, node->size() - 1);
|
||||||
}
|
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NODE_VARDECL: {
|
case NODE_VARDECL: {
|
||||||
|
@ -76,6 +66,7 @@ namespace jk
|
||||||
size_t addr = program->push_constant(Value::make_code(code));
|
size_t addr = program->push_constant(Value::make_code(code));
|
||||||
program->push_instr(OPCODE_PUSH_CONST, addr);
|
program->push_instr(OPCODE_PUSH_CONST, addr);
|
||||||
program->push_instr(OPCODE_MK_FUNCTION);
|
program->push_instr(OPCODE_MK_FUNCTION);
|
||||||
|
//program->push_instr(OpcodeType opcode)
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NODE_IDENT: {
|
case NODE_IDENT: {
|
||||||
|
@ -100,12 +91,6 @@ namespace jk
|
||||||
program->push_instr(OPCODE_PUSH_CONST, addr);
|
program->push_instr(OPCODE_PUSH_CONST, addr);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NODE_BOOL: {
|
|
||||||
auto value = Value::make_bool(node->repr() == "true");
|
|
||||||
size_t addr = program->push_constant(value);
|
|
||||||
program->push_instr(OPCODE_PUSH_CONST, addr);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
std::cerr << "cannot compile unknown node '"
|
std::cerr << "cannot compile unknown node '"
|
||||||
<< NodeTypeStr[node->type()] << "'" << std::endl;
|
<< NodeTypeStr[node->type()] << "'" << std::endl;
|
||||||
|
@ -114,9 +99,4 @@ namespace jk
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Compiler::declare_static(std::string const& name,
|
|
||||||
std::shared_ptr<StaticFunction> fun)
|
|
||||||
{
|
|
||||||
m_statics[name] = fun;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,6 @@ namespace jk
|
||||||
{
|
{
|
||||||
JK_ERROR(compile_error);
|
JK_ERROR(compile_error);
|
||||||
|
|
||||||
class StaticFunction;
|
|
||||||
|
|
||||||
class Compiler
|
class Compiler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -24,13 +22,8 @@ namespace jk
|
||||||
std::shared_ptr<Program> program,
|
std::shared_ptr<Program> program,
|
||||||
std::shared_ptr<SymTable> sym);
|
std::shared_ptr<SymTable> sym);
|
||||||
|
|
||||||
void declare_static(std::string const& name,
|
|
||||||
std::shared_ptr<StaticFunction> fun);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Logger& m_logger;
|
Logger& m_logger;
|
||||||
std::unordered_map<std::string,
|
|
||||||
std::shared_ptr<StaticFunction>> m_statics;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,11 +6,6 @@ namespace jk
|
||||||
: m_logger { logger }
|
: m_logger { logger }
|
||||||
, m_loc { loc }
|
, m_loc { loc }
|
||||||
{
|
{
|
||||||
std::vector<std::tuple<NodeType, std::string, bool>> keywords = {
|
|
||||||
{NODE_BOOL, "true", true},
|
|
||||||
{NODE_BOOL, "false", true},
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<std::tuple<NodeType, std::string, bool>> texts = {
|
std::vector<std::tuple<NodeType, std::string, bool>> texts = {
|
||||||
{NODE_RARROW, "->", false},
|
{NODE_RARROW, "->", false},
|
||||||
{NODE_DECL, "$", false},
|
{NODE_DECL, "$", false},
|
||||||
|
@ -20,7 +15,6 @@ namespace jk
|
||||||
|
|
||||||
for (auto text: texts)
|
for (auto text: texts)
|
||||||
{
|
{
|
||||||
m_texts.push_back(std::get<1>(text));
|
|
||||||
m_scanners.push_back(std::bind(&Lexer::scan_text,
|
m_scanners.push_back(std::bind(&Lexer::scan_text,
|
||||||
this,
|
this,
|
||||||
std::get<0>(text),
|
std::get<0>(text),
|
||||||
|
@ -28,15 +22,6 @@ namespace jk
|
||||||
std::get<2>(text)));
|
std::get<2>(text)));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto kw: keywords)
|
|
||||||
{
|
|
||||||
m_scanners.push_back(std::bind(&Lexer::scan_keyword,
|
|
||||||
this,
|
|
||||||
std::get<0>(kw),
|
|
||||||
std::get<1>(kw),
|
|
||||||
std::get<2>(kw)));
|
|
||||||
}
|
|
||||||
|
|
||||||
m_scanners.push_back(std::bind(&Lexer::scan_ident, this));
|
m_scanners.push_back(std::bind(&Lexer::scan_ident, this));
|
||||||
m_scanners.push_back(std::bind(&Lexer::scan_int, this));
|
m_scanners.push_back(std::bind(&Lexer::scan_int, this));
|
||||||
}
|
}
|
||||||
|
@ -118,24 +103,6 @@ namespace jk
|
||||||
return m_source[index];
|
return m_source[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Lexer::is_sep(size_t index) const
|
|
||||||
{
|
|
||||||
if (std::isspace(at(index)))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto txt: m_texts)
|
|
||||||
{
|
|
||||||
if (txt == std::string(1, at(index)))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Lexer::skip_spaces()
|
void Lexer::skip_spaces()
|
||||||
{
|
{
|
||||||
while (more(m_cursor)
|
while (more(m_cursor)
|
||||||
|
@ -202,46 +169,12 @@ namespace jk
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<ScanInfo> Lexer::scan_keyword(NodeType type,
|
|
||||||
std::string const& text,
|
|
||||||
bool has_value) const
|
|
||||||
{
|
|
||||||
if (m_cursor + text.size() > m_source.size())
|
|
||||||
{
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i=0; i<text.size(); i++)
|
|
||||||
{
|
|
||||||
if (at(m_cursor + i) != text[i])
|
|
||||||
{
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_cursor + text.size() < m_source.size()
|
|
||||||
&& !is_sep(m_cursor + text.size()))
|
|
||||||
{
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ScanInfo {
|
|
||||||
m_cursor + text.size(),
|
|
||||||
type,
|
|
||||||
has_value ? text : ""
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<ScanInfo> Lexer::scan_ident() const
|
std::optional<ScanInfo> Lexer::scan_ident() const
|
||||||
{
|
{
|
||||||
auto car = [](char c){
|
auto car = [](char c){
|
||||||
return std::isalpha(c)
|
return std::isalpha(c)
|
||||||
|| c == '_'
|
|| c == '_'
|
||||||
|| c == '-'
|
|| c == '-'
|
||||||
|| c == '+'
|
|
||||||
|| c == '*'
|
|
||||||
|| c == '^'
|
|
||||||
|| c == '%'
|
|
||||||
|| c == '?'
|
|| c == '?'
|
||||||
|| c == '!'
|
|| c == '!'
|
||||||
|| c == '/';
|
|| c == '/';
|
||||||
|
|
|
@ -34,11 +34,9 @@ namespace jk
|
||||||
size_t m_cursor;
|
size_t m_cursor;
|
||||||
std::string m_source;
|
std::string m_source;
|
||||||
std::vector<scanner_t> m_scanners;
|
std::vector<scanner_t> m_scanners;
|
||||||
std::vector<std::string> m_texts;
|
|
||||||
|
|
||||||
bool more(size_t index) const;
|
bool more(size_t index) const;
|
||||||
char at(size_t index) const;
|
char at(size_t index) const;
|
||||||
bool is_sep(size_t index) const;
|
|
||||||
|
|
||||||
void skip_spaces();
|
void skip_spaces();
|
||||||
|
|
||||||
|
@ -46,11 +44,6 @@ namespace jk
|
||||||
std::optional<ScanInfo> scan_text(NodeType type,
|
std::optional<ScanInfo> scan_text(NodeType type,
|
||||||
std::string const& text,
|
std::string const& text,
|
||||||
bool has_value) const;
|
bool has_value) const;
|
||||||
|
|
||||||
std::optional<ScanInfo> scan_keyword(NodeType type,
|
|
||||||
std::string const& text,
|
|
||||||
bool has_value) const;
|
|
||||||
|
|
||||||
std::optional<ScanInfo> scan_ident() const;
|
std::optional<ScanInfo> scan_ident() const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,13 @@
|
||||||
#include "Loader.hpp"
|
#include "Loader.hpp"
|
||||||
#include "lib/Function.hpp"
|
#include "lib/Function.hpp"
|
||||||
#include "lib/StaticFunction.hpp"
|
|
||||||
#include "lib/config.in.hpp"
|
#include "lib/config.in.hpp"
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
|
||||||
namespace jk
|
namespace jk
|
||||||
{
|
{
|
||||||
/*explicit*/ Loader::Loader(std::shared_ptr<VM> vm,
|
/*explicit*/ Loader::Loader(std::shared_ptr<VM> vm,
|
||||||
std::shared_ptr<StaticPass> static_pass,
|
|
||||||
std::shared_ptr<Compiler> compiler,
|
|
||||||
std::shared_ptr<SymTable> sym)
|
std::shared_ptr<SymTable> sym)
|
||||||
: m_vm { vm }
|
: m_vm { vm }
|
||||||
, m_static_pass { static_pass }
|
|
||||||
, m_compiler { compiler }
|
|
||||||
, m_sym { sym }
|
, m_sym { sym }
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -52,10 +47,4 @@ namespace jk
|
||||||
m_vm->set_global(global_addr, ref);
|
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,9 +5,6 @@
|
||||||
#include "VM.hpp"
|
#include "VM.hpp"
|
||||||
#include "SymTable.hpp"
|
#include "SymTable.hpp"
|
||||||
#include "Function.hpp"
|
#include "Function.hpp"
|
||||||
#include "StaticFunction.hpp"
|
|
||||||
#include "Compiler.hpp"
|
|
||||||
#include "StaticPass.hpp"
|
|
||||||
|
|
||||||
namespace jk
|
namespace jk
|
||||||
{
|
{
|
||||||
|
@ -15,21 +12,14 @@ namespace jk
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Loader(std::shared_ptr<VM> vm,
|
explicit Loader(std::shared_ptr<VM> vm,
|
||||||
std::shared_ptr<StaticPass> static_pass,
|
|
||||||
std::shared_ptr<Compiler> compiler,
|
|
||||||
std::shared_ptr<SymTable> sym);
|
std::shared_ptr<SymTable> sym);
|
||||||
virtual ~Loader();
|
virtual ~Loader();
|
||||||
|
|
||||||
std::shared_ptr<Compiler> compiler() const { return m_compiler; }
|
|
||||||
|
|
||||||
void load();
|
void load();
|
||||||
void declare(std::string const& name, foreign_t body);
|
void declare(std::string const& name, foreign_t body);
|
||||||
void declare_static(std::string const& name, static_fun_t body);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<VM> m_vm;
|
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;
|
std::shared_ptr<SymTable> m_sym;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
#define NODE_TYPE(G) \
|
#define NODE_TYPE(G) \
|
||||||
G(NODE_PROG), \
|
G(NODE_PROG), \
|
||||||
G(NODE_INT), \
|
G(NODE_INT), \
|
||||||
G(NODE_BOOL), \
|
|
||||||
G(NODE_OPAR), \
|
G(NODE_OPAR), \
|
||||||
G(NODE_CPAR), \
|
G(NODE_CPAR), \
|
||||||
G(NODE_IDENT), \
|
G(NODE_IDENT), \
|
||||||
|
|
|
@ -10,9 +10,6 @@
|
||||||
G(OPCODE_STORE), \
|
G(OPCODE_STORE), \
|
||||||
G(OPCODE_LOAD_GLOBAL), \
|
G(OPCODE_LOAD_GLOBAL), \
|
||||||
G(OPCODE_RET), \
|
G(OPCODE_RET), \
|
||||||
G(OPCODE_BRF), \
|
|
||||||
G(OPCODE_BR), \
|
|
||||||
G(OPCODE_NOT), \
|
|
||||||
G(OPCODE_MK_FUNCTION)
|
G(OPCODE_MK_FUNCTION)
|
||||||
|
|
||||||
namespace jk
|
namespace jk
|
||||||
|
|
|
@ -220,7 +220,6 @@ namespace jk
|
||||||
std::shared_ptr<Node> Parser::parse_literal()
|
std::shared_ptr<Node> Parser::parse_literal()
|
||||||
{
|
{
|
||||||
if (type_is(NODE_INT)
|
if (type_is(NODE_INT)
|
||||||
|| type_is(NODE_BOOL)
|
|
||||||
|| type_is(NODE_IDENT))
|
|| type_is(NODE_IDENT))
|
||||||
{
|
{
|
||||||
return consume();
|
return consume();
|
||||||
|
|
|
@ -22,12 +22,6 @@ namespace jk
|
||||||
m_instrs.push_back(Instr { opcode, param });
|
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::string Program::string() const
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
|
|
@ -27,8 +27,6 @@ namespace jk
|
||||||
void push_instr(OpcodeType opcode,
|
void push_instr(OpcodeType opcode,
|
||||||
std::optional<param_t> param = std::nullopt);
|
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);
|
size_t push_constant(std::shared_ptr<Value> value);
|
||||||
std::shared_ptr<Value> constant(size_t index) const;
|
std::shared_ptr<Value> constant(size_t index) const;
|
||||||
|
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
#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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
#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,7 +19,6 @@ namespace jk
|
||||||
{
|
{
|
||||||
case NODE_PROG:
|
case NODE_PROG:
|
||||||
case NODE_BODY: {
|
case NODE_BODY: {
|
||||||
|
|
||||||
for (size_t i=0; i<node->size(); i++)
|
for (size_t i=0; i<node->size(); i++)
|
||||||
{
|
{
|
||||||
pass(node->child(i).lock());
|
pass(node->child(i).lock());
|
||||||
|
@ -49,17 +48,11 @@ namespace jk
|
||||||
push(std::make_shared<Type>(TYPE_INT));
|
push(std::make_shared<Type>(TYPE_INT));
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NODE_BOOL: {
|
|
||||||
push(std::make_shared<Type>(TYPE_BOOL));
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case NODE_IDENT: {
|
case NODE_IDENT: {
|
||||||
std::string ident = node->repr();
|
std::string ident = node->repr();
|
||||||
auto entry = m_sym->find(ident);
|
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(),
|
m_logger.log<symbolic_error>(LOG_ERROR, node->loc(),
|
||||||
std::string()
|
std::string()
|
||||||
|
@ -68,10 +61,7 @@ namespace jk
|
||||||
+ "' is undefined");
|
+ "' is undefined");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry)
|
|
||||||
{
|
|
||||||
push(entry->type);
|
push(entry->type);
|
||||||
}
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NODE_VARDECL: {
|
case NODE_VARDECL: {
|
||||||
|
@ -83,22 +73,13 @@ namespace jk
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NODE_FUNCALL: {
|
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++)
|
for (size_t i=0; i<node->size(); i++)
|
||||||
{
|
{
|
||||||
pass(node->child(i).lock());
|
pass(node->child(i).lock());
|
||||||
pop();
|
pop();
|
||||||
}
|
}
|
||||||
}
|
// TODO find actual returned type
|
||||||
|
|
||||||
push(std::make_shared<Type>(TYPE_NIL));
|
push(std::make_shared<Type>(TYPE_NIL));
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -108,11 +89,6 @@ namespace jk
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StaticPass::add_static(std::string const& name)
|
|
||||||
{
|
|
||||||
m_statics.push_back(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StaticPass::push(std::shared_ptr<Type> type)
|
void StaticPass::push(std::shared_ptr<Type> type)
|
||||||
{
|
{
|
||||||
m_types.push_back(type);
|
m_types.push_back(type);
|
||||||
|
|
|
@ -15,13 +15,10 @@ namespace jk
|
||||||
|
|
||||||
void pass(std::shared_ptr<Node> node);
|
void pass(std::shared_ptr<Node> node);
|
||||||
|
|
||||||
void add_static(std::string const& name);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<SymTable> m_sym;
|
std::shared_ptr<SymTable> m_sym;
|
||||||
Logger& m_logger;
|
Logger& m_logger;
|
||||||
std::vector<std::shared_ptr<Type>> m_types;
|
std::vector<std::shared_ptr<Type>> m_types;
|
||||||
std::vector<std::string> m_statics;
|
|
||||||
|
|
||||||
void push(std::shared_ptr<Type> type);
|
void push(std::shared_ptr<Type> type);
|
||||||
std::shared_ptr<Type> pop();
|
std::shared_ptr<Type> pop();
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
#define TYPE_TYPE(G) \
|
#define TYPE_TYPE(G) \
|
||||||
G(TYPE_NIL), \
|
G(TYPE_NIL), \
|
||||||
G(TYPE_INT), \
|
G(TYPE_INT), \
|
||||||
G(TYPE_BOOL), \
|
|
||||||
G(TYPE_FUNCTION), \
|
G(TYPE_FUNCTION), \
|
||||||
G(TYPE_CODE), \
|
G(TYPE_CODE), \
|
||||||
G(TYPE_REF)
|
G(TYPE_REF)
|
||||||
|
|
25
lib/VM.cpp
25
lib/VM.cpp
|
@ -29,31 +29,6 @@ namespace jk
|
||||||
|
|
||||||
switch (instr.opcode)
|
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: {
|
case OPCODE_MK_FUNCTION: {
|
||||||
auto code = program()->constant(pop());
|
auto code = program()->constant(pop());
|
||||||
|
|
||||||
|
|
|
@ -20,14 +20,6 @@ namespace jk
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*static*/ std::shared_ptr<Value> Value::make_bool(bool val)
|
|
||||||
{
|
|
||||||
auto value = std::make_shared<Value>();
|
|
||||||
value->m_type = std::make_shared<Type>(TYPE_BOOL);
|
|
||||||
value->m_bool_val = val;
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*static*/ std::shared_ptr<Value>
|
/*static*/ std::shared_ptr<Value>
|
||||||
Value::make_function(std::shared_ptr<Function> val)
|
Value::make_function(std::shared_ptr<Function> val)
|
||||||
{
|
{
|
||||||
|
@ -76,7 +68,6 @@ namespace jk
|
||||||
{
|
{
|
||||||
case TYPE_NIL: return "<nil>";
|
case TYPE_NIL: return "<nil>";
|
||||||
case TYPE_INT: return std::to_string(*m_int_val);
|
case TYPE_INT: return std::to_string(*m_int_val);
|
||||||
case TYPE_BOOL: return *m_bool_val ? "true" : "false";
|
|
||||||
case TYPE_REF: return "<ref:" + std::to_string(*m_ref_val) + ">";
|
case TYPE_REF: return "<ref:" + std::to_string(*m_ref_val) + ">";
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -14,7 +14,6 @@ namespace jk
|
||||||
public:
|
public:
|
||||||
static std::shared_ptr<Value> make_nil();
|
static std::shared_ptr<Value> make_nil();
|
||||||
static std::shared_ptr<Value> make_int(int val);
|
static std::shared_ptr<Value> make_int(int val);
|
||||||
static std::shared_ptr<Value> make_bool(bool val);
|
|
||||||
static std::shared_ptr<Value> make_function(std::shared_ptr<Function>
|
static std::shared_ptr<Value> make_function(std::shared_ptr<Function>
|
||||||
val);
|
val);
|
||||||
static std::shared_ptr<Value> make_code(std::shared_ptr<Code> val);
|
static std::shared_ptr<Value> make_code(std::shared_ptr<Code> val);
|
||||||
|
@ -24,8 +23,6 @@ namespace jk
|
||||||
virtual ~Value() = default;
|
virtual ~Value() = default;
|
||||||
|
|
||||||
int as_int() const { return *m_int_val; }
|
int as_int() const { return *m_int_val; }
|
||||||
int as_bool() const { return *m_bool_val; }
|
|
||||||
|
|
||||||
size_t as_ref() const { return *m_ref_val; }
|
size_t as_ref() const { return *m_ref_val; }
|
||||||
|
|
||||||
std::shared_ptr<Function> as_function() const;
|
std::shared_ptr<Function> as_function() const;
|
||||||
|
@ -38,7 +35,6 @@ namespace jk
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<Type> m_type;
|
std::shared_ptr<Type> m_type;
|
||||||
std::optional<int> m_int_val;
|
std::optional<int> m_int_val;
|
||||||
std::optional<bool> m_bool_val;
|
|
||||||
std::shared_ptr<Function> m_function_val;
|
std::shared_ptr<Function> m_function_val;
|
||||||
std::shared_ptr<Code> m_code_val;
|
std::shared_ptr<Code> m_code_val;
|
||||||
std::optional<size_t> m_ref_val;
|
std::optional<size_t> m_ref_val;
|
||||||
|
|
|
@ -33,7 +33,6 @@ joko_lib = static_library(
|
||||||
'lib/Type.cpp',
|
'lib/Type.cpp',
|
||||||
'lib/Value.cpp',
|
'lib/Value.cpp',
|
||||||
'lib/Function.cpp',
|
'lib/Function.cpp',
|
||||||
'lib/StaticFunction.cpp',
|
|
||||||
'lib/Code.cpp',
|
'lib/Code.cpp',
|
||||||
'lib/SymTable.cpp',
|
'lib/SymTable.cpp',
|
||||||
'lib/StaticPass.cpp',
|
'lib/StaticPass.cpp',
|
||||||
|
|
|
@ -85,15 +85,12 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
|
|
||||||
auto compiler = std::make_shared<jk::Compiler>(logger);
|
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 program = std::make_shared<jk::Program>();
|
||||||
auto vm = std::make_shared<jk::VM>();
|
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();
|
loader->load();
|
||||||
|
|
||||||
|
auto static_pass = std::make_shared<jk::StaticPass>(sym, logger);
|
||||||
static_pass->pass(ast);
|
static_pass->pass(ast);
|
||||||
|
|
||||||
compiler->compile(ast, program, sym);
|
compiler->compile(ast, program, sym);
|
||||||
|
|
|
@ -81,18 +81,3 @@ TEST_CASE_METHOD(LexerTest, "Lexer_lambda")
|
||||||
test_next(*lexer, "RARROW");
|
test_next(*lexer, "RARROW");
|
||||||
test_end(*lexer);
|
test_end(*lexer);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_METHOD(LexerTest, "Lexer_bools")
|
|
||||||
{
|
|
||||||
auto lexer = jk::Factory(m_logger, "tests/lexer").make_lexer();
|
|
||||||
lexer->scan(" true false truea afalse (true) false!");
|
|
||||||
test_next(*lexer, "BOOL[true]");
|
|
||||||
test_next(*lexer, "BOOL[false]");
|
|
||||||
test_next(*lexer, "IDENT[truea]");
|
|
||||||
test_next(*lexer, "IDENT[afalse]");
|
|
||||||
test_next(*lexer, "OPAR");
|
|
||||||
test_next(*lexer, "BOOL[true]");
|
|
||||||
test_next(*lexer, "CPAR");
|
|
||||||
test_next(*lexer, "IDENT[false!]");
|
|
||||||
test_end(*lexer);
|
|
||||||
}
|
|
||||||
|
|
|
@ -71,9 +71,3 @@ TEST_CASE_METHOD(ParserTest, "Parser_fundecl")
|
||||||
")))",
|
")))",
|
||||||
" ($ (f x y) (add y x)) ");
|
" ($ (f x y) (add y x)) ");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_METHOD(ParserTest, "Parser_bool")
|
|
||||||
{
|
|
||||||
test_parser("PROG(VARDECL(IDENT[hello],BOOL[true]))",
|
|
||||||
"($ hello true)");
|
|
||||||
}
|
|
||||||
|
|
Reference in New Issue