Compare commits

..

No commits in common. "22131c2cf0d5fd5d58a60e04c494c5adb73736c1" and "4d91c05aeaebecf033bc5006a4f591de955e8c8e" have entirely different histories.

28 changed files with 65 additions and 467 deletions

View File

@ -1,16 +0,0 @@
($ mk-counter
(-> (init)
($ counter (- init 1))
(-> ()
(! counter (+ counter 1))
counter)))
($ a (mk-counter 5))
($ b (mk-counter 32))
(assert= 5 (a))
(assert= 32 (b))
(assert= 33 (b))
(assert= 6 (a))
(assert= 7 (a))
(assert= 34 (b))

View File

@ -1,4 +0,0 @@
($ add (-> (x) (+ 1 x)))
($ twice (-> (f x) (f (f x))))
(assert= 6 (twice add 4))

View File

@ -1,13 +0,0 @@
;; RECURSIVE LAMBDA
;; ================
(assert= 720 ((-> (n)
(if (= n 0) 1
(* n (self (- n 1))))) 6))
;; RECURSIVE NAMED LAMBDA
;; ======================
($ fac (-> (n)
(if (= n 0) 1
(* n (fac (- n 1))))))
(assert= 120 (fac 5))

View File

@ -1,21 +0,0 @@
($ a 32)
(! a 54)
(assert= 54 a)
(:
($ a 12)
(! a 99)
(assert= 99 a)
)
(assert= 54 a)
($ f (-> (x) (+ 2 x)))
(assert= 5 (f 3))
(! f (-> (x) (* x 4)))
(assert= 12 (f 3))

View File

@ -4,13 +4,11 @@
#include <cmath> #include <cmath>
#include "../src/Module.hpp" #include "../src/Module.hpp"
#include "../src/Constant.hpp" #include "../src/Constant.hpp"
#include "../src/SymTable.hpp"
using namespace fk; using namespace fk;
#define STDARGS std::vector<std::shared_ptr<Constant>> #define STDARGS std::vector<std::shared_ptr<Constant>>
#define STDRET std::shared_ptr<Constant> #define STDRET std::shared_ptr<Constant>
#define STDSYM std::shared_ptr<SymTable>
FK_ERROR(assert_error); FK_ERROR(assert_error);

View File

