ADD: high order functions.

main
bog 2023-09-22 13:27:13 +02:00
parent 7a792274f6
commit 70d0ba241c
7 changed files with 125 additions and 12 deletions

4
examples/high_order.fk Normal file
View File

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

View File

@ -2,8 +2,11 @@
#include "fun.hpp"
#include "macro.hpp"
Module* glob_mod;
extern "C" void lib(Module& mod)
{
glob_mod = &mod;
mod.register_function("assert=", fkstd::assert_eq);
mod.register_function("println", fkstd::println);
mod.register_function("+", fkstd::add_int);

View File

@ -18,6 +18,8 @@ namespace fk
explicit Module(std::filesystem::path source_path);
virtual ~Module();
std::shared_ptr<VM> vm() const { return m_vm; }
void build();
void import_std();

View File

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

View File

@ -21,7 +21,8 @@ namespace fk
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);
@ -75,10 +76,19 @@ namespace fk
pop();
}
}
auto value = m_frames.back().program->get_const(*ret);
m_frames.pop_back();
if (m_frames.empty() == false)
{
push(frame().program->add(value));
}
else
{
m_return_const = value;
}
m_pc++;
} break;
@ -92,10 +102,16 @@ namespace fk
}
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));
auto self = std::make_shared<Constant>(TYPE_REF,
static_cast<size_t>(ref),
ref_val->loc());
Frame frame;
frame.program = lambda->program();
frame.ret_addr = m_pc;
@ -107,9 +123,6 @@ namespace fk
store_local(i, args[i]);
}
auto self = std::make_shared<Constant>(TYPE_REF,
static_cast<size_t>(ref),
ref_val->loc());
store_local(args.size(), self);
m_pc = 0;
@ -144,7 +157,15 @@ namespace fk
case OP_LOAD_LOCAL: {
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));
m_pc++;
@ -185,8 +206,41 @@ 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.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
{
if (m_globals.find(addr) == std::end(m_globals))
{
std::cerr << "cannot find global " << addr << std::endl;
abort();
}
return m_globals.at(addr);
}
@ -243,4 +297,39 @@ namespace fk
m_stack.pop_back();
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.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

@ -30,6 +30,12 @@ namespace fk
void mount(std::shared_ptr<Program> program);
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;
void store_global(addr_t addr, global_t value);
size_t store_global(global_t value);
@ -39,15 +45,23 @@ namespace fk
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:
addr_t m_pc = 0;
std::vector<Frame> m_frames;
std::vector<addr_t> m_stack;
std::unordered_map<addr_t, global_t> m_globals;
void push(addr_t addr);
addr_t top();
addr_t pop();
std::shared_ptr<Constant> m_return_const;
};
}

View File

@ -17,7 +17,7 @@ int main(int argc, char** argv)
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)
{