aboutsummaryrefslogtreecommitdiffstats
path: root/src/lift.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lift.cpp')
-rw-r--r--src/lift.cpp169
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;
+}