Compare commits
2 Commits
22131c2cf0
...
6df8167669
Author | SHA1 | Date |
---|---|---|
bog | 6df8167669 | |
bog | 5d975eafdf |
|
@ -4,7 +4,17 @@ EXPR ::=
|
|||
| ident
|
||||
| CALL
|
||||
| LAMBDA
|
||||
| FUNDECL
|
||||
| VARDECL
|
||||
| NS
|
||||
| IMPORT
|
||||
CALL ::= opar EXPR EXPR* cpar
|
||||
LAMBDA ::= opar rarrow opar PARAMS cpar BODY cpar
|
||||
PARAMS ::= ident*
|
||||
BODY ::= EXPR*
|
||||
FUNDECL ::=
|
||||
| opar decl opar ident PARAMS cpar BODY cpar
|
||||
VARDECL ::= opar decl ident EXPR cpar
|
||||
NS ::= ident ns ident
|
||||
IMPORT ::= opar import string cpar
|
||||
SHORT_IMPORT ::= opar decl import ident string? cpar
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
($ (f x y) (* x y))
|
||||
|
||||
(assert= 42 (f 6 7))
|
|
@ -0,0 +1,4 @@
|
|||
($ a (@ './mod2'))
|
||||
|
||||
(assert= 42 a::var)
|
||||
(assert= 6 (a::fun 3))
|
|
@ -0,0 +1,2 @@
|
|||
($ var 42)
|
||||
($ (fun x) (* 2 x))
|
|
@ -4,8 +4,6 @@
|
|||
|
||||
namespace fkstd
|
||||
{
|
||||
STDRET set(Loc loc, Module& mod, STDARGS args);
|
||||
|
||||
STDRET assert_eq(Loc loc, Module& mod, STDARGS args);
|
||||
STDRET println(Loc loc, Module& mod, STDARGS args);
|
||||
|
||||
|
|
|
@ -2,11 +2,8 @@
|
|||
#include "fun.hpp"
|
||||
#include "macro.hpp"
|
||||
|
||||
Module* _module;
|
||||
|
||||
extern "C" void lib(Module& mod)
|
||||
{
|
||||
_module = &mod;
|
||||
mod.register_function("assert=", fkstd::assert_eq);
|
||||
mod.register_function("println", fkstd::println);
|
||||
mod.register_function("+", fkstd::add_int);
|
||||
|
@ -25,6 +22,5 @@ extern "C" void lib(Module& mod)
|
|||
mod.register_macro("!", fkstd::set_addr);
|
||||
mod.register_macro("assert-static-fail", fkstd::assert_static_fail);
|
||||
mod.register_macro(":", fkstd::block);
|
||||
mod.register_macro("$", fkstd::decl);
|
||||
mod.register_macro("if", fkstd::if_macro);
|
||||
}
|
||||
|
|
114
src/Compiler.cpp
114
src/Compiler.cpp
|
@ -1,10 +1,14 @@
|
|||
#include "Compiler.hpp"
|
||||
#include "Module.hpp"
|
||||
#include "Lambda.hpp"
|
||||
#include "commons.hpp"
|
||||
|
||||
namespace fk
|
||||
{
|
||||
/*explicit*/ Compiler::Compiler(std::shared_ptr<SymTable> sym)
|
||||
: m_sym { sym }
|
||||
/*explicit*/ Compiler::Compiler(Module& mod,
|
||||
std::shared_ptr<SymTable> sym)
|
||||
: m_mod { mod }
|
||||
, m_sym { sym }
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -18,6 +22,24 @@ namespace fk
|
|||
m_macros[name] = macro;
|
||||
}
|
||||
|
||||
std::shared_ptr<NativeMacro> Compiler::get_macro(std::string const& name)
|
||||
{
|
||||
assert(m_macros.find(name) != std::end(m_macros));
|
||||
return m_macros[name];
|
||||
}
|
||||
|
||||
bool Compiler::has_macro(std::string const& name) const
|
||||
{
|
||||
return m_macros.find(name) != std::end(m_macros);
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, std::shared_ptr<NativeMacro>>
|
||||
Compiler::macros()
|
||||
{
|
||||
return m_macros;
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<Program> Compiler::compile(std::shared_ptr<Node> node)
|
||||
{
|
||||
auto prog = std::make_shared<Program>();
|
||||
|
@ -50,6 +72,73 @@ namespace fk
|
|||
}
|
||||
} break;
|
||||
|
||||
case NODE_VARDECL: {
|
||||
m_addr++;
|
||||
|
||||
std::string ident = node->child(0)->repr();
|
||||
auto rhs = node->child(1);
|
||||
|
||||
push_decl(ident);
|
||||
compile_prog(rhs, prog);
|
||||
pop_decl();
|
||||
|
||||
auto entry = sym()->declare_local(ident,
|
||||
m_addr,
|
||||
node->loc())
|
||||
.set_node(rhs);
|
||||
|
||||
prog->add(OP_STORE_LOCAL, m_addr);
|
||||
|
||||
} break;
|
||||
|
||||
case NODE_NS: {
|
||||
auto mod = node->child(0);
|
||||
auto var = node->child(1);
|
||||
|
||||
if (has_macro(var->repr()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
prog->load_const(std::make_shared<Constant>(TYPE_STRING,
|
||||
var->repr(),
|
||||
node->loc()));
|
||||
|
||||
compile_prog(mod, prog);
|
||||
|
||||
prog->add(OP_LOAD_MOD);
|
||||
|
||||
} break;
|
||||
|
||||
case NODE_IMPORT: {
|
||||
std::string val = node->child(0)->repr();
|
||||
|
||||
std::string path_str = val.substr(1, val.size() - 2);
|
||||
std::filesystem::path path = path_str;
|
||||
|
||||
if (path_str[0] == '.')
|
||||
{
|
||||
if (!path.has_extension())
|
||||
{
|
||||
path += ".fk";
|
||||
}
|
||||
|
||||
auto res = std::make_shared<Constant>
|
||||
(TYPE_STRING, path.string(), node->loc());
|
||||
prog->load_const(res);
|
||||
prog->add(OP_IMPORT);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto res = std::make_shared<Constant>
|
||||
(TYPE_STRING, path.string(),
|
||||
node->loc());
|
||||
|
||||
prog->load_const(res);
|
||||
prog->add(OP_IMPORT_SYS);
|
||||
}
|
||||
} break;
|
||||
|
||||
case NODE_LAMBDA: {
|
||||
auto params = node->child(0);
|
||||
auto body = node->child(1);
|
||||
|
@ -70,7 +159,7 @@ namespace fk
|
|||
|
||||
m_sym->declare_local(func_name, params->size(), node->loc());
|
||||
|
||||
Compiler compiler {m_sym};
|
||||
Compiler compiler {m_mod, m_sym};
|
||||
for (auto e: m_macros)
|
||||
{
|
||||
compiler.add_macro(e.first, e.second);
|
||||
|
@ -92,13 +181,24 @@ namespace fk
|
|||
case NODE_CALL: {
|
||||
std::string ident = node->child(0)->repr();
|
||||
|
||||
|
||||
if (auto itr=m_macros.find(ident);
|
||||
itr != std::end(m_macros))
|
||||
{
|
||||
auto macro = itr->second;
|
||||
macro->call(*this, node, prog);
|
||||
}
|
||||
else if (node->child(0)->type() == NODE_NS
|
||||
&& has_macro(node->child(0)->child(1)->repr()))
|
||||
{
|
||||
std::string name = node->child(0)->child(1)->repr();
|
||||
|
||||
if (auto itr=m_macros.find(name);
|
||||
itr != std::end(m_macros))
|
||||
{
|
||||
auto macro = itr->second;
|
||||
macro->call(*this, node, prog);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i=0; i<node->size(); i++)
|
||||
|
@ -106,8 +206,10 @@ namespace fk
|
|||
compile_prog(node->child(i), prog);
|
||||
}
|
||||
|
||||
|
||||
if (node->child(0)->type() == NODE_LAMBDA
|
||||
|| node->child(0)->type() == NODE_CALL)
|
||||
|| node->child(0)->type() == NODE_CALL
|
||||
|| node->child(0)->type() == NODE_NS)
|
||||
{
|
||||
prog->add(OP_CALL_REF, node->size() - 1);
|
||||
}
|
||||
|
@ -137,7 +239,7 @@ namespace fk
|
|||
}
|
||||
else
|
||||
{
|
||||
prog->add(OP_CALL_NATIVE, node->size() - 1);
|
||||
prog->add(OP_CALL_REF, node->size() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,10 +15,12 @@ namespace fk
|
|||
size_t arity;
|
||||
};
|
||||
|
||||
class Module;
|
||||
|
||||
class Compiler
|
||||
{
|
||||
public:
|
||||
explicit Compiler(std::shared_ptr<SymTable> sym);
|
||||
explicit Compiler(Module& mod, std::shared_ptr<SymTable> sym);
|
||||
virtual ~Compiler();
|
||||
|
||||
std::shared_ptr<SymTable> sym() const { return m_sym; }
|
||||
|
@ -26,6 +28,14 @@ namespace fk
|
|||
void add_macro(std::string const& name,
|
||||
std::shared_ptr<NativeMacro> macro);
|
||||
|
||||
std::shared_ptr<NativeMacro> get_macro(std::string const& name);
|
||||
|
||||
bool has_macro(std::string const& name) const;
|
||||
|
||||
std::unordered_map<std::string, std::shared_ptr<NativeMacro>>
|
||||
macros();
|
||||
|
||||
|
||||
std::shared_ptr<Program> compile(std::shared_ptr<Node> node);
|
||||
|
||||
void compile_prog(std::shared_ptr<Node> node,
|
||||
|
@ -35,6 +45,8 @@ namespace fk
|
|||
void pop_decl();
|
||||
|
||||
private:
|
||||
Module& m_mod;
|
||||
addr_t m_addr = 0;
|
||||
std::shared_ptr<SymTable> m_sym;
|
||||
std::vector<std::string> m_decl_stack;
|
||||
std::unordered_map<std::string,
|
||||
|
|
|
@ -7,6 +7,9 @@ namespace fk
|
|||
: m_loc { loc }
|
||||
{
|
||||
std::vector<std::tuple<NodeType, std::string, bool>> text = {
|
||||
{NODE_IMPORT, "@", false},
|
||||
{NODE_DECL, "$", false},
|
||||
{NODE_NS, "::", false},
|
||||
{NODE_RARROW, "->", false},
|
||||
{NODE_OPAR, "(", false},
|
||||
{NODE_CPAR, ")", false},
|
||||
|
@ -255,8 +258,16 @@ namespace fk
|
|||
std::string repr;
|
||||
|
||||
while (cursor < m_source.size()
|
||||
&& !is_sep(cursor))
|
||||
&& !is_sep(cursor)
|
||||
&& m_source[cursor])
|
||||
{
|
||||
if (cursor + 1 < m_source.size()
|
||||
&& m_source[cursor] == ':'
|
||||
&& m_source[cursor + 1] == ':')
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
repr += m_source[cursor];
|
||||
cursor++;
|
||||
}
|
||||
|
|
|
@ -15,11 +15,27 @@ namespace fk
|
|||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<Module> Module::get_mod(std::string const& name)
|
||||
{
|
||||
assert(m_native_modules.find(name) != std::end(m_native_modules));
|
||||
return m_native_modules[name];
|
||||
}
|
||||
|
||||
void Module::build()
|
||||
{
|
||||
import_std();
|
||||
m_source = load_sources();
|
||||
m_ast = m_parser->parse(m_source);
|
||||
|
||||
// Add natives macros before compilation
|
||||
for (auto mod: m_native_modules)
|
||||
{
|
||||
for (auto e: mod.second->compiler()->macros())
|
||||
{
|
||||
m_compiler->add_macro(e.first, e.second);
|
||||
}
|
||||
}
|
||||
|
||||
m_program = m_compiler->compile(m_ast);
|
||||
|
||||
m_vm->mount(m_program);
|
||||
|
@ -43,6 +59,14 @@ namespace fk
|
|||
f(*this);
|
||||
}
|
||||
|
||||
std::shared_ptr<Module> Module::register_module(std::string const& name)
|
||||
{
|
||||
auto mod = std::make_shared<Module>(name);
|
||||
m_native_modules[name] = mod;
|
||||
|
||||
return mod;
|
||||
}
|
||||
|
||||
void Module::register_function(std::string const& name, native_t native)
|
||||
{
|
||||
auto fun = std::make_shared<NativeFunction>(native);
|
||||
|
|
|
@ -18,15 +18,20 @@ namespace fk
|
|||
explicit Module(std::filesystem::path source_path);
|
||||
virtual ~Module();
|
||||
|
||||
std::shared_ptr<Compiler> compiler() const { return m_compiler; }
|
||||
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; }
|
||||
|
||||
std::shared_ptr<Module> get_mod(std::string const& name);
|
||||
|
||||
void build();
|
||||
|
||||
void import_std();
|
||||
void import_library(std::filesystem::path lib_path);
|
||||
|
||||
std::shared_ptr<Module> register_module(std::string const& name);
|
||||
|
||||
void register_function(std::string const& name, native_t native);
|
||||
void register_macro(std::string const& name, macro_t macro);
|
||||
|
||||
|
@ -37,10 +42,13 @@ namespace fk
|
|||
std::shared_ptr<Lexer> m_lexer = std::make_shared<Lexer>(m_loc);
|
||||
std::shared_ptr<Parser> m_parser = std::make_shared<Parser>(*m_lexer);
|
||||
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>(*this,
|
||||
m_sym);
|
||||
std::shared_ptr<Node> m_ast;
|
||||
std::shared_ptr<VM> m_vm = std::make_shared<VM>(*this);
|
||||
std::shared_ptr<Program> m_program = std::make_shared<Program>();
|
||||
std::unordered_map<std::string, std::shared_ptr<Module>> m_native_modules;
|
||||
|
||||
std::string load_sources();
|
||||
};
|
||||
}
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
#define NODE_TYPES(G) \
|
||||
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_RARROW), G(NODE_PARAMS), G(NODE_BODY)
|
||||
G(NODE_RARROW), G(NODE_PARAMS), G(NODE_BODY), G(NODE_NS), G(NODE_IMPORT),\
|
||||
G(NODE_VARDECL), G(NODE_DECL)
|
||||
|
||||
namespace fk
|
||||
{
|
||||
|
|
117
src/Parser.cpp
117
src/Parser.cpp
|
@ -1,6 +1,7 @@
|
|||
#include "Parser.hpp"
|
||||
#include "src/Loc.hpp"
|
||||
#include "src/Node.hpp"
|
||||
#include <memory>
|
||||
|
||||
namespace fk
|
||||
{
|
||||
|
@ -49,6 +50,24 @@ namespace fk
|
|||
|
||||
std::shared_ptr<Node> Parser::parse_expr()
|
||||
{
|
||||
|
||||
if (type_all({NODE_IDENT, NODE_NS}))
|
||||
{
|
||||
return parse_ns();
|
||||
}
|
||||
|
||||
if (type_all({NODE_OPAR, NODE_DECL, NODE_IMPORT,
|
||||
NODE_IDENT, NODE_STRING, NODE_CPAR})
|
||||
|| type_all({NODE_OPAR, NODE_DECL, NODE_IMPORT,
|
||||
NODE_IDENT, NODE_CPAR}))
|
||||
{
|
||||
return parse_short_import();
|
||||
}
|
||||
else if (type_all({NODE_OPAR, NODE_IMPORT}))
|
||||
{
|
||||
return parse_import();
|
||||
}
|
||||
|
||||
if (type_any({
|
||||
NODE_INT,
|
||||
NODE_FLOAT,
|
||||
|
@ -59,7 +78,15 @@ namespace fk
|
|||
return consume();
|
||||
}
|
||||
|
||||
if (type_all({NODE_OPAR, NODE_RARROW}))
|
||||
if (type_all({NODE_OPAR, NODE_DECL, NODE_OPAR, NODE_IDENT}))
|
||||
{
|
||||
return parse_fundecl();
|
||||
}
|
||||
else if (type_all({NODE_OPAR, NODE_DECL}))
|
||||
{
|
||||
return parse_vardecl();
|
||||
}
|
||||
else if (type_all({NODE_OPAR, NODE_RARROW}))
|
||||
{
|
||||
return parse_lambda();
|
||||
}
|
||||
|
@ -134,6 +161,94 @@ namespace fk
|
|||
return node;
|
||||
}
|
||||
|
||||
std::shared_ptr<Node> Parser::parse_fundecl()
|
||||
{
|
||||
consume(NODE_OPAR);
|
||||
auto dollar = consume(NODE_DECL);
|
||||
|
||||
consume(NODE_OPAR);
|
||||
auto ident = consume(NODE_IDENT);
|
||||
auto params = parse_params();
|
||||
consume(NODE_CPAR);
|
||||
|
||||
auto body = parse_body();
|
||||
consume(NODE_CPAR);
|
||||
|
||||
auto res = make_node(NODE_VARDECL);
|
||||
res->add_child(ident);
|
||||
|
||||
auto lambda = make_node(NODE_LAMBDA);
|
||||
lambda->add_child(params);
|
||||
lambda->add_child(body);
|
||||
res->add_child(lambda);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
std::shared_ptr<Node> Parser::parse_vardecl()
|
||||
{
|
||||
auto node = make_node(NODE_VARDECL);
|
||||
consume(NODE_OPAR);
|
||||
consume(NODE_DECL);
|
||||
|
||||
node->add_child(consume(NODE_IDENT));
|
||||
node->add_child(parse_expr());
|
||||
consume(NODE_CPAR);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
std::shared_ptr<Node> Parser::parse_ns()
|
||||
{
|
||||
auto ns = make_node(NODE_NS);
|
||||
ns->add_child(consume(NODE_IDENT));
|
||||
consume(NODE_NS);
|
||||
ns->add_child(consume(NODE_IDENT));
|
||||
return ns;
|
||||
}
|
||||
|
||||
std::shared_ptr<Node> Parser::parse_import()
|
||||
{
|
||||
consume(NODE_OPAR);
|
||||
auto node = consume(NODE_IMPORT);
|
||||
node->add_child(consume(NODE_STRING));
|
||||
consume(NODE_CPAR);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
std::shared_ptr<Node> Parser::parse_short_import()
|
||||
{
|
||||
consume(NODE_OPAR);
|
||||
consume(NODE_DECL);
|
||||
|
||||
auto node_import = consume(NODE_IMPORT);
|
||||
auto ident = consume(NODE_IDENT);
|
||||
std::shared_ptr<Node> str;
|
||||
|
||||
if (type_is(NODE_CPAR))
|
||||
{
|
||||
str = std::make_shared<Node>(NODE_STRING,
|
||||
"'" + ident->repr() + "'",
|
||||
ident->loc());
|
||||
}
|
||||
else
|
||||
{
|
||||
str = consume(NODE_STRING);
|
||||
}
|
||||
|
||||
consume(NODE_CPAR);
|
||||
|
||||
auto vardecl = make_node(NODE_VARDECL);
|
||||
vardecl->add_child(ident);
|
||||
|
||||
auto imp = make_node(NODE_IMPORT);
|
||||
imp->add_child(str);
|
||||
vardecl->add_child(imp);
|
||||
|
||||
return vardecl;
|
||||
}
|
||||
|
||||
std::shared_ptr<Node> Parser::make_node(NodeType type)
|
||||
{
|
||||
return std::make_shared<Node>(type, "", loc());
|
||||
|
|
|
@ -26,6 +26,11 @@ namespace fk
|
|||
std::shared_ptr<Node> parse_lambda();
|
||||
std::shared_ptr<Node> parse_params();
|
||||
std::shared_ptr<Node> parse_body();
|
||||
std::shared_ptr<Node> parse_fundecl();
|
||||
std::shared_ptr<Node> parse_vardecl();
|
||||
std::shared_ptr<Node> parse_ns();
|
||||
std::shared_ptr<Node> parse_import();
|
||||
std::shared_ptr<Node> parse_short_import();
|
||||
|
||||
std::shared_ptr<Node> make_node(NodeType type);
|
||||
Loc loc() const;
|
||||
|
|
144
src/VM.cpp
144
src/VM.cpp
|
@ -1,5 +1,7 @@
|
|||
#include "VM.hpp"
|
||||
#include "src/opcodes.hpp"
|
||||
#include "opcodes.hpp"
|
||||
#include "Module.hpp"
|
||||
#include "src/NativeFunction.hpp"
|
||||
#include <memory>
|
||||
|
||||
namespace fk
|
||||
|
@ -29,6 +31,103 @@ namespace fk
|
|||
|
||||
switch (instr.opcode)
|
||||
{
|
||||
case OP_IMPORT: {
|
||||
auto path_val = frame().program->get_const(pop());
|
||||
std::filesystem::path path =
|
||||
std::get<std::string>(path_val->value());
|
||||
|
||||
auto mod = std::make_shared<Module>(path);
|
||||
mod->build();
|
||||
|
||||
addr_t addr = store_global(mod);
|
||||
auto res = std::make_shared<Constant>(TYPE_REF, addr,
|
||||
path_val->loc());
|
||||
push(frame().program->add(res));
|
||||
m_pc++;
|
||||
|
||||
} break;
|
||||
|
||||
case OP_IMPORT_SYS: {
|
||||
auto path_val = frame().program->get_const(pop());
|
||||
|
||||
std::filesystem::path path =
|
||||
std::get<std::string>(path_val->value());
|
||||
|
||||
auto mod = m_mod.get_mod(path);
|
||||
|
||||
addr_t addr = store_global(mod);
|
||||
auto res = std::make_shared<Constant>(TYPE_REF, addr,
|
||||
path_val->loc());
|
||||
push(frame().program->add(res));
|
||||
|
||||
m_pc++;
|
||||
} break;
|
||||
|
||||
case OP_LOAD_MOD: {
|
||||
addr_t mod_addr = pop();
|
||||
auto mod_val = frame().program->get_const(mod_addr);
|
||||
size_t mod_ref =
|
||||
std::get<size_t>(mod_val->value());
|
||||
|
||||
auto mod = std::get<std::shared_ptr<Module>>
|
||||
(load_global(mod_ref));
|
||||
|
||||
addr_t ident_addr = pop();
|
||||
auto ident =
|
||||
std::get<std::string>(frame().program->
|
||||
get_const(ident_addr)->value());
|
||||
|
||||
auto entry = mod->sym()->find_global(ident);
|
||||
|
||||
if (mod->compiler()->has_macro(ident))
|
||||
{
|
||||
m_pc++;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!entry)
|
||||
{
|
||||
std::cerr << "cannot load " << ident << std::endl;
|
||||
abort();
|
||||
}
|
||||
|
||||
if (entry->is_global())
|
||||
{
|
||||
auto fun = std::get<std::shared_ptr<NativeFunction>>
|
||||
(mod->vm()->m_globals[entry->addr()]);
|
||||
size_t addr = store_global(fun);
|
||||
|
||||
auto ref = std::make_shared<Constant>(TYPE_REF,
|
||||
addr,
|
||||
Loc {""});
|
||||
push(frame().program->add(ref));
|
||||
m_pc++;
|
||||
break;
|
||||
}
|
||||
|
||||
auto var = mod->vm()->load_local(entry->addr());
|
||||
|
||||
if (var->type() == TYPE_REF)
|
||||
{
|
||||
auto value = mod->vm()->load_global
|
||||
(std::get<size_t>(var->value()));
|
||||
|
||||
size_t new_addr = store_global(value);
|
||||
|
||||
push(frame().program->add
|
||||
(std::make_shared<Constant>(TYPE_REF,
|
||||
new_addr,
|
||||
mod_val->loc())));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto value = mod->vm()->load_local(entry->addr());
|
||||
push(frame().program->add(value));
|
||||
}
|
||||
|
||||
m_pc++;
|
||||
} break;
|
||||
|
||||
case OP_STORE_CLOSURE: {
|
||||
auto val = frame().program->get_const(top());
|
||||
auto lambda = frame().lambda;
|
||||
|
@ -135,6 +234,19 @@ namespace fk
|
|||
|
||||
addr_t ref = std::get<addr_t>(ref_val->value());
|
||||
|
||||
auto val = load_global(ref);
|
||||
|
||||
if (std::get_if<std::shared_ptr<NativeFunction>>(&val))
|
||||
{
|
||||
auto fun = std::get<std::shared_ptr<NativeFunction>>
|
||||
(load_global(ref));
|
||||
|
||||
push(frame().program->add(fun->call(ref_val->loc(),
|
||||
m_mod, args)));
|
||||
m_pc++;
|
||||
break;
|
||||
}
|
||||
|
||||
auto lambda = std::get<std::shared_ptr<Lambda>>(load_global(ref));
|
||||
|
||||
|
||||
|
@ -159,36 +271,6 @@ namespace fk
|
|||
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_val = frame().program->get_const(pop());
|
||||
|
||||
Loc loc = ref_val->loc();
|
||||
|
||||
if (instr.param > 0)
|
||||
{
|
||||
loc = args.front()->loc();
|
||||
}
|
||||
|
||||
auto ref = std::get<size_t>(ref_val->value());
|
||||
|
||||
auto fun = std::get<std::shared_ptr<NativeFunction>>
|
||||
(load_global(ref));
|
||||
|
||||
push(frame().program->add(fun->call(loc, m_mod, args)));
|
||||
|
||||
m_pc++;
|
||||
} break;
|
||||
|
||||
case OP_LOAD_LOCAL: {
|
||||
auto value = frame().locals[instr.param];
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
namespace fk
|
||||
{
|
||||
using global_t = std::variant<std::shared_ptr<NativeFunction>,
|
||||
std::shared_ptr<Module>,
|
||||
std::shared_ptr<Lambda>
|
||||
>;
|
||||
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
#ifndef 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_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_BR), G(OP_LOAD_CLOSURE), G(OP_STORE_CLOSURE)
|
||||
G(OP_BR), G(OP_LOAD_CLOSURE), G(OP_STORE_CLOSURE), \
|
||||
G(OP_LOAD_MOD), G(OP_IMPORT), G(OP_IMPORT_SYS)
|
||||
|
||||
#include "commons.hpp"
|
||||
|
||||
|
|
|
@ -97,3 +97,15 @@ TEST_CASE_METHOD(LexerTest, "Lexer_lambda")
|
|||
test_next("CPAR");
|
||||
test_end();
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(LexerTest, "Lexer_namespace")
|
||||
{
|
||||
m_lexer.scan(" (a::x 3) ");
|
||||
test_next("OPAR");
|
||||
test_next("IDENT[a]");
|
||||
test_next("NS");
|
||||
test_next("IDENT[x]");
|
||||
test_next("INT[3]");
|
||||
test_next("CPAR");
|
||||
test_end();
|
||||
}
|
||||
|
|
|
@ -36,6 +36,12 @@ TEST_CASE_METHOD(ParserTest, "Parser_call")
|
|||
" (bim 2 '3' false) ");
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(ParserTest, "Parser_vardecl")
|
||||
{
|
||||
test_parse("MODULE(VARDECL(IDENT[hello],INT[3]))",
|
||||
" ($ hello 3) ");
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(ParserTest, "Parser_lambda")
|
||||
{
|
||||
test_parse("MODULE(LAMBDA(PARAMS,BODY))",
|
||||
|
@ -47,3 +53,31 @@ TEST_CASE_METHOD(ParserTest, "Parser_lambda")
|
|||
test_parse("MODULE(LAMBDA(PARAMS(IDENT[x],IDENT[y]),BODY(INT[7])))",
|
||||
" (-> (x y) 7) ");
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(ParserTest, "Parser_fundecl")
|
||||
{
|
||||
test_parse("MODULE(VARDECL(IDENT[f],"
|
||||
"LAMBDA(PARAMS(IDENT[x]),BODY(INT[7]))))",
|
||||
" ($ (f x) 7) ");
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(ParserTest, "Parser_namespace")
|
||||
{
|
||||
test_parse("MODULE(CALL(NS(IDENT[x],IDENT[y]),IDENT[z]))",
|
||||
" (x::y z) ");
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(ParserTest, "Parser_import")
|
||||
{
|
||||
test_parse("MODULE(VARDECL(IDENT[x],IMPORT(STRING['y'])))",
|
||||
" ($ x (@ 'y') )");
|
||||
|
||||
test_parse("MODULE(VARDECL(IDENT[x],IMPORT(STRING['y'])))",
|
||||
" ($ @x 'y' )");
|
||||
|
||||
test_parse("MODULE(VARDECL(IDENT[bim],IMPORT(STRING['bam'])))",
|
||||
" ($ @bim 'bam' )");
|
||||
|
||||
test_parse("MODULE(VARDECL(IDENT[example],IMPORT(STRING['example'])))",
|
||||
" ($ @example )");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue