Compare commits

..

No commits in common. "12cc10720e442e7d60b0b9bf8df2a8615873cb9a" and "3eefed351c3c4cdc4c6731fb6d5909d4d1da859d" have entirely different histories.

29 changed files with 48 additions and 534 deletions

View File

@ -3,8 +3,4 @@ EXPR ::=
| int | float | bool | string | int | float | bool | string
| ident | ident
| CALL | CALL
| LAMBDA CALL opar ident EXPR* cpar
CALL ::= opar EXPR EXPR* cpar
LAMBDA ::= opar rarrow opar PARAMS cpar BODY cpar
PARAMS ::= ident*
BODY ::= EXPR*

View File

@ -1,24 +0,0 @@
($ a 2)
(:
(assert= 2 a)
($ a 3)
(assert= 3 a)
(:
($ a 7)
(assert= 7 a)
(assert-static-fail ($ a 2))
)
(assert= 3 a)
)
(assert= 2 a)
($ b (: 2 6 9))
(assert= 9 b)
($ c (: 1 2 (: 3 4 (: 5 6 7))))
(assert= 7 c)

View File

@ -1,33 +0,0 @@
;; CALL LAMBDA
;; ===========
(assert= 2 (
(-> (x y) x)
2 3
))
(assert= 3 (
(-> (x y) y)
2 3
))
(assert= 7 (
(-> (x)
($ a 39)
x)
7))
;; CALL IDENT
;; ==========
($ a (-> (x y) y))
(assert= 9 (a 3 9))
;; RETURN LAMBDA
;; =============
($ b (-> () (-> () 32)))
(assert= 32 ((b)))
(assert-static-fail ((b 7)))

View File

@ -1,10 +0,0 @@
(assert-static-fail a)
($ a 12)
(assert-static-fail ($ a 3))
($ b 13)
($ c a)
(assert= 12 a)
(assert= 13 b)
(assert= 12 c)

View File

@ -8,6 +8,4 @@ extern "C" void lib(Module& mod)
mod.register_function("println", fkstd::println); mod.register_function("println", fkstd::println);
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::decl);
} }

View File

@ -1,5 +1,4 @@
#include "macro.hpp" #include "macro.hpp"
#include "src/Compiler.hpp"
namespace fkstd namespace fkstd
{ {
@ -23,43 +22,4 @@ namespace fkstd
ss << "assertion failed"; ss << "assertion failed";
node->loc().error<assert_error>(LOG_ERROR, ss.str()); node->loc().error<assert_error>(LOG_ERROR, ss.str());
} }
void decl(Compiler& compiler,
std::shared_ptr<Node> node,
std::shared_ptr<Program> program)
{
static addr_t addr = 0;
addr++;
std::string ident = node->child(1)->repr();
auto rhs = node->child(2);
compiler.compile_prog(rhs, program);
auto entry = compiler.sym()->declare_local(ident,
addr,
node->loc())
.set_node(rhs);
program->add(OP_STORE_LOCAL, addr);
}
void block(Compiler& compiler,
std::shared_ptr<Node> node,
std::shared_ptr<Program> program)
{
compiler.sym()->enter_scope();
for (size_t i=1; i<node->size(); i++)
{
compiler.compile_prog(node->child(i), program);
if (i != node->size() - 1)
{
program->add(OP_POP);
}
}
compiler.sym()->leave_scope();
}
} }

View File

@ -7,14 +7,6 @@ namespace fkstd
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);
void decl(Compiler& compiler,
std::shared_ptr<Node> node,
std::shared_ptr<Program> program);
void block(Compiler& compiler,
std::shared_ptr<Node> node,
std::shared_ptr<Program> program);
} }
#endif #endif

View File

