diff options
author | David Robillard <d@drobilla.net> | 2010-12-02 08:03:47 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2010-12-02 08:03:47 +0000 |
commit | cf6c924f9cb10a583edbab2560773f2500a86323 (patch) | |
tree | 9073dbe14d904764d4af59141a03228f2e0fbf8e /src/lift.cpp | |
parent | 563a807be78bfe12e5bfbb9ff0d6da44242696c4 (diff) | |
download | resp-cf6c924f9cb10a583edbab2560773f2500a86323.tar.gz resp-cf6c924f9cb10a583edbab2560773f2500a86323.tar.bz2 resp-cf6c924f9cb10a583edbab2560773f2500a86323.zip |
Work towards removing different classes for each type of expression.
git-svn-id: http://svn.drobilla.net/resp/resp@278 ad02d1e2-f140-0410-9f75-f8b11f17cedd
Diffstat (limited to 'src/lift.cpp')
-rw-r--r-- | src/lift.cpp | 169 |
1 files changed, 103 insertions, 66 deletions
diff --git a/src/lift.cpp b/src/lift.cpp index 81b157d..754118a 100644 --- a/src/lift.cpp +++ b/src/lift.cpp @@ -27,56 +27,44 @@ using namespace std; -AST* -ASymbol::lift(CEnv& cenv, Code& code) throw() +static AST* +lift_symbol(CEnv& cenv, Code& code, ASymbol* sym) throw() { + const std::string& cppstr = sym->cppstr; if (!cenv.liftStack.empty() && cppstr == cenv.liftStack.top().fn->name) { return cenv.penv.sym("_me"); // Reference to innermost function } else if (!cenv.penv.handler(true, cppstr) && !cenv.penv.handler(false, cppstr) - && !cenv.code.innermost(this)) { + && !cenv.code.innermost(sym)) { - const int32_t index = cenv.liftStack.top().index(this); + const int32_t index = cenv.liftStack.top().index(sym); // Replace symbol with code to access free variable from closure - return tup<ADot>(loc, cenv.penv.sym("."), + return tup<ADot>(sym->loc, cenv.penv.sym("."), cenv.penv.sym("_me"), new ALiteral<int32_t>(index, Cursor()), NULL); } else { - return this; + return sym; } } -AST* -AQuote::lift(CEnv& cenv, Code& code) throw() -{ - return this; -} - -AST* -ATuple::lift(CEnv& cenv, Code& code) throw() -{ - assert(false); - return NULL; -} - -AST* -AFn::lift(CEnv& cenv, Code& code) throw() +static AST* +lift_fn(CEnv& cenv, Code& code, AFn* fn) throw() { - AFn* impl = new AFn(this); - const string nameBase = cenv.penv.gensymstr(((name != "") ? name : "fn").c_str()); + AFn* impl = new AFn(fn); + const string nameBase = cenv.penv.gensymstr(((fn->name != "") ? fn->name : "fn").c_str()); impl->name = "_" + nameBase; - cenv.liftStack.push(CEnv::FreeVars(this, impl->name)); + cenv.liftStack.push(CEnv::FreeVars(fn, impl->name)); // Create a new stub environment frame for parameters cenv.push(); - const AType* type = cenv.type(this); + const AType* type = cenv.type(fn); AType::const_iterator tp = type->prot()->begin(); AType* implProtT = new AType(*type->prot()->as<const AType*>()); ATuple::iterator ip = implProtT->begin(); - for (const_iterator p = prot()->begin(); p != prot()->end(); ++p) { + for (AFn::const_iterator p = fn->prot()->begin(); p != fn->prot()->end(); ++p) { const AType* paramType = (*tp++)->as<const AType*>(); if (paramType->kind == AType::EXPR && *paramType->head() == *cenv.tenv.Fn) { AType* fnType = new AType(*paramType); @@ -96,9 +84,9 @@ AFn::lift(CEnv& cenv, Code& code) throw() // Lift body const AType* implRetT = NULL; - iterator ci = impl->iter_at(2); - for (iterator i = iter_at(2); i != end(); ++i, ++ci) { - *ci = (*i)->lift(cenv, code); + AFn::iterator ci = impl->iter_at(2); + for (AFn::iterator i = fn->iter_at(2); i != fn->end(); ++i, ++ci) { + *ci = resp_lift(cenv, code, *i); implRetT = cenv.type(*ci); } @@ -109,13 +97,13 @@ AFn::lift(CEnv& cenv, Code& code) throw() // Create definition for implementation fn ASymbol* implName = cenv.penv.sym(impl->name); - ADef* def = tup<ADef>(loc, cenv.penv.sym("def"), implName, impl, NULL); + ADef* def = tup<ADef>(fn->loc, cenv.penv.sym("def"), implName, impl, NULL); code.push_back(def); AType* implT = new AType(*type); // Type of the implementation function - TList tupT(loc, cenv.tenv.Tup, cenv.tenv.var(), NULL); - TList consT(loc, cenv.tenv.Tup, implT, NULL); - List<ACons, AST> cons(loc, cenv.penv.sym("Closure"), implName, NULL); + TList tupT(fn->loc, cenv.tenv.Tup, cenv.tenv.var(), NULL); + TList consT(fn->loc, cenv.tenv.Tup, implT, NULL); + List<ACons, AST> cons(fn->loc, cenv.penv.sym("Closure"), implName, NULL); implT->list_ref(1) = implProtT; @@ -134,32 +122,32 @@ AFn::lift(CEnv& cenv, Code& code) throw() cenv.setType(cons, consT); cenv.def(implName, impl, implT, NULL); - if (name != "") - cenv.def(cenv.penv.sym(name), this, consT, NULL); + if (fn->name != "") + cenv.def(cenv.penv.sym(fn->name), fn, consT, NULL); return cons; } -AST* -ACall::lift(CEnv& cenv, Code& code) throw() +static AST* +lift_call(CEnv& cenv, Code& code, ACall* call) throw() { List<ACall, AST> copy; // Lift all children (callee and arguments, recursively) - for (iterator i = begin(); i != end(); ++i) - copy.push_back((*i)->lift(cenv, code)); + for (ATuple::iterator i = call->begin(); i != call->end(); ++i) + copy.push_back(resp_lift(cenv, code, *i)); - copy.head->loc = loc; + copy.head->loc = call->loc; const AType* copyT = NULL; - ASymbol* sym = head()->to<ASymbol*>(); + ASymbol* sym = call->head()->to<ASymbol*>(); if (sym && !cenv.liftStack.empty() && sym->cppstr == cenv.liftStack.top().fn->name) { /* Recursive call to innermost function, call implementation directly, * reusing the current "_me" closure parameter (no cons or .). */ copy.push_front(cenv.penv.sym(cenv.liftStack.top().implName)); - } else if (head()->to<AFn*>()) { + } else if (call->head()->to<AFn*>()) { /* Special case: ((fn ...) ...) * Lifting (fn ...) yields: (Fn _impl ...). * We don't want ((Fn _impl ...) (Fn _impl ...) ...), @@ -174,7 +162,7 @@ ACall::lift(CEnv& cenv, Code& code) throw() copyT = implT->list_ref(2)->as<const AType*>(); } else { // Call to a closure, prepend code to access implementation function - ADot* getFn = tup<ADot>(loc, cenv.penv.sym("."), + ADot* getFn = tup<ADot>(call->loc, cenv.penv.sym("."), copy.head->head(), new ALiteral<int32_t>(0, Cursor()), NULL); const AType* calleeT = cenv.type(copy.head->head()); @@ -189,47 +177,96 @@ ACall::lift(CEnv& cenv, Code& code) throw() return copy; } -AST* -ADef::lift(CEnv& cenv, Code& code) throw() +static AST* +lift_def(CEnv& cenv, Code& code, ADef* def) throw() { // Define stub first for recursion - cenv.def(sym(), body(), cenv.type(body()), NULL); - AFn* c = body()->to<AFn*>(); + const ASymbol* const sym = def->list_ref(1)->as<const ASymbol*>(); + cenv.def(sym, def->body(), cenv.type(def->body()), NULL); + AFn* c = def->body()->to<AFn*>(); if (c) - c->name = sym()->str(); + c->name = sym->str(); - assert(list_ref(1)->to<const ASymbol*>()); + assert(def->list_ref(1)->to<const ASymbol*>()); List<ADef, AST> copy; - copy.push_back(head()); - copy.push_back(list_ref(1)->lift(cenv, code)); - for (iterator t = iter_at(2); t != end(); ++t) - copy.push_back((*t)->lift(cenv, code)); + copy.push_back(def->head()); + copy.push_back(resp_lift(cenv, code, def->list_ref(1))); + for (ADef::iterator t = def->iter_at(2); t != def->end(); ++t) + copy.push_back(resp_lift(cenv, code, *t)); - cenv.setTypeSameAs(copy, this); + cenv.setTypeSameAs(copy, def); - if (copy.head->sym() == copy.head->body()) + if (copy.head->list_ref(1) == copy.head->list_ref(2)) return NULL; // Definition created by AFn::lift when body was lifted - cenv.def(copy.head->sym(), copy.head->body(), cenv.type(copy.head->body()), NULL); + cenv.def(copy.head->list_ref(1)->as<const ASymbol*>(), + copy.head->list_ref(2), + cenv.type(copy.head->list_ref(2)), + NULL); return copy; } template<typename T> -AST* -lift_builtin_call(CEnv& cenv, T* call, Code& code) throw() +static AST* +lift_builtin_call(CEnv& cenv, Code& code, ACall* call) throw() { - ATuple* copy = new T(call); - ATuple::iterator ri = copy->iter_at(1); + List<T, AST> copy; + copy.push_back(call->head()); // Lift all arguments - for (typename T::iterator i = call->iter_at(1); i != call->end(); ++i) - *ri++ = (*i)->lift(cenv, code); + for (ATuple::iterator i = call->iter_at(1); i != call->end(); ++i) + copy.push_back(resp_lift(cenv, code, *i)); cenv.setTypeSameAs(copy, call); return copy; } -AST* AIf::lift(CEnv& cenv, Code& code) throw() { return lift_builtin_call(cenv, this, code); } -AST* ACons::lift(CEnv& cenv, Code& code) throw() { return lift_builtin_call(cenv, this, code); } -AST* ADot::lift(CEnv& cenv, Code& code) throw() { return lift_builtin_call(cenv, this, code); } -AST* APrimitive::lift(CEnv& cenv, Code& code) throw() { return lift_builtin_call(cenv, this, code); } +AST* +resp_lift(CEnv& cenv, Code& code, AST* ast) throw() +{ + ASymbol* const sym = ast->to<ASymbol*>(); + if (sym) + return lift_symbol(cenv, code, sym); + + ADef* const def = ast->to<ADef*>(); + if (def) + return lift_def(cenv, code, def); + + AFn* const fn = ast->to<AFn*>(); + if (fn) + return lift_fn(cenv, code, fn); + + AIf* const aif = ast->to<AIf*>(); + if (aif) + return lift_builtin_call<AIf>(cenv, code, aif); + + ACons* const cons = ast->to<ACons*>(); + if (cons) + return lift_builtin_call<ACons>(cenv, code, cons); + + ADot* const dot = ast->to<ADot*>(); + if (dot) + return lift_builtin_call<ADot>(cenv, code, dot); + + AQuote* const quote = ast->to<AQuote*>(); + if (quote) + return lift_builtin_call<AQuote>(cenv, code, quote); + + AMatch* const match = ast->to<AMatch*>(); + if (match) + return match; // FIXME + + APrimitive* const prim = ast->to<APrimitive*>(); + if (prim) + return lift_builtin_call<APrimitive>(cenv, code, prim); + + ADefType* const defType = ast->to<ADefType*>(); + if (defType) + return defType; + + ACall* const call = ast->to<ACall*>(); + if (call) + return lift_call(cenv, code, call); + + return ast; +} |