@ -20,7 +20,7 @@
namespace fkstd namespace fkstd
{ {
STDRET assert_eq(Loc loc, Module&, STDARGS args) STDRET assert_eq(Loc loc, STDARGS args)
{ {
auto oracle = args[0]; auto oracle = args[0];
auto expr = args[1]; auto expr = args[1];
@ -40,7 +40,7 @@ namespace fkstd
return std::make_shared<Constant>(TYPE_BOOL, true, loc); return std::make_shared<Constant>(TYPE_BOOL, true, loc);
} }
STDRET println(Loc loc, Module&, STDARGS args) STDRET println(Loc loc, STDARGS args)
{ {
std::string sep; std::string sep;
@ -60,7 +60,7 @@ namespace fkstd
return std::make_shared<Constant>(TYPE_INT, 0, loc); return std::make_shared<Constant>(TYPE_INT, 0, loc);
} }
STDRET add_int(Loc loc, Module&, STDARGS args) STDRET add_int(Loc loc, STDARGS args)
{ {
int result = 0; int result = 0;
@ -72,7 +72,7 @@ namespace fkstd
return std::make_shared<Constant>(TYPE_INT, result, loc); return std::make_shared<Constant>(TYPE_INT, result, loc);
} }
STDRET sub_int(Loc loc, Module&, STDARGS args) STDRET sub_int(Loc loc, STDARGS args)
{ {
if (args.empty()) if (args.empty())
{ {
@ -96,7 +96,7 @@ namespace fkstd
return std::make_shared<Constant>(TYPE_INT, result, loc); return std::make_shared<Constant>(TYPE_INT, result, loc);
} }
STDRET mul_int(Loc loc, Module&, STDARGS args) STDRET mul_int(Loc loc, STDARGS args)
{ {
int result = 1; int result = 1;
@ -108,7 +108,7 @@ namespace fkstd
return std::make_shared<Constant>(TYPE_INT, result, loc); return std::make_shared<Constant>(TYPE_INT, result, loc);
} }
STDRET div_int(Loc loc, Module&, STDARGS args) STDRET div_int(Loc loc, STDARGS args)
{ {
if (args.empty()) if (args.empty())
{ {
@ -132,7 +132,7 @@ namespace fkstd
return std::make_shared<Constant>(TYPE_INT, result, loc); return std::make_shared<Constant>(TYPE_INT, result, loc);
} }
STDRET mod_int(Loc loc, Module&, STDARGS args) STDRET mod_int(Loc loc, STDARGS args)
{ {
if (args.empty()) if (args.empty())
{ {
@ -149,7 +149,7 @@ namespace fkstd
return std::make_shared<Constant>(TYPE_INT, result, loc); return std::make_shared<Constant>(TYPE_INT, result, loc);
} }
STDRET pow_int(Loc loc, Module&, STDARGS args) STDRET pow_int(Loc loc, STDARGS args)
{ {
if (args.empty()) if (args.empty())
{ {
@ -166,32 +166,32 @@ namespace fkstd
return std::make_shared<Constant>(TYPE_INT, result, loc); return std::make_shared<Constant>(TYPE_INT, result, loc);
} }
STDRET lt(Loc loc, Module&, STDARGS args) STDRET lt(Loc loc, STDARGS args)
{ {
NUM_BINOP(<); NUM_BINOP(<);
} }
STDRET le(Loc loc, Module&, STDARGS args) STDRET le(Loc loc, STDARGS args)
{ {
NUM_BINOP(<=); NUM_BINOP(<=);
} }
STDRET gt(Loc loc, Module&, STDARGS args) STDRET gt(Loc loc, STDARGS args)
{ {
NUM_BINOP(>); NUM_BINOP(>);
} }
STDRET ge(Loc loc, Module&, STDARGS args) STDRET ge(Loc loc, STDARGS args)
{ {
NUM_BINOP(>=); NUM_BINOP(>=);
} }
STDRET eq(Loc loc, Module&, STDARGS args) STDRET eq(Loc loc, STDARGS args)
{ {
NUM_BINOP(==); NUM_BINOP(==);
} }
STDRET ne(Loc loc, Module&, STDARGS args) STDRET ne(Loc loc, STDARGS args)
{ {
NUM_BINOP(!=); NUM_BINOP(!=);
} }

View File

@ -4,24 +4,22 @@
namespace fkstd namespace fkstd
{ {
STDRET set(Loc loc, Module& mod, STDARGS args); STDRET assert_eq(Loc loc, STDARGS args);
STDRET println(Loc loc, STDARGS args);
STDRET assert_eq(Loc loc, Module& mod, STDARGS args); STDRET add_int(Loc loc, STDARGS args);
STDRET println(Loc loc, Module& mod, STDARGS args); STDRET sub_int(Loc loc, STDARGS args);
STDRET mul_int(Loc loc, STDARGS args);
STDRET div_int(Loc loc, STDARGS args);
STDRET mod_int(Loc loc, STDARGS args);
STDRET pow_int(Loc loc, STDARGS args);
STDRET add_int(Loc loc, Module& mod, STDARGS args); STDRET lt(Loc loc, STDARGS args);
STDRET sub_int(Loc loc, Module& mod, STDARGS args); STDRET le(Loc loc, STDARGS args);
STDRET mul_int(Loc loc, Module& mod, STDARGS args); STDRET gt(Loc loc, STDARGS args);
STDRET div_int(Loc loc, Module& mod, STDARGS args); STDRET ge(Loc loc, STDARGS args);
STDRET mod_int(Loc loc, Module& mod, STDARGS args); STDRET eq(Loc loc, STDARGS args);
STDRET pow_int(Loc loc, Module& mod, STDARGS args); STDRET ne(Loc loc, STDARGS args);
STDRET lt(Loc loc, Module& mod, STDARGS args);
STDRET le(Loc loc, Module& mod, STDARGS args);
STDRET gt(Loc loc, Module& mod, STDARGS args);
STDRET ge(Loc loc, Module& mod, STDARGS args);
STDRET eq(Loc loc, Module& mod, STDARGS args);
STDRET ne(Loc loc, Module& mod, STDARGS args);
} }
#endif #endif

View File

@ -2,11 +2,8 @@
#include "fun.hpp" #include "fun.hpp"
#include "macro.hpp" #include "macro.hpp"
Module* _module;
extern "C" void lib(Module& mod) extern "C" void lib(Module& mod)
{ {
_module = &mod;
mod.register_function("assert=", fkstd::assert_eq); mod.register_function("assert=", fkstd::assert_eq);
mod.register_function("println", fkstd::println); mod.register_function("println", fkstd::println);
mod.register_function("+", fkstd::add_int); mod.register_function("+", fkstd::add_int);
@ -22,7 +19,6 @@ extern "C" void lib(Module& mod)
mod.register_function("=", fkstd::eq); mod.register_function("=", fkstd::eq);
mod.register_function("<>", fkstd::ne); mod.register_function("<>", fkstd::ne);
mod.register_macro("!", fkstd::set_addr);
mod.register_macro("assert-static-fail", fkstd::assert_static_fail); mod.register_macro("assert-static-fail", fkstd::assert_static_fail);
mod.register_macro(":", fkstd::block); mod.register_macro(":", fkstd::block);
mod.register_macro("$", fkstd::decl); mod.register_macro("$", fkstd::decl);

View File

@ -3,26 +3,6 @@
namespace fkstd namespace fkstd
{ {
void set_addr(Compiler& compiler,
std::shared_ptr<Node> node,
std::shared_ptr<Program> program)
{
auto ident = node->child(1)->repr();
compiler.compile_prog(node->child(2), program);
std::cout << "push " << node->child(2)->string() << std::endl;
auto entry = compiler.sym()->find(ident);
if (entry)
{
program->add(OP_STORE_LOCAL, entry->addr());
}
else
{
auto entry = compiler.sym()->find_global(ident);
program->add(OP_STORE_CLOSURE, entry->addr());
}
}
void assert_static_fail(Compiler& compiler, void assert_static_fail(Compiler& compiler,
std::shared_ptr<Node> node, std::shared_ptr<Node> node,
std::shared_ptr<Program> program) std::shared_ptr<Program> program)
@ -54,9 +34,7 @@ namespace fkstd
std::string ident = node->child(1)->repr(); std::string ident = node->child(1)->repr();
auto rhs = node->child(2); auto rhs = node->child(2);
compiler.push_decl(ident);
compiler.compile_prog(rhs, program); compiler.compile_prog(rhs, program);
compiler.pop_decl();
auto entry = compiler.sym()->declare_local(ident, auto entry = compiler.sym()->declare_local(ident,
addr, addr,

View File

@ -4,10 +4,6 @@
namespace fkstd namespace fkstd
{ {
void set_addr(Compiler& compiler,
std::shared_ptr<Node> node,
std::shared_ptr<Program> program);
void assert_static_fail(Compiler& compiler, void assert_static_fail(Compiler& compiler,
std::shared_ptr<Node> node, std::shared_ptr<Node> node,
std::shared_ptr<Program> program); std::shared_ptr<Program> program);

View File

@ -53,12 +53,6 @@ namespace fk
case NODE_LAMBDA: { case NODE_LAMBDA: {
auto params = node->child(0); auto params = node->child(0);
auto body = node->child(1); auto body = node->child(1);
std::string func_name = "self";
if (m_decl_stack.empty() == false)
{
func_name = m_decl_stack.back();
}
m_sym->enter_scope(node); m_sym->enter_scope(node);
@ -68,8 +62,6 @@ namespace fk
m_sym->declare_local(ident, i, node->loc()); m_sym->declare_local(ident, i, node->loc());
} }
m_sym->declare_local(func_name, params->size(), node->loc());
Compiler compiler {m_sym}; Compiler compiler {m_sym};
for (auto e: m_macros) for (auto e: m_macros)
{ {
@ -77,7 +69,6 @@ namespace fk
} }
auto program = compiler.compile(body); auto program = compiler.compile(body);
program->add(OP_RET); program->add(OP_RET);
m_sym->leave_scope(); m_sym->leave_scope();
@ -116,21 +107,18 @@ namespace fk
if (auto entry = m_sym->find(node->child(0)->repr()); if (auto entry = m_sym->find(node->child(0)->repr());
entry && entry->is_global() == false) entry && entry->is_global() == false)
{ {
if (entry->node()) size_t arity = entry->node()->child(0)->size();
if (arity != node->size() - 1)
{ {
size_t arity = entry->node()->child(0)->size(); std::stringstream ss;
if (arity != node->size() - 1) ss << "arity mismatch: " << node->child(0)->repr()
{ << " expect '"
std::stringstream ss; << arity
ss << "arity mismatch: " << node->child(0)->repr() << "' arguments, got '"
<< " expect '" << node->size() - 1
<< arity << "'";
<< "' arguments, got '"
<< node->size() - 1
<< "'";
node->loc().error<compile_error>(LOG_ERROR, ss.str()); node->loc().error<compile_error>(LOG_ERROR, ss.str());
}
} }
prog->add(OP_CALL_REF, node->size() - 1); prog->add(OP_CALL_REF, node->size() - 1);
@ -146,17 +134,6 @@ namespace fk
case NODE_IDENT: { case NODE_IDENT: {
auto entry = m_sym->find(node->repr()); auto entry = m_sym->find(node->repr());
if (!entry)
{
auto entry = m_sym->find_global(node->repr());
if (entry)
{
prog->add(OP_LOAD_CLOSURE, entry->addr());
break;
}
}
if (!entry) if (!entry)
{ {
std::stringstream ss; std::stringstream ss;
@ -213,16 +190,4 @@ namespace fk
} break; } break;
} }
} }
void Compiler::push_decl(std::string const& ident)
{
m_decl_stack.push_back(ident);
}
void Compiler::pop_decl()
{
assert(m_decl_stack.empty() == false);
m_decl_stack.pop_back();
}
} }

View File

@ -31,12 +31,8 @@ namespace fk
void compile_prog(std::shared_ptr<Node> node, void compile_prog(std::shared_ptr<Node> node,
std::shared_ptr<Program> prog); std::shared_ptr<Program> prog);
void push_decl(std::string const& ident);
void pop_decl();
private: private:
std::shared_ptr<SymTable> m_sym; std::shared_ptr<SymTable> m_sym;
std::vector<std::string> m_decl_stack;
std::unordered_map<std::string, std::unordered_map<std::string,
std::shared_ptr<NativeMacro>> m_macros; std::shared_ptr<NativeMacro>> m_macros;

View File

@ -14,12 +14,6 @@ namespace fk
{ {
} }
std::shared_ptr<Constant> Constant::clone()
{
auto res = std::make_shared<Constant>(m_type, m_value, m_loc);
return res;
}
std::string Constant::string() const std::string Constant::string() const
{ {
switch (m_type) switch (m_type)
@ -29,7 +23,6 @@ namespace fk
case TYPE_BOOL: return std::get<bool>(m_value) ? "true" : "false"; case TYPE_BOOL: return std::get<bool>(m_value) ? "true" : "false";
case TYPE_STRING: return std::get<std::string>(m_value); case TYPE_STRING: return std::get<std::string>(m_value);
case TYPE_REF: return std::to_string(std::get<size_t>(m_value)); case TYPE_REF: return std::to_string(std::get<size_t>(m_value));
case TYPE_PROGRAM: return "<program>";
default: { default: {
std::stringstream ss; std::stringstream ss;

View File

@ -25,8 +25,6 @@ namespace fk
explicit Constant(Type type, constant_t value, Loc const& loc); explicit Constant(Type type, constant_t value, Loc const& loc);
virtual ~Constant(); virtual ~Constant();
std::shared_ptr<Constant> clone();
Type type() const { return m_type; } Type type() const { return m_type; }
constant_t value() const { return m_value; } constant_t value() const { return m_value; }
Loc loc() const { return m_loc; } Loc loc() const { return m_loc; }

View File

@ -11,23 +11,4 @@ namespace fk
/*virtual*/ Lambda::~Lambda() /*virtual*/ Lambda::~Lambda()
{ {
} }
bool Lambda::has_env(addr_t addr) const
{
return m_env.find(addr) != std::end(m_env);
}
std::shared_ptr<Constant>
Lambda::get_env(addr_t addr) const
{
assert(has_env(addr));
return m_env.at(addr);
}
void
Lambda::add_env(addr_t addr, std::shared_ptr<Constant> constant)
{
m_env[addr] = constant;
}
} }

View File

@ -4,7 +4,6 @@
#include "commons.hpp" #include "commons.hpp"
#include "SymTable.hpp" #include "SymTable.hpp"
#include "Program.hpp" #include "Program.hpp"
#include <unordered_map>
namespace fk namespace fk
{ {
@ -19,13 +18,8 @@ namespace fk
std::shared_ptr<Program> program() const { return m_program; } std::shared_ptr<Program> program() const { return m_program; }
std::shared_ptr<SymTable> sym() const { return m_sym; } std::shared_ptr<SymTable> sym() const { return m_sym; }
bool has_env(addr_t addr) const;
std::shared_ptr<Constant> get_env(addr_t addr) const;
void add_env(addr_t addr, std::shared_ptr<Constant> constant);
private: private:
std::shared_ptr<Program> m_program; std::shared_ptr<Program> m_program;
std::unordered_map<addr_t, std::shared_ptr<Constant>> m_env;
size_t m_arity; size_t m_arity;
std::shared_ptr<SymTable> m_sym = std::make_shared<SymTable>(); std::shared_ptr<SymTable> m_sym = std::make_shared<SymTable>();
}; };

View File

@ -20,9 +20,9 @@ namespace fk
import_std(); import_std();
m_source = load_sources(); m_source = load_sources();
m_ast = m_parser->parse(m_source); m_ast = m_parser->parse(m_source);
m_program = m_compiler->compile(m_ast);
m_vm->mount(m_program); auto program = m_compiler->compile(m_ast);
m_vm->mount(program);
m_vm->run(); m_vm->run();
} }

View File

@ -18,10 +18,6 @@ namespace fk
explicit Module(std::filesystem::path source_path); explicit Module(std::filesystem::path source_path);
virtual ~Module(); virtual ~Module();
std::shared_ptr<Program> program() const { return m_program; }
std::shared_ptr<SymTable> sym() const { return m_sym; }
std::shared_ptr<VM> vm() const { return m_vm; }
void build(); void build();
void import_std(); void import_std();
@ -39,8 +35,8 @@ namespace fk
std::shared_ptr<SymTable> m_sym = std::make_shared<SymTable>(); std::shared_ptr<SymTable> m_sym = std::make_shared<SymTable>();
std::shared_ptr<Compiler> m_compiler = std::make_shared<Compiler>(m_sym); std::shared_ptr<Compiler> m_compiler = std::make_shared<Compiler>(m_sym);
std::shared_ptr<Node> m_ast; std::shared_ptr<Node> m_ast;
std::shared_ptr<VM> m_vm = std::make_shared<VM>(*this); std::shared_ptr<VM> m_vm = std::make_shared<VM>();
std::shared_ptr<Program> m_program = std::make_shared<Program>();
std::string load_sources(); std::string load_sources();
}; };
} }

View File

@ -1,5 +1,4 @@
#include "NativeFunction.hpp" #include "NativeFunction.hpp"
#include "Module.hpp"
namespace fk namespace fk
{ {
@ -14,9 +13,8 @@ namespace fk
std::shared_ptr<Constant> std::shared_ptr<Constant>
NativeFunction::call(Loc const& loc, NativeFunction::call(Loc const& loc,
Module& mod,
std::vector<std::shared_ptr<Constant>> args) std::vector<std::shared_ptr<Constant>> args)
{ {
return m_native(loc, mod, args); return m_native(loc, args);
} }
} }

View File

@ -6,12 +6,8 @@
namespace fk namespace fk
{ {
class Module;
using native_t = std::function using native_t = std::function
<std::shared_ptr<Constant>(Loc, <std::shared_ptr<Constant>(Loc, std::vector<std::shared_ptr<Constant>>)>;
Module&,
std::vector<std::shared_ptr<Constant>>)>;
class NativeFunction class NativeFunction
{ {
@ -20,9 +16,7 @@ namespace fk
virtual ~NativeFunction(); virtual ~NativeFunction();
std::shared_ptr<Constant> std::shared_ptr<Constant>
call(Loc const& loc, call(Loc const& loc, std::vector<std::shared_ptr<Constant>> args);
Module& mod,
std::vector<std::shared_ptr<Constant>> args);
private: private:
native_t m_native; native_t m_native;

View File

@ -7,7 +7,6 @@ namespace fk
{ {
class Compiler; class Compiler;
class Program; class Program;
class SymTable;
class Node; class Node;
using macro_t = std::function<void(Compiler&, using macro_t = std::function<void(Compiler&,

View File

@ -36,7 +36,6 @@ namespace fk
size_t Program::add(std::shared_ptr<Constant> constant) size_t Program::add(std::shared_ptr<Constant> constant)
{ {
assert(constant);
for (size_t i=0; i<m_consts.size(); i++) for (size_t i=0; i<m_consts.size(); i++)
{ {
if (m_consts[i]->equals(*constant) if (m_consts[i]->equals(*constant)

View File

@ -51,95 +51,23 @@ namespace fk
} }
std::optional<SymEntry> SymTable::find(std::string const& name) std::optional<SymEntry> SymTable::find(std::string const& name)
{
auto idx = find_idx(name);
if (!idx) { return std::nullopt; }
return m_entries[*idx];
}
std::optional<size_t> SymTable::find_idx(std::string const& name)
{ {
std::optional<SymEntry> result; std::optional<SymEntry> result;
size_t i=0;
std::optional<size_t> idx;
for (auto& entry: m_entries) for (auto& entry: m_entries)
{ {
if (entry.name() == name && entry.is_global()) if (entry.name() == name
&& entry.scope() <= m_scope
&& ((entry.parent() == nullptr && m_parents.empty())
|| entry.parent() == m_parents.back())
&& (result == std::nullopt ||
entry.scope() > result->scope()))
{ {
result = entry; result = entry;
idx = i;
} }
else if (entry.name() == name
&& entry.scope() <= m_scope
&& ((entry.parent() == nullptr && m_parents.empty())
|| entry.parent() == m_parents.back())
&& (result == std::nullopt ||
entry.scope() > result->scope()))
{
result = entry;
idx = i;
}
i++;
} }
return idx; return result;
}
std::optional<SymEntry> SymTable::find_global(std::string const& name)
{
auto idx = find_idx_global(name);
if (!idx) { return std::nullopt; }
return m_entries[*idx];
}
std::optional<size_t> SymTable::find_idx_global(std::string const& name)
{
std::optional<SymEntry> result;
size_t i=0;
std::optional<size_t> idx;
for (auto& entry: m_entries)
{
if (entry.name() == name && entry.is_global())
{
result = entry;
idx = i;
}
else if (entry.name() == name
&& entry.scope() <= m_scope
&& (result == std::nullopt ||
entry.scope() > result->scope()))
{
result = entry;
idx = i;
}
i++;
}
return idx;
}
void SymTable::set(std::string const& name, addr_t addr)
{
if (auto idx = find_idx(name);
idx)
{
m_entries[*idx].set_addr(addr);
}
else
{
std::cerr << "cannot set value to '"
<< name
<< "'" << std::endl;
abort();
}
} }
std::string SymTable::string() const std::string SymTable::string() const

View File

@ -14,8 +14,6 @@ namespace fk
explicit SymTable(); explicit SymTable();
virtual ~SymTable(); virtual ~SymTable();
int scope() const { return m_scope; }
SymEntry& declare_local(std::string const& name, SymEntry& declare_local(std::string const& name,
addr_t addr, addr_t addr,
Loc const& loc); Loc const& loc);
@ -25,12 +23,6 @@ namespace fk
Loc const& loc); Loc const& loc);
std::optional<SymEntry> find(std::string const& name); std::optional<SymEntry> find(std::string const& name);
std::optional<size_t> find_idx(std::string const& name);
std::optional<SymEntry> find_global(std::string const& name);
std::optional<size_t> find_idx_global(std::string const& name);
void set(std::string const& name, addr_t addr);
std::string string() const; std::string string() const;

View File

@ -4,8 +4,7 @@
namespace fk namespace fk
{ {
/*explicit*/ VM::VM(Module& mod) /*explicit*/ VM::VM()
: m_mod { mod }
{ {
} }
@ -22,34 +21,12 @@ namespace fk
void VM::run() void VM::run()
{ {
while (m_frames.empty() == false while (m_pc < frame().program->size())
&& m_pc < frame().program->size())
{ {
Instr instr = frame().program->instr(m_pc); Instr instr = frame().program->instr(m_pc);
switch (instr.opcode) switch (instr.opcode)
{ {
case OP_STORE_CLOSURE: {
auto val = frame().program->get_const(top());
auto lambda = frame().lambda;
lambda->add_env(instr.param, val);
m_pc++;
} break;
case OP_LOAD_CLOSURE: {
if (frame().lambda && frame().lambda->has_env(instr.param))
{
auto val = frame().lambda->get_env(instr.param);
addr_t addr = frame().program->add(val);
push(addr);
m_pc++;
break;
}
m_pc++;
} break;
case OP_BR: { case OP_BR: {
m_pc = instr.param; m_pc = instr.param;
} break; } break;
@ -77,14 +54,6 @@ namespace fk
addr_t addr = store_global(lambda); addr_t addr = store_global(lambda);
auto ref = std::make_shared<Constant>(TYPE_REF, addr, p->loc()); auto ref = std::make_shared<Constant>(TYPE_REF, addr, p->loc());
if (m_frames.size() > 1)
{
for (auto e: m_frames.back().locals)
{
lambda->add_env(e.first, e.second);
}
}
push(frame().program->add(ref)); push(frame().program->add(ref));
m_pc++; m_pc++;
@ -106,19 +75,10 @@ namespace fk
pop(); pop();
} }
} }
auto value = m_frames.back().program->get_const(*ret); auto value = m_frames.back().program->get_const(*ret);
m_frames.pop_back(); m_frames.pop_back();
push(frame().program->add(value));
if (m_frames.empty() == false)
{
push(frame().program->add(value));
}
else
{
m_return_const = value;
}
m_pc++; m_pc++;
} break; } break;
@ -132,18 +92,11 @@ namespace fk
} }
auto ref_val = frame().program->get_const(pop()); auto ref_val = frame().program->get_const(pop());
addr_t ref = std::get<addr_t>(ref_val->value()); addr_t ref = std::get<addr_t>(ref_val->value());
auto lambda = std::get<std::shared_ptr<Lambda>>(load_global(ref)); auto lambda = std::get<std::shared_ptr<Lambda>>(load_global(ref));
auto self = std::make_shared<Constant>(TYPE_REF,
static_cast<size_t>(ref),
ref_val->loc());
Frame frame; Frame frame;
frame.lambda = lambda;
frame.program = lambda->program(); frame.program = lambda->program();
frame.ret_addr = m_pc; frame.ret_addr = m_pc;
frame.stack_sz = m_stack.size(); frame.stack_sz = m_stack.size();
@ -154,8 +107,6 @@ namespace fk
store_local(i, args[i]); store_local(i, args[i]);
} }
store_local(args.size(), self);
m_pc = 0; m_pc = 0;
} break; } break;
@ -169,9 +120,7 @@ namespace fk
args.insert(std::begin(args), args.insert(std::begin(args),
frame().program->get_const(addr)); frame().program->get_const(addr));
} }
auto ref_val = frame().program->get_const(pop()); auto ref_val = frame().program->get_const(pop());
Loc loc = ref_val->loc(); Loc loc = ref_val->loc();
if (instr.param > 0) if (instr.param > 0)
@ -180,26 +129,17 @@ namespace fk
} }
auto ref = std::get<size_t>(ref_val->value()); auto ref = std::get<size_t>(ref_val->value());
auto fun = std::get<std::shared_ptr<NativeFunction>> auto fun = std::get<std::shared_ptr<NativeFunction>>
(load_global(ref)); (load_global(ref));
push(frame().program->add(fun->call(loc, m_mod, args))); push(frame().program->add(fun->call(loc, args)));
m_pc++; m_pc++;
} break; } break;
case OP_LOAD_LOCAL: { case OP_LOAD_LOCAL: {
auto value = frame().locals[instr.param]; auto value = frame().locals[instr.param];
assert(value);
if (!value)
{
std::cerr << "cannot find value with ref '"
<< instr.param
<< "'" << std::endl;
abort();
}
push(frame().program->add(value)); push(frame().program->add(value));
m_pc++; m_pc++;
@ -240,42 +180,8 @@ namespace fk
} }
} }
std::shared_ptr<Constant>
VM::call(std::shared_ptr<Lambda> lambda,
size_t ref,
std::vector<std::shared_ptr<Constant>> const& args,
Loc const& loc)
{
Frame frame;
frame.lambda = lambda;
frame.program = lambda->program();
frame.ret_addr = m_pc;
frame.stack_sz = m_stack.size();
m_frames.push_back(frame);
for (size_t i=0; i<args.size(); i++)
{
store_local(i, args[i]);
}
auto self = std::make_shared<Constant>(TYPE_REF,
static_cast<size_t>(ref),
loc);
store_local(args.size(), self);
m_pc = 0;
return nullptr;
}
global_t VM::load_global(addr_t addr) const global_t VM::load_global(addr_t addr) const
{ {
if (m_globals.find(addr) == std::end(m_globals))
{
std::cerr << "cannot find global " << addr << std::endl;
abort();
}
return m_globals.at(addr); return m_globals.at(addr);
} }
@ -332,40 +238,4 @@ namespace fk
m_stack.pop_back(); m_stack.pop_back();
return t; return t;
} }
std::shared_ptr<Constant>
VM::run_lambda(VM const& parent,
std::shared_ptr<Lambda> lambda,
std::vector<std::shared_ptr<Constant>> args,
size_t ref,
Loc const& loc)
{
for (auto entry: parent.m_globals)
{
store_global(entry.first, entry.second);
}
auto self = std::make_shared<Constant>(TYPE_REF,
static_cast<size_t>(ref),
loc);
Frame frame;
frame.lambda = lambda;
frame.program = lambda->program();
frame.ret_addr = m_pc;
frame.stack_sz = m_stack.size();
m_frames.push_back(frame);
for (size_t i=0; i<args.size(); i++)
{
store_local(i, args[i]);
}
store_local(args.size(), self);
m_pc = 0;
run();
return m_return_const;
}
} }

View File

@ -14,17 +14,15 @@ namespace fk
struct Frame { struct Frame {
std::shared_ptr<Program> program; std::shared_ptr<Program> program;
std::shared_ptr<Lambda> lambda;
addr_t ret_addr; addr_t ret_addr;
size_t stack_sz; size_t stack_sz;
std::unordered_map<addr_t, std::shared_ptr<Constant>> locals; std::unordered_map<addr_t, std::shared_ptr<Constant>> locals;
}; };
class Module;
class VM class VM
{ {
public: public:
explicit VM(Module& mod); explicit VM();
virtual ~VM(); virtual ~VM();
Frame& frame() { return m_frames.back(); } Frame& frame() { return m_frames.back(); }
@ -32,12 +30,6 @@ namespace fk
void mount(std::shared_ptr<Program> program); void mount(std::shared_ptr<Program> program);
void run(); void run();
std::shared_ptr<Constant>
call(std::shared_ptr<Lambda> lambda,
size_t ref,
std::vector<std::shared_ptr<Constant>> const& args,
Loc const& loc);
global_t load_global(addr_t addr) const; global_t load_global(addr_t addr) const;
void store_global(addr_t addr, global_t value); void store_global(addr_t addr, global_t value);
size_t store_global(global_t value); size_t store_global(global_t value);
@ -47,24 +39,15 @@ namespace fk
std::string string() const; std::string string() const;
void push(addr_t addr);
addr_t top();
addr_t pop();
std::shared_ptr<Constant>
run_lambda(VM const& parent,
std::shared_ptr<Lambda> lambda,
std::vector<std::shared_ptr<Constant>> args,
size_t ref,
Loc const& loc);
private: private:
Module& m_mod;
addr_t m_pc = 0; addr_t m_pc = 0;
std::vector<Frame> m_frames; std::vector<Frame> m_frames;
std::vector<addr_t> m_stack; std::vector<addr_t> m_stack;
std::unordered_map<addr_t, global_t> m_globals; std::unordered_map<addr_t, global_t> m_globals;
std::shared_ptr<Constant> m_return_const;
void push(addr_t addr);
addr_t top();
addr_t pop();
}; };
} }

View File

@ -17,7 +17,7 @@ int main(int argc, char** argv)
int opt_index = 0; int opt_index = 0;
int c = getopt_long(argc, argv, "hd", options, &opt_index); int c = getopt_long(argc, argv, "h", options, &opt_index);
if (c == -1) if (c == -1)
{ {

View File

@ -4,7 +4,7 @@
#define OPCODES(G) G(OP_LOAD_CONST), G(OP_POP), G(OP_CALL_NATIVE), \ #define OPCODES(G) G(OP_LOAD_CONST), G(OP_POP), G(OP_CALL_NATIVE), \
G(OP_LOAD_GLOBAL), G(OP_LOAD_LOCAL), G(OP_STORE_LOCAL), \ G(OP_LOAD_GLOBAL), G(OP_LOAD_LOCAL), G(OP_STORE_LOCAL), \
G(OP_MAKE_FUNCTION), G(OP_CALL_REF), G(OP_RET), G(OP_BNE), \ G(OP_MAKE_FUNCTION), G(OP_CALL_REF), G(OP_RET), G(OP_BNE), \
G(OP_BR), G(OP_LOAD_CLOSURE), G(OP_STORE_CLOSURE) G(OP_BR)
#include "commons.hpp" #include "commons.hpp"