@ -29,7 +29,6 @@ fakir_cpp = [
'src/Parser.cpp', 'src/Parser.cpp',
'src/Constant.cpp', 'src/Constant.cpp',
'src/NativeFunction.cpp', 'src/NativeFunction.cpp',
'src/Lambda.cpp',
'src/NativeMacro.cpp', 'src/NativeMacro.cpp',
'src/SymTable.cpp', 'src/SymTable.cpp',
'src/SymEntry.cpp', 'src/SymEntry.cpp',
@ -54,7 +53,6 @@ fakir_hpp = [
'src/Program.hpp', 'src/Program.hpp',
'src/Module.hpp', 'src/Module.hpp',
'src/NativeFunction.hpp', 'src/NativeFunction.hpp',
'src/Lambda.hpp',
'src/NativeMacro.hpp', 'src/NativeMacro.hpp',
'src/opcodes.hpp', 'src/opcodes.hpp',
'src/commons.hpp', 'src/commons.hpp',

View File

@ -1,5 +1,4 @@
#include "Compiler.hpp" #include "Compiler.hpp"
#include "Lambda.hpp"
namespace fk namespace fk
{ {
@ -38,48 +37,6 @@ namespace fk
} }
} break; } break;
case NODE_BODY: {
for (size_t i=0; i<node->size(); i++)
{
compile_prog(node->child(i), prog);
if (i != node->size() - 1)
{
prog->add(OP_POP);
}
}
} break;
case NODE_LAMBDA: {
auto params = node->child(0);
auto body = node->child(1);
m_sym->enter_scope(node);
for (size_t i=0; i<params->size(); i++)
{
std::string ident = params->child(i)->repr();
m_sym->declare_local(ident, i, node->loc());
}
Compiler compiler {m_sym};
for (auto e: m_macros)
{
compiler.add_macro(e.first, e.second);
}
auto program = compiler.compile(body);
program->add(OP_RET);
m_sym->leave_scope();
auto constant = std::make_shared<Constant>(TYPE_PROGRAM,
program,
node->loc());
prog->load_const(constant);
prog->add(OP_MAKE_FUNCTION, params->size());
} break;
case NODE_CALL: { case NODE_CALL: {
std::string ident = node->child(0)->repr(); std::string ident = node->child(0)->repr();
@ -96,37 +53,7 @@ namespace fk
compile_prog(node->child(i), prog); compile_prog(node->child(i), prog);
} }
if (node->child(0)->type() == NODE_LAMBDA prog->add(OP_CALL_NATIVE, node->size() - 1);
|| node->child(0)->type() == NODE_CALL)
{
prog->add(OP_CALL_REF, node->size() - 1);
}
else if (node->child(0)->type() == NODE_IDENT)
{
if (auto entry = m_sym->find(node->child(0)->repr());
entry && entry->is_global() == false)
{
size_t arity = entry->node()->child(0)->size();
if (arity != node->size() - 1)
{
std::stringstream ss;
ss << "arity mismatch: " << node->child(0)->repr()
<< " expect '"
<< arity
<< "' arguments, got '"
<< node->size() - 1
<< "'";
node->loc().error<compile_error>(LOG_ERROR, ss.str());
}
prog->add(OP_CALL_REF, node->size() - 1);
}
else
{
prog->add(OP_CALL_NATIVE, node->size() - 1);
}
}
} }
} break; } break;
@ -145,13 +72,11 @@ namespace fk
if (!entry->is_global()) if (!entry->is_global())
{ {
prog->add(OP_LOAD_LOCAL, entry->addr()); throw std::runtime_error { "not implemented yet" };
}
else
{
prog->add(OP_LOAD_GLOBAL, entry->addr());
} }
prog->add(OP_LOAD_GLOBAL, entry->addr());
} break; } break;
case NODE_INT: { case NODE_INT: {
@ -189,4 +114,5 @@ namespace fk
} break; } break;
} }
} }
} }

View File

