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();
|
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,
|
||||||
|
|
|
@ -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();
|
||||||
|
@ -107,18 +116,21 @@ 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)
|
||||||
{
|
{
|
||||||
size_t arity = entry->node()->child(0)->size();
|
if (entry->node())
|
||||||
if (arity != node->size() - 1)
|
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
size_t arity = entry->node()->child(0)->size();
|
||||||
ss << "arity mismatch: " << node->child(0)->repr()
|
if (arity != node->size() - 1)
|
||||||
<< " expect '"
|
{
|
||||||
<< arity
|
std::stringstream ss;
|
||||||
<< "' arguments, got '"
|
ss << "arity mismatch: " << node->child(0)->repr()
|
||||||
<< node->size() - 1
|
<< " expect '"
|
||||||
<< "'";
|
<< arity
|
||||||
|
<< "' arguments, got '"
|
||||||
|
<< node->size() - 1
|
||||||
|
<< "'";
|
||||||
|
|
||||||
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();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue