Compare commits
4 Commits
4d91c05aea
...
22131c2cf0
Author | SHA1 | Date |
---|---|---|
bog | 22131c2cf0 | |
bog | 9591d6c176 | |
bog | 70d0ba241c | |
bog | 7a792274f6 |
|
@ -0,0 +1,16 @@
|
||||||
|
($ 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))
|
|
@ -0,0 +1,4 @@
|
||||||
|
($ add (-> (x) (+ 1 x)))
|
||||||
|
($ twice (-> (f x) (f (f x))))
|
||||||
|
|
||||||
|
(assert= 6 (twice add 4))
|
|
@ -0,0 +1,13 @@
|
||||||
|
;; 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))
|
|
@ -0,0 +1,21 @@
|
||||||
|
($ 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))
|
|
@ -4,11 +4,13 @@
|
||||||
#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);
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
namespace fkstd
|
namespace fkstd
|
||||||
{
|
{
|
||||||
STDRET assert_eq(Loc loc, STDARGS args)
|
STDRET assert_eq(Loc loc, Module&, 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, STDARGS args)
|
STDRET println(Loc loc, Module&, 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, STDARGS args)
|
STDRET add_int(Loc loc, Module&, 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, STDARGS args)
|
STDRET sub_int(Loc loc, Module&, 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, STDARGS args)
|
STDRET mul_int(Loc loc, Module&, 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, STDARGS args)
|
STDRET div_int(Loc loc, Module&, 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, STDARGS args)
|
STDRET mod_int(Loc loc, Module&, 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, STDARGS args)
|
STDRET pow_int(Loc loc, Module&, 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, STDARGS args)
|
STDRET lt(Loc loc, Module&, STDARGS args)
|
||||||
{
|
{
|
||||||
NUM_BINOP(<);
|
NUM_BINOP(<);
|
||||||
}
|
}
|
||||||
|
|
||||||
STDRET le(Loc loc, STDARGS args)
|
STDRET le(Loc loc, Module&, STDARGS args)
|
||||||
{
|
{
|
||||||
NUM_BINOP(<=);
|
NUM_BINOP(<=);
|
||||||
}
|
}
|
||||||
|
|
||||||
STDRET gt(Loc loc, STDARGS args)
|
STDRET gt(Loc loc, Module&, STDARGS args)
|
||||||
{
|
{
|
||||||
NUM_BINOP(>);
|
NUM_BINOP(>);
|
||||||
}
|
}
|
||||||
|
|
||||||
STDRET ge(Loc loc, STDARGS args)
|
STDRET ge(Loc loc, Module&, STDARGS args)
|
||||||
{
|
{
|
||||||
NUM_BINOP(>=);
|
NUM_BINOP(>=);
|
||||||
}
|
}
|
||||||
|
|
||||||
STDRET eq(Loc loc, STDARGS args)
|
STDRET eq(Loc loc, Module&, STDARGS args)
|
||||||
{
|
{
|
||||||
NUM_BINOP(==);
|
NUM_BINOP(==);
|
||||||
}
|
}
|
||||||
|
|
||||||
STDRET ne(Loc loc, STDARGS args)
|
STDRET ne(Loc loc, Module&, STDARGS args)
|
||||||
{
|
{
|
||||||
NUM_BINOP(!=);
|
NUM_BINOP(!=);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,22 +4,24 @@
|
||||||
|
|
||||||
namespace fkstd
|
namespace fkstd
|
||||||
{
|
{
|
||||||
STDRET assert_eq(Loc loc, STDARGS args);
|
STDRET set(Loc loc, Module& mod, STDARGS args);
|
||||||
STDRET println(Loc loc, STDARGS args);
|
|
||||||
|
|
||||||
STDRET add_int(Loc loc, STDARGS args);
|
STDRET assert_eq(Loc loc, Module& mod, STDARGS args);
|
||||||
STDRET sub_int(Loc loc, STDARGS args);
|
STDRET println(Loc loc, Module& mod, 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 lt(Loc loc, STDARGS args);
|
STDRET add_int(Loc loc, Module& mod, STDARGS args);
|
||||||
STDRET le(Loc loc, STDARGS args);
|
STDRET sub_int(Loc loc, Module& mod, STDARGS args);
|
||||||
STDRET gt(Loc loc, STDARGS args);
|
STDRET mul_int(Loc loc, Module& mod, STDARGS args);
|
||||||
STDRET ge(Loc loc, STDARGS args);
|
STDRET div_int(Loc loc, Module& mod, STDARGS args);
|
||||||
STDRET eq(Loc loc, STDARGS args);
|
STDRET mod_int(Loc loc, Module& mod, STDARGS args);
|
||||||
STDRET ne(Loc loc, STDARGS args);
|
STDRET pow_int(Loc loc, Module& mod, 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
|
||||||
|
|
|
@ -2,8 +2,11 @@
|
||||||
#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);
|
||||||
|
@ -19,6 +22,7 @@ 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);
|
||||||
|
|
|
@ -3,6 +3,26 @@
|
||||||
|
|
||||||
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)
|
||||||
|
@ -34,7 +54,9 @@ 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,
|
||||||
|
|
|
@ -4,6 +4,10 @@
|
||||||
|
|
||||||
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);
|
||||||
|
|
|
@ -53,6 +53,12 @@ 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);
|
||||||
|
|
||||||
|
@ -62,6 +68,8 @@ 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)
|
||||||
{
|
{
|
||||||
|
@ -69,6 +77,7 @@ 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();
|
||||||
|
@ -107,18 +116,21 @@ 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)
|
||||||
{
|
{
|
||||||
size_t arity = entry->node()->child(0)->size();
|
if (entry->node())
|
||||||
if (arity != node->size() - 1)
|
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
size_t arity = entry->node()->child(0)->size();
|
||||||
ss << "arity mismatch: " << node->child(0)->repr()
|
if (arity != node->size() - 1)
|
||||||
<< " expect '"
|
{
|
||||||
<< arity
|
std::stringstream ss;
|
||||||
<< "' arguments, got '"
|
ss << "arity mismatch: " << node->child(0)->repr()
|
||||||
<< node->size() - 1
|
<< " expect '"
|
||||||
<< "'";
|
<< 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);
|
||||||
|
@ -134,6 +146,17 @@ 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;
|
||||||
|
@ -190,4 +213,16 @@ 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();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,8 +31,12 @@ 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;
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,12 @@ 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)
|
||||||
|
@ -23,6 +29,7 @@ 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;
|
||||||
|
|
|
@ -25,6 +25,8 @@ 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; }
|
||||||
|
|
|
@ -11,4 +11,23 @@ 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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#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
|
||||||
{
|
{
|
||||||
|
@ -18,8 +19,13 @@ 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>();
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
auto program = m_compiler->compile(m_ast);
|
m_vm->mount(m_program);
|
||||||
m_vm->mount(program);
|
|
||||||
m_vm->run();
|
m_vm->run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,10 @@ 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();
|
||||||
|
@ -35,8 +39,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>();
|
std::shared_ptr<VM> m_vm = std::make_shared<VM>(*this);
|
||||||
|
std::shared_ptr<Program> m_program = std::make_shared<Program>();
|
||||||
std::string load_sources();
|
std::string load_sources();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "NativeFunction.hpp"
|
#include "NativeFunction.hpp"
|
||||||
|
#include "Module.hpp"
|
||||||
|
|
||||||
namespace fk
|
namespace fk
|
||||||
{
|
{
|
||||||
|
@ -13,8 +14,9 @@ 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, args);
|
return m_native(loc, mod, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,12 @@
|
||||||
|
|
||||||
namespace fk
|
namespace fk
|
||||||
{
|
{
|
||||||
|
class Module;
|
||||||
|
|
||||||
using native_t = std::function
|
using native_t = std::function
|
||||||
<std::shared_ptr<Constant>(Loc, std::vector<std::shared_ptr<Constant>>)>;
|
<std::shared_ptr<Constant>(Loc,
|
||||||
|
Module&,
|
||||||
|
std::vector<std::shared_ptr<Constant>>)>;
|
||||||
|
|
||||||
class NativeFunction
|
class NativeFunction
|
||||||
{
|
{
|
||||||
|
@ -16,7 +20,9 @@ namespace fk
|
||||||
virtual ~NativeFunction();
|
virtual ~NativeFunction();
|
||||||
|
|
||||||
std::shared_ptr<Constant>
|
std::shared_ptr<Constant>
|
||||||
call(Loc const& loc, std::vector<std::shared_ptr<Constant>> args);
|
call(Loc const& loc,
|
||||||
|
Module& mod,
|
||||||
|
std::vector<std::shared_ptr<Constant>> args);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
native_t m_native;
|
native_t m_native;
|
||||||
|
|
|
@ -7,6 +7,7 @@ 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&,
|
||||||
|
|
|
@ -36,6 +36,7 @@ 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)
|
||||||
|
|
|
@ -51,23 +51,95 @@ 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
|
if (entry.name() == name && entry.is_global())
|
||||||
&& 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 result;
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
|
|
@ -14,6 +14,8 @@ 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);
|
||||||
|
@ -23,6 +25,12 @@ 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;
|
||||||
|
|
||||||
|
|
142
src/VM.cpp
142
src/VM.cpp
|
@ -4,7 +4,8 @@
|
||||||
|
|
||||||
namespace fk
|
namespace fk
|
||||||
{
|
{
|
||||||
/*explicit*/ VM::VM()
|
/*explicit*/ VM::VM(Module& mod)
|
||||||
|
: m_mod { mod }
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,12 +22,34 @@ namespace fk
|
||||||
|
|
||||||
void VM::run()
|
void VM::run()
|
||||||
{
|
{
|
||||||
while (m_pc < frame().program->size())
|
while (m_frames.empty() == false
|
||||||
|
&& 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;
|
||||||
|
@ -54,6 +77,14 @@ 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++;
|
||||||
|
@ -75,10 +106,19 @@ 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;
|
||||||
|
|
||||||
|
@ -92,11 +132,18 @@ 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();
|
||||||
|
@ -107,6 +154,8 @@ 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;
|
||||||
|
|
||||||
|
@ -120,7 +169,9 @@ 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)
|
||||||
|
@ -129,17 +180,26 @@ 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, args)));
|
push(frame().program->add(fun->call(loc, m_mod, 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++;
|
||||||
|
@ -180,8 +240,42 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,4 +332,40 @@ 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
27
src/VM.hpp
27
src/VM.hpp
|
@ -14,15 +14,17 @@ 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();
|
explicit VM(Module& mod);
|
||||||
virtual ~VM();
|
virtual ~VM();
|
||||||
|
|
||||||
Frame& frame() { return m_frames.back(); }
|
Frame& frame() { return m_frames.back(); }
|
||||||
|
@ -30,6 +32,12 @@ 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);
|
||||||
|
@ -39,15 +47,24 @@ 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();
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
int opt_index = 0;
|
int opt_index = 0;
|
||||||
|
|
||||||
int c = getopt_long(argc, argv, "h", options, &opt_index);
|
int c = getopt_long(argc, argv, "hd", options, &opt_index);
|
||||||
|
|
||||||
if (c == -1)
|
if (c == -1)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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_BR), G(OP_LOAD_CLOSURE), G(OP_STORE_CLOSURE)
|
||||||
|
|
||||||
#include "commons.hpp"
|
#include "commons.hpp"
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue