ADD: recursive functions and lambda.
parent
4d91c05aea
commit
7a792274f6
|
@ -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))
|
|
@ -34,7 +34,9 @@ namespace fkstd
|
|||
std::string ident = node->child(1)->repr();
|
||||
auto rhs = node->child(2);
|
||||
|
||||
compiler.push_decl(ident);
|
||||
compiler.compile_prog(rhs, program);
|
||||
compiler.pop_decl();
|
||||
|
||||
auto entry = compiler.sym()->declare_local(ident,
|
||||
addr,
|
||||
|
|
|
@ -53,6 +53,12 @@ namespace fk
|
|||
case NODE_LAMBDA: {
|
||||
auto params = node->child(0);
|
||||
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);
|
||||
|
||||
|
@ -62,6 +68,8 @@ namespace fk
|
|||
m_sym->declare_local(ident, i, node->loc());
|
||||
}
|
||||
|
||||
m_sym->declare_local(func_name, params->size(), node->loc());
|
||||
|
||||
Compiler compiler {m_sym};
|
||||
for (auto e: m_macros)
|
||||
{
|
||||
|
@ -69,6 +77,7 @@ namespace fk
|
|||
}
|
||||
|
||||
auto program = compiler.compile(body);
|
||||
|
||||
program->add(OP_RET);
|
||||
|
||||
m_sym->leave_scope();
|
||||
|
@ -106,6 +115,8 @@ namespace fk
|
|||
{
|
||||
if (auto entry = m_sym->find(node->child(0)->repr());
|
||||
entry && entry->is_global() == false)
|
||||
{
|
||||
if (entry->node())
|
||||
{
|
||||
size_t arity = entry->node()->child(0)->size();
|
||||
if (arity != node->size() - 1)
|
||||
|
@ -120,6 +131,7 @@ namespace fk
|
|||
|
||||
node->loc().error<compile_error>(LOG_ERROR, ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
prog->add(OP_CALL_REF, node->size() - 1);
|
||||
}
|
||||
|
@ -190,4 +202,16 @@ namespace fk
|
|||
} 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,
|
||||
std::shared_ptr<Program> prog);
|
||||
|
||||
void push_decl(std::string const& ident);
|
||||
void pop_decl();
|
||||
|
||||
private:
|
||||
std::shared_ptr<SymTable> m_sym;
|
||||
std::vector<std::string> m_decl_stack;
|
||||
std::unordered_map<std::string,
|
||||
std::shared_ptr<NativeMacro>> m_macros;
|
||||
|
||||
|
|
|
@ -56,7 +56,11 @@ namespace fk
|
|||
|
||||
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.parent() == nullptr && m_parents.empty())
|
||||
|| entry.parent() == m_parents.back())
|
||||
|
|
|
@ -107,6 +107,11 @@ 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;
|
||||
} break;
|
||||
|
||||
|
|
Loading…
Reference in New Issue