diff options
author | David Robillard <d@drobilla.net> | 2010-12-25 09:24:48 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2010-12-25 09:24:48 +0000 |
commit | 6dec2bd33e6c142664c881405bdc0f9b298e4a11 (patch) | |
tree | 8cc17f033c145f2a9467a2c2f56ee7b015fc1a03 | |
parent | c1ee499d0b14be87b5f5664448507026b9b87fd6 (diff) | |
download | resp-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
-rw-r--r-- | src/compile.cpp | 40 | ||||
-rw-r--r-- | src/lift.cpp | 34 | ||||
-rw-r--r-- | src/repl.cpp | 2 | ||||
-rw-r--r-- | src/resp.hpp | 4 | ||||
-rw-r--r-- | src/simplify.cpp | 54 |
5 files changed, 66 insertions, 68 deletions
diff --git a/src/compile.cpp b/src/compile.cpp index 4c7980e..eed481a 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -29,7 +29,7 @@ using namespace std; static CVal compile_symbol(CEnv& cenv, const ASymbol* sym) throw() { - if (cenv.vals.topLevel(sym) && cenv.type(sym)->head()->str() != "Fn") { + if (cenv.repl && cenv.vals.topLevel(sym) && cenv.type(sym)->head()->str() != "Fn") { return cenv.engine()->compileGlobalGet(cenv, sym->sym(), *cenv.vals.ref(sym)); } else { return *cenv.vals.ref(sym); @@ -67,7 +67,7 @@ compile_def(CEnv& cenv, const ATuple* def) throw() const AST* const body = def->list_ref(2); cenv.def(sym, body, cenv.type(body), NULL); // define stub first for recursion CVal val = resp_compile(cenv, body); - if (cenv.vals.size() == 1 && cenv.type(body)->head()->str() != "Fn") { + if (cenv.repl && cenv.vals.size() == 1 && cenv.type(body)->head()->str() != "Fn") { val = cenv.engine()->compileGlobalSet( cenv, sym->str(), val, cenv.type(body)); cenv.lock(def); @@ -77,6 +77,16 @@ compile_def(CEnv& cenv, const ATuple* def) throw() } static CVal +compile_do(CEnv& cenv, const ATuple* ado) throw() +{ + CVal retVal = NULL; + for (ATuple::const_iterator i = ado->iter_at(1); i != ado->end(); ++i) + retVal = resp_compile(cenv, *i); + + return retVal; +} + +static CVal compile_fn(CEnv& cenv, const ATuple* fn) throw() { assert(!cenv.currentFn); @@ -117,28 +127,6 @@ compile_if(CEnv& cenv, const ATuple* aif) throw() } static CVal -compile_let(CEnv& cenv, const ATuple* let) throw() -{ - const ATuple* vars = let->list_ref(1)->to_tuple(); - - 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), resp_compile(cenv, val)); - } - - CVal ret = NULL; - for (ATuple::const_iterator i = let->iter_at(2); i != let->end(); ++i) - ret = resp_compile(cenv, *i); - - cenv.pop(); - - return ret; -} - -static CVal compile_tag_is(CEnv& cenv, const ATuple* call) throw() { const AST* lhs = call->list_ref(1); @@ -207,12 +195,12 @@ resp_compile(CEnv& cenv, const AST* ast) throw() return compile_def(cenv, call); else if (form == "def-type") return NULL; // FIXME + else if (form == "do") + return compile_do(cenv, call); else if (form == "fn") return compile_fn(cenv, call); else if (form == "if") return compile_if(cenv, call); - else if (form == "let") - return compile_let(cenv, call); else if (form == "__tag_is") return compile_tag_is(cenv, call); else diff --git a/src/lift.cpp b/src/lift.cpp index 71843b5..1e115cf 100644 --- a/src/lift.cpp +++ b/src/lift.cpp @@ -183,36 +183,6 @@ 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; @@ -295,12 +265,12 @@ resp_lift(CEnv& cenv, Code& code, const AST* ast) throw() return lift_def(cenv, code, call); else if (form == "def-type") return call; + else if (form == "do") + return lift_args(cenv, code, call); else if (form == "fn") 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 == "__tag_is") return call; else diff --git a/src/repl.cpp b/src/repl.cpp index 063f1e7..d5d78a6 100644 --- a/src/repl.cpp +++ b/src/repl.cpp @@ -177,6 +177,8 @@ eval(CEnv& cenv, Cursor& cursor, istream& is, bool execute) int repl(CEnv& cenv) { + cenv.repl = true; + const AST* exp = NULL; const AST* ast = NULL; const string replFnName = cenv.penv.gensymstr("_repl"); diff --git a/src/resp.hpp b/src/resp.hpp index 439d00b..9bc34e8 100644 --- a/src/resp.hpp +++ b/src/resp.hpp @@ -748,7 +748,7 @@ Engine* resp_new_c_engine(); /// Compile-Time Environment struct CEnv { CEnv(PEnv& p, TEnv& t, Engine* e, ostream& os=std::cout, ostream& es=std::cerr) - : out(os), err(es), penv(p), tenv(t), currentFn(NULL), _engine(e) + : out(os), err(es), penv(p), tenv(t), currentFn(NULL), repl(false), _engine(e) {} ~CEnv() { Object::pool.collect(GC::Roots()); } @@ -829,6 +829,8 @@ struct CEnv { CFunc currentFn; ///< Currently compiling function + bool repl; + struct FreeVars : public std::vector<const ASymbol*> { FreeVars(const ATuple* f, const std::string& n) : fn(f), implName(n) {} const ATuple* const fn; 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); } |