ADD: recursive functions and lambda.

main
bog 2023-09-22 09:49:28 +02:00
parent 4d91c05aea
commit 7a792274f6
6 changed files with 63 additions and 11 deletions

13
examples/rec.fk Normal file
View File

@ -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))

View File

@ -34,7 +34,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,

View File

@ -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();
@ -106,6 +115,8 @@ 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(); size_t arity = entry->node()->child(0)->size();
if (arity != node->size() - 1) if (arity != node->size() - 1)
@ -120,6 +131,7 @@ namespace fk
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);
} }
@ -190,4 +202,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();
}
} }

View File

@ -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;

View File

@ -56,7 +56,11 @@ namespace fk
for (auto& entry: m_entries) for (auto& entry: m_entries)
{ {
if (entry.name() == name if (entry.name() == name && entry.is_global())
{
result = entry;
}
else if (entry.name() == name
&& entry.scope() <= m_scope && entry.scope() <= m_scope
&& ((entry.parent() == nullptr && m_parents.empty()) && ((entry.parent() == nullptr && m_parents.empty())
|| entry.parent() == m_parents.back()) || entry.parent() == m_parents.back())

View File

@ -107,6 +107,11 @@ namespace fk
store_local(i, args[i]); 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; m_pc = 0;
} break; } break;