aboutsummaryrefslogtreecommitdiffstats
path: root/src/lift.cpp
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2010-12-09 17:58:43 +0000
committerDavid Robillard <d@drobilla.net>2010-12-09 17:58:43 +0000
commitacf13b1df559c6187d270ef7e31890201c191b12 (patch)
tree4a3d07f257efac1cd5ef51b21af2e55d4fd798b5 /src/lift.cpp
parentd92de14f7d8354004edb14ed5658d5f434ce1e31 (diff)
downloadresp-acf13b1df559c6187d270ef7e31890201c191b12.tar.gz
resp-acf13b1df559c6187d270ef7e31890201c191b12.tar.bz2
resp-acf13b1df559c6187d270ef7e31890201c191b12.zip
Add let form.
git-svn-id: http://svn.drobilla.net/resp/resp@328 ad02d1e2-f140-0410-9f75-f8b11f17cedd
Diffstat (limited to 'src/lift.cpp')
-rw-r--r--src/lift.cpp34
1 files changed, 33 insertions, 1 deletions
diff --git a/src/lift.cpp b/src/lift.cpp
index ad377d7..e3a741b 100644
--- a/src/lift.cpp
+++ b/src/lift.cpp
@@ -32,7 +32,7 @@ lift_symbol(CEnv& cenv, Code& code, const ASymbol* sym) throw()
{
if (!cenv.liftStack.empty() && cenv.name(cenv.liftStack.top().fn) == sym->sym()) {
return cenv.penv.sym("_me"); // Reference to innermost function
- } else if (!cenv.code.innermost(sym)) {
+ } else if (!cenv.liftStack.empty() && !cenv.code.innermost(sym)) {
// Replace symbol with code to access free variable from closure
const int32_t index = cenv.liftStack.top().index(sym);
return tup<ATuple>(sym->loc, cenv.penv.sym("."),
@@ -158,6 +158,36 @@ lift_fn(CEnv& cenv, Code& code, const ATuple* fn) throw()
}
static const AST*
+lift_let(CEnv& cenv, Code& code, const ATuple* let) throw()
+{
+ const ATuple* vars = let->list_ref(1)->to_tuple();
+
+ List<ATuple, const AST> copy(let->loc, let->head(), NULL);
+ List<ATuple, const AST> copyVars;
+
+ cenv.push();
+
+ for (ATuple::const_iterator i = vars->begin(); i != vars->end();) {
+ const ASymbol* sym = (*i++)->to_symbol();
+ const AST* val = (*i++);
+ cenv.def(sym, val, cenv.type(val), NULL);
+ copyVars.push_back(sym);
+ copyVars.push_back(val);
+ resp_lift(cenv, code, val);
+ }
+ copy.push_back(copyVars);
+
+ for (ATuple::const_iterator i = let->iter_at(2); i != let->end(); ++i)
+ copy.push_back(resp_lift(cenv, code, *i));
+
+ cenv.pop();
+
+ cenv.setTypeSameAs(copy, let);
+
+ return copy;
+}
+
+static const AST*
lift_call(CEnv& cenv, Code& code, const ATuple* call) throw()
{
List<ATuple, const AST> copy;
@@ -246,6 +276,8 @@ resp_lift(CEnv& cenv, Code& code, const AST* ast) throw()
return lift_fn(cenv, code, call);
else if (form == "if")
return lift_args(cenv, code, call);
+ else if (form == "let")
+ return lift_let(cenv, code, call);
else if (form == "match")
return call; // FIXME
else