@ -11,18 +11,12 @@ namespace fk
{ {
FK_ERROR(compile_error); FK_ERROR(compile_error);
struct DeclContext {
size_t arity;
};
class Compiler class Compiler
{ {
public: public:
explicit Compiler(std::shared_ptr<SymTable> sym); explicit Compiler(std::shared_ptr<SymTable> sym);
virtual ~Compiler(); virtual ~Compiler();
std::shared_ptr<SymTable> sym() const { return m_sym; }
void add_macro(std::string const& name, void add_macro(std::string const& name,
std::shared_ptr<NativeMacro> macro); std::shared_ptr<NativeMacro> macro);

View File

@ -1,5 +1,4 @@
#include "Constant.hpp" #include "Constant.hpp"
#include "Program.hpp"
namespace fk namespace fk
{ {

View File

@ -9,15 +9,7 @@ namespace fk
{ {
FK_ERROR(constant_error); FK_ERROR(constant_error);
class Program; using constant_t = std::variant<int, float, bool, std::string, size_t>;
using constant_t = std::variant<int,
float,
bool,
std::string,
size_t,
std::shared_ptr<Program>
>;
class Constant class Constant
{ {

View File

@ -1,14 +0,0 @@
#include "Lambda.hpp"
namespace fk
{
/*explicit*/ Lambda::Lambda(std::shared_ptr<Program> program, size_t arity)
: m_program { program }
, m_arity { arity }
{
}
/*virtual*/ Lambda::~Lambda()
{
}
}

View File

@ -1,28 +0,0 @@
#ifndef fk_LAMBDA_HPP
#define fk_LAMBDA_HPP
#include "commons.hpp"
#include "SymTable.hpp"
#include "Program.hpp"
namespace fk
{
class Lambda
{
public:
explicit Lambda(std::shared_ptr<Program> program, size_t arity);
virtual ~Lambda();
size_t arity() const { return m_arity; }
std::shared_ptr<Program> program() const { return m_program; }
std::shared_ptr<SymTable> sym() const { return m_sym; }
private:
std::shared_ptr<Program> m_program;
size_t m_arity;
std::shared_ptr<SymTable> m_sym = std::make_shared<SymTable>();
};
}
#endif

View File

@ -7,7 +7,6 @@ namespace fk
: m_loc { loc } : m_loc { loc }
{ {
std::vector<std::tuple<NodeType, std::string, bool>> text = { std::vector<std::tuple<NodeType, std::string, bool>> text = {
{NODE_RARROW, "->", false},
{NODE_OPAR, "(", false}, {NODE_OPAR, "(", false},
{NODE_CPAR, ")", false}, {NODE_CPAR, ")", false},
{NODE_BOOL, "true", true}, {NODE_BOOL, "true", true},

View File

@ -6,8 +6,7 @@
#define NODE_TYPES(G) \ #define NODE_TYPES(G) \
G(NODE_MODULE), G(NODE_INT), G(NODE_FLOAT), G(NODE_BOOL), G(NODE_STRING),\ G(NODE_MODULE), G(NODE_INT), G(NODE_FLOAT), G(NODE_BOOL), G(NODE_STRING),\
G(NODE_IDENT), G(NODE_OPAR), G(NODE_CPAR), G(NODE_CALL), G(NODE_LAMBDA),\ G(NODE_IDENT), G(NODE_OPAR), G(NODE_CPAR), G(NODE_CALL)
G(NODE_RARROW), G(NODE_PARAMS), G(NODE_BODY)
namespace fk namespace fk
{ {

View File

@ -1,6 +1,5 @@
#include "Parser.hpp" #include "Parser.hpp"
#include "src/Loc.hpp" #include "src/Loc.hpp"
#include "src/Node.hpp"
namespace fk namespace fk
{ {
@ -49,21 +48,12 @@ namespace fk
std::shared_ptr<Node> Parser::parse_expr() std::shared_ptr<Node> Parser::parse_expr()
{ {
if (type_any({ if (type_any({NODE_INT, NODE_FLOAT, NODE_BOOL, NODE_STRING}))
NODE_INT,
NODE_FLOAT,
NODE_BOOL,
NODE_STRING,
NODE_IDENT}))
{ {
return consume(); return consume();
} }
if (type_all({NODE_OPAR, NODE_RARROW})) if (type_is(NODE_OPAR))
{
return parse_lambda();
}
else if (type_is(NODE_OPAR))
{ {
return parse_call(); return parse_call();
} }
@ -82,7 +72,7 @@ namespace fk
{ {
auto node = make_node(NODE_CALL); auto node = make_node(NODE_CALL);
consume(NODE_OPAR); consume(NODE_OPAR);
node->add_child(parse_expr()); node->add_child(consume(NODE_IDENT));
while (type_isnt(NODE_CPAR)) while (type_isnt(NODE_CPAR))
{ {
@ -94,46 +84,6 @@ namespace fk
return node; return node;
} }
std::shared_ptr<Node> Parser::parse_lambda()
{
auto node = make_node(NODE_LAMBDA);
consume(NODE_OPAR);
consume(NODE_RARROW);
consume(NODE_OPAR);
node->add_child(parse_params());
consume(NODE_CPAR);
node->add_child(parse_body());
consume(NODE_CPAR);
return node;
}
std::shared_ptr<Node> Parser::parse_params()
{
auto node = make_node(NODE_PARAMS);
while (type_isnt(NODE_CPAR))
{
node->add_child(consume(NODE_IDENT));
}
return node;
}
std::shared_ptr<Node> Parser::parse_body()
{
auto node = make_node(NODE_BODY);
while (type_isnt(NODE_CPAR))
{
node->add_child(parse_expr());
}
return node;
}
std::shared_ptr<Node> Parser::make_node(NodeType type) std::shared_ptr<Node> Parser::make_node(NodeType type)
{ {
return std::make_shared<Node>(type, "", loc()); return std::make_shared<Node>(type, "", loc());

View File

@ -23,9 +23,6 @@ namespace fk
std::shared_ptr<Node> parse_module(); std::shared_ptr<Node> parse_module();
std::shared_ptr<Node> parse_expr(); std::shared_ptr<Node> parse_expr();
std::shared_ptr<Node> parse_call(); std::shared_ptr<Node> parse_call();
std::shared_ptr<Node> parse_lambda();
std::shared_ptr<Node> parse_params();
std::shared_ptr<Node> parse_body();
std::shared_ptr<Node> make_node(NodeType type); std::shared_ptr<Node> make_node(NodeType type);
Loc loc() const; Loc loc() const;

View File

@ -1,19 +1,14 @@
#include "SymEntry.hpp" #include "SymEntry.hpp"
#include "Node.hpp"
namespace fk namespace fk
{ {
/*explicit*/ SymEntry::SymEntry(std::string const& name, /*explicit*/ SymEntry::SymEntry(std::string const& name,
addr_t addr, addr_t addr,
bool is_global, bool is_global,
int scope,
std::shared_ptr<Node> parent,
Loc const& loc) Loc const& loc)
: m_name { name } : m_name { name }
, m_addr { addr } , m_addr { addr }
, m_is_global { is_global } , m_is_global { is_global }
, m_scope { scope }
, m_parent { parent }
, m_loc { loc } , m_loc { loc }
{ {
} }
@ -25,9 +20,7 @@ namespace fk
std::string SymEntry::string() const std::string SymEntry::string() const
{ {
std::stringstream ss; std::stringstream ss;
ss << m_name << "\t" << m_addr << "\t" << m_is_global << "\t" << m_scope ss << m_name << "\t" << m_addr << "\t" << m_is_global;
<< "\t"
<< (m_parent ? NodeTypeStr[m_parent->type()] + strlen("NODE_") : "");
return ss.str(); return ss.str();
} }
} }

View File

@ -6,35 +6,21 @@
namespace fk namespace fk
{ {
class Node;
class SymEntry class SymEntry
{ {
public: public:
explicit SymEntry(std::string const& name, explicit SymEntry(std::string const& name,
addr_t addr, addr_t addr,
bool is_global, bool is_global,
int scope,
std::shared_ptr<Node> parent,
Loc const& loc); Loc const& loc);
virtual ~SymEntry(); virtual ~SymEntry();
std::string name() const { return m_name; } std::string name() const { return m_name; }
addr_t addr() const { return m_addr; } addr_t addr() const { return m_addr; }
bool is_global() const { return m_is_global; } bool is_global() const { return m_is_global; }
int scope() const { return m_scope; }
std::shared_ptr<Node> parent() const { return m_parent; }
std::shared_ptr<Node> node() const { return m_node; }
Loc loc() const { return m_loc; } Loc loc() const { return m_loc; }
size_t arity() const { return m_arity; }
SymEntry& set_global(bool global) { m_is_global = global; return *this; } void set_global(bool global) { m_is_global = global; }
SymEntry& set_addr(addr_t addr) { m_addr = addr; return *this; }
SymEntry& set_arity(size_t arity) { m_arity = arity; return *this; }
SymEntry& set_parent(std::shared_ptr<Node> parent)
{ m_parent = parent; return *this; }
SymEntry& set_node(std::shared_ptr<Node> node)
{ m_node = node; return *this; }
std::string string() const; std::string string() const;
@ -42,11 +28,7 @@ namespace fk
std::string m_name; std::string m_name;
addr_t m_addr; addr_t m_addr;
bool m_is_global = false; bool m_is_global = false;
int m_scope;
std::shared_ptr<Node> m_parent;
std::shared_ptr<Node> m_node;
Loc m_loc; Loc m_loc;
size_t m_arity = 0;
}; };
} }

View File

@ -1,6 +1,5 @@
#include "SymTable.hpp" #include "SymTable.hpp"
#include "src/Loc.hpp" #include "src/Loc.hpp"
#include "Node.hpp"
namespace fk namespace fk
{ {
@ -12,15 +11,13 @@ namespace fk
{ {
} }
SymEntry& SymTable::declare_local(std::string const& name, void SymTable::declare_local(std::string const& name,
addr_t addr, addr_t addr,
Loc const& loc) Loc const& loc)
{ {
auto entry = find(name); auto entry = find(name);
if (entry && entry->scope() == m_scope if (entry)
&& ((entry->parent() == nullptr && m_parents.empty())
|| entry->parent() == m_parents.back()))
{ {
std::stringstream ss; std::stringstream ss;
ss << "cannot declare existing variable '" ss << "cannot declare existing variable '"
@ -30,44 +27,28 @@ namespace fk
entry->loc().error<symbol_error>(LOG_ERROR, ss.str()); entry->loc().error<symbol_error>(LOG_ERROR, ss.str());
} }
SymEntry e {name, m_entries.push_back(SymEntry {name, addr, false, loc});
addr,
false,
m_scope,
m_parents.empty() ?
nullptr : m_parents.back(),
loc};
m_entries.push_back(e);
return m_entries.back();
} }
SymEntry& SymTable::declare_global(std::string const& name, void SymTable::declare_global(std::string const& name,
addr_t addr, addr_t addr,
Loc const& loc) Loc const& loc)
{ {
return declare_local(name, addr, loc).set_global(true); declare_local(name, addr, loc);
m_entries.back().set_global(true);
} }
std::optional<SymEntry> SymTable::find(std::string const& name) std::optional<SymEntry> SymTable::find(std::string const& name)
{ {
std::optional<SymEntry> result;
for (auto& entry: m_entries) for (auto& entry: m_entries)
{ {
if (entry.name() == name 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; return entry;
} }
} }
return result; return std::nullopt;
} }
std::string SymTable::string() const std::string SymTable::string() const
@ -75,9 +56,6 @@ namespace fk
std::stringstream ss; std::stringstream ss;
ss << "======== SymTable ========\n"; ss << "======== SymTable ========\n";
ss << std::setw(8) << std::left;
ss << "name\taddr\tglobal\tscope\tfunction" << std::endl;
for (auto const& entry: m_entries) for (auto const& entry: m_entries)
{ {
ss << entry.string() << std::endl; ss << entry.string() << std::endl;
@ -85,16 +63,4 @@ namespace fk
return ss.str(); return ss.str();
} }
void SymTable::enter_scope(std::shared_ptr<Node> parent)
{
m_scope++;
m_parents.push_back(parent);
}
void SymTable::leave_scope()
{
m_scope--;
m_parents.pop_back();
}
} }

View File

@ -14,25 +14,20 @@ namespace fk
explicit SymTable(); explicit SymTable();
virtual ~SymTable(); virtual ~SymTable();
SymEntry& declare_local(std::string const& name, void declare_local(std::string const& name,
addr_t addr, addr_t addr,
Loc const& loc); Loc const& loc);
SymEntry& declare_global(std::string const& name, void declare_global(std::string const& name,
addr_t addr, addr_t addr,
Loc const& loc); Loc const& loc);
std::optional<SymEntry> find(std::string const& name); std::optional<SymEntry> find(std::string const& name);
std::string string() const; std::string string() const;
void enter_scope(std::shared_ptr<Node> parent=nullptr);
void leave_scope();
private: private:
std::vector<SymEntry> m_entries; std::vector<SymEntry> m_entries;
int m_scope;
std::vector<std::shared_ptr<Node>> m_parents;
}; };
} }

View File

@ -1,6 +1,4 @@
#include "VM.hpp" #include "VM.hpp"
#include "src/opcodes.hpp"
#include <memory>
namespace fk namespace fk
{ {
@ -27,43 +25,7 @@ namespace fk
switch (instr.opcode) switch (instr.opcode)
{ {
case OP_MAKE_FUNCTION: { case OP_CALL_NATIVE: {
auto p = frame().program->get_const(pop());
auto prog = std::get<std::shared_ptr<Program>>(p->value());
auto lambda = std::make_shared<Lambda>(prog, instr.param);
addr_t addr = store_global(lambda);
auto ref = std::make_shared<Constant>(TYPE_REF, addr, p->loc());
push(frame().program->add(ref));
m_pc++;
} break;
case OP_RET: {
m_pc = m_frames.back().ret_addr;
size_t sz = m_frames.back().stack_sz;
std::optional<addr_t> ret;
while (m_stack.size() > sz)
{
if (!ret)
{
ret = pop();
}
else
{
pop();
}
}
auto value = m_frames.back().program->get_const(*ret);
m_frames.pop_back();
push(frame().program->add(value));
m_pc++;
} break;
case OP_CALL_REF: {
std::vector<std::shared_ptr<Constant>> args; std::vector<std::shared_ptr<Constant>> args;
for (size_t i=0; i<instr.param; i++) for (size_t i=0; i<instr.param; i++)
@ -72,36 +34,6 @@ namespace fk
frame().program->get_const(pop())); frame().program->get_const(pop()));
} }
auto ref_val = frame().program->get_const(pop());
addr_t ref = std::get<addr_t>(ref_val->value());
auto lambda = std::get<std::shared_ptr<Lambda>>(load_global(ref));
Frame frame;
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]);
}
m_pc = 0;
} break;
case OP_CALL_NATIVE: {
std::vector<std::shared_ptr<Constant>> args;
for (size_t i=0; i<instr.param; i++)
{
addr_t addr = pop();
args.insert(std::begin(args),
frame().program->get_const(addr));
}
auto ref = std::get<size_t>(frame().program auto ref = std::get<size_t>(frame().program
->get_const(pop())->value()); ->get_const(pop())->value());
auto fun = std::get<std::shared_ptr<NativeFunction>> auto fun = std::get<std::shared_ptr<NativeFunction>>
@ -112,21 +44,6 @@ namespace fk
m_pc++; m_pc++;
} break; } break;
case OP_LOAD_LOCAL: {
auto value = frame().locals[instr.param];
assert(value);
push(frame().program->add(value));
m_pc++;
} break;
case OP_STORE_LOCAL: {
auto value = frame().program->get_const(top());
assert(value);
frame().locals[instr.param] = value;
m_pc++;
} break;
case OP_LOAD_GLOBAL: { case OP_LOAD_GLOBAL: {
auto ref = std::make_shared<Constant>(TYPE_REF, auto ref = std::make_shared<Constant>(TYPE_REF,
(size_t) instr.param, (size_t) instr.param,
@ -172,16 +89,6 @@ namespace fk
return addr; return addr;
} }
std::shared_ptr<Constant> VM::load_local(addr_t addr)
{
return frame().locals[addr];
}
void VM::store_local(addr_t addr, std::shared_ptr<Constant> constant)
{
frame().locals[addr] = constant;
}
std::string VM::string() const std::string VM::string() const
{ {
std::stringstream ss; std::stringstream ss;

View File

@ -4,19 +4,13 @@
#include "commons.hpp" #include "commons.hpp"
#include "Program.hpp" #include "Program.hpp"
#include "NativeFunction.hpp" #include "NativeFunction.hpp"
#include "Lambda.hpp"
namespace fk namespace fk
{ {
using global_t = std::variant<std::shared_ptr<NativeFunction>, using global_t = std::variant<std::shared_ptr<NativeFunction>>;
std::shared_ptr<Lambda>
>;
struct Frame { struct Frame {
std::shared_ptr<Program> program; std::shared_ptr<Program> program;
addr_t ret_addr;
size_t stack_sz;
std::unordered_map<addr_t, std::shared_ptr<Constant>> locals;
}; };
class VM class VM
@ -25,7 +19,7 @@ namespace fk
explicit VM(); explicit VM();
virtual ~VM(); virtual ~VM();
Frame& frame() { return m_frames.back(); } Frame frame() const { return m_frames.back(); }
void mount(std::shared_ptr<Program> program); void mount(std::shared_ptr<Program> program);
void run(); void run();
@ -34,9 +28,6 @@ namespace fk
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);
std::shared_ptr<Constant> load_local(addr_t addr);
void store_local(addr_t addr, std::shared_ptr<Constant> constant);
std::string string() const; std::string string() const;
private: private:

View File

@ -2,8 +2,7 @@
#define fk_OPCODES_HPP #define fk_OPCODES_HPP
#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_MAKE_FUNCTION), G(OP_CALL_REF), G(OP_RET)
#include "commons.hpp" #include "commons.hpp"

View File

@ -4,7 +4,7 @@
#include "commons.hpp" #include "commons.hpp"
#define TYPES(G) G(TYPE_INT), G(TYPE_FLOAT), G(TYPE_BOOL), G(TYPE_STRING), \ #define TYPES(G) G(TYPE_INT), G(TYPE_FLOAT), G(TYPE_BOOL), G(TYPE_STRING), \
G(TYPE_REF), G(TYPE_PROGRAM) G(TYPE_REF)
namespace fk namespace fk
{ {

View File

@ -88,12 +88,3 @@ TEST_CASE_METHOD(LexerTest, "Lexer_parenthesis")
test_next("CPAR"); test_next("CPAR");
test_end(); test_end();
} }
TEST_CASE_METHOD(LexerTest, "Lexer_lambda")
{
m_lexer.scan(" (->) ");
test_next("OPAR");
test_next("RARROW");
test_next("CPAR");
test_end();
}

View File

@ -35,15 +35,3 @@ TEST_CASE_METHOD(ParserTest, "Parser_call")
test_parse("MODULE(CALL(IDENT[bim],INT[2],STRING['3'],BOOL[false]))", test_parse("MODULE(CALL(IDENT[bim],INT[2],STRING['3'],BOOL[false]))",
" (bim 2 '3' false) "); " (bim 2 '3' false) ");
} }
TEST_CASE_METHOD(ParserTest, "Parser_lambda")
{
test_parse("MODULE(LAMBDA(PARAMS,BODY))",
" (-> ()) ");
test_parse("MODULE(LAMBDA(PARAMS(IDENT[x]),BODY))",
" (-> (x)) ");
test_parse("MODULE(LAMBDA(PARAMS(IDENT[x],IDENT[y]),BODY(INT[7])))",
" (-> (x y) 7) ");
}

View File

@ -14,5 +14,16 @@ protected:
TEST_CASE_METHOD(SymTableTest, "SymTable_declare_var") TEST_CASE_METHOD(SymTableTest, "SymTable_declare_var")
{ {
REQUIRE(std::nullopt == m_sym.find("hello"));
m_sym.declare_local("hello", 404, m_loc);
auto entry = m_sym.find("hello");
REQUIRE(std::nullopt != entry);
REQUIRE("hello" == entry->name());
REQUIRE(404 == entry->addr());
REQUIRE(false == entry->is_global());
REQUIRE_THROWS_AS(m_sym.declare_local("hello", 407, m_loc),
fk::symbol_error);
} }