aboutsummaryrefslogtreecommitdiffstats
path: root/src/simplify.cpp
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2010-12-25 09:24:48 +0000
committerDavid Robillard <d@drobilla.net>2010-12-25 09:24:48 +0000
commit6dec2bd33e6c142664c881405bdc0f9b298e4a11 (patch)
tree8cc17f033c145f2a9467a2c2f56ee7b015fc1a03 /src/simplify.cpp
parentc1ee499d0b14be87b5f5664448507026b9b87fd6 (diff)
downloadresp-6dec2bd33e6c142664c881405bdc0f9b298e4a11.tar.gz
resp-6dec2bd33e6c142664c881405bdc0f9b298e4a11.tar.bz2
resp-6dec2bd33e6c142664c881405bdc0f9b298e4a11.zip
Simplify let to fn, rather than deal with it through to compilation.
The previous implementation of let was a premature optimization intended to make let cheap/free, but screws up closure creation and variable indexing because a new scope is created by something other than fn. Only compile top level expressions to globals (with associated store/retrieve overhead) in a REPL when it is necessary. Add `do' form (ala scheme `begin') to backend (used by `match' simplify). git-svn-id: http://svn.drobilla.net/resp/resp@348 ad02d1e2-f140-0410-9f75-f8b11f17cedd
Diffstat (limited to 'src/simplify.cpp')
-rw-r--r--src/simplify.cpp54
1 files changed, 45 insertions, 9 deletions
diff --git a/src/simplify.cpp b/src/simplify.cpp
index 35178ac..b797057 100644
--- a/src/simplify.cpp
+++ b/src/simplify.cpp
@@ -56,19 +56,16 @@ simplify_if(CEnv& cenv, const ATuple* aif) throw()
static const AST*
simplify_match(CEnv& cenv, const ATuple* match) throw()
{
- List<ATuple, const AST> copy(match->loc, cenv.penv.sym("let"), NULL);
- List<ATuple, const AST> copyVars;
-
- const ASymbol* tsym = cenv.penv.gensym("_matchT");
-
+ // Dot expression to get tag. Note index is -1 to compensate for the lift phase
+ // which adds 1 to skip the RTTI, which we don't want here (FIXME: ick...)
List<ATuple, const AST> tval;
tval.push_back(cenv.penv.sym("."));
tval.push_back(resp_simplify(cenv, match->list_ref(1)));
- tval.push_back(new ALiteral<int32_t>(T_INT32, 0, Cursor()));
+ tval.push_back(new ALiteral<int32_t>(T_INT32, -1, Cursor()));
+
+ const ASymbol* tsym = cenv.penv.gensym("_matchT");
- copyVars.push_back(tsym);
- copyVars.push_back(tval);
- copy.push_back(copyVars);
+ List<ATuple, const AST> def(match->loc, cenv.penv.sym("def"), tsym, tval.head, NULL);
List<ATuple, const AST> copyIf;
copyIf.push_back(cenv.penv.sym("if"));
@@ -86,6 +83,10 @@ simplify_match(CEnv& cenv, const ATuple* match) throw()
}
copyIf.push_back(cenv.penv.sym("__unreachable"));
cenv.setTypeSameAs(copyIf, match);
+
+ List<ATuple, const AST> copy;
+ copy.push_back(cenv.penv.sym("do"));
+ copy.push_back(def);
copy.push_back(simplify_if(cenv, copyIf));
cenv.setTypeSameAs(copy, match);
@@ -104,6 +105,39 @@ simplify_list(CEnv& cenv, const ATuple* call) throw()
return copy;
}
+static const AST*
+simplify_let(CEnv& cenv, const ATuple* call) throw()
+{
+ const ATuple* vars = call->list_ref(1)->to_tuple();
+
+ List<ATuple, const AST> fn(Cursor(), cenv.penv.sym("fn"), NULL);
+
+ List<ATuple, const AST> fnProt;
+ List<ATuple, const AST> fnArgs;
+ List<AType, const AType> fnProtT;
+ for (ATuple::const_iterator i = vars->begin(); i != vars->end();) {
+ const ASymbol* sym = (*i++)->to_symbol();
+ const AST* val = (*i++);
+ fnProt.push_back(sym);
+ fnArgs.push_back(resp_simplify(cenv, val));
+ fnProtT.push_back(cenv.type(val));
+ }
+
+ fn.push_back(fnProt.head);
+ fn.push_back(resp_simplify(cenv, call->list_ref(2)));
+
+ List<AType, const AType> fnT;
+ fnT.push_back(cenv.tenv.Fn);
+ fnT.push_back(fnProtT);
+ fnT.push_back(cenv.type(call->list_ref(2)));
+ cenv.setType(fn, fnT);
+
+ ATuple* copy = new ATuple(fn, fnArgs, call->loc);
+ cenv.setTypeSameAs(copy, call);
+
+ return copy;
+}
+
const AST*
resp_simplify(CEnv& cenv, const AST* ast) throw()
{
@@ -118,6 +152,8 @@ resp_simplify(CEnv& cenv, const AST* ast) throw()
return simplify_match(cenv, list);
else if (form == "if")
return simplify_if(cenv, list);
+ else if (form == "let")
+ return simplify_let(cenv, list);
else
return simplify_list(cenv, list);
}