aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/c.cpp67
-rw-r--r--src/compile.cpp11
-rw-r--r--src/constrain.cpp73
-rw-r--r--src/cps.cpp47
-rw-r--r--src/gc.cpp2
-rw-r--r--src/lift.cpp18
-rw-r--r--src/llvm.cpp66
-rw-r--r--src/pprint.cpp17
-rw-r--r--src/tuplr.cpp1
-rw-r--r--src/tuplr.hpp30
-rw-r--r--src/unify.cpp32
11 files changed, 211 insertions, 153 deletions
diff --git a/src/c.cpp b/src/c.cpp
index 74dceb2..2dc51d5 100644
--- a/src/c.cpp
+++ b/src/c.cpp
@@ -49,14 +49,15 @@ llType(const AType* t)
if (t->head()->str() == "Float") return new string("float");
throw Error(t->loc, string("Unknown primitive type `") + t->str() + "'");
} else if (t->kind == AType::EXPR && t->head()->str() == "Fn") {
- const AType* retT = t->at(2)->as<const AType*>();
+ AType::const_iterator i = t->begin();
+ const ATuple* protT = (*++i)->to<const ATuple*>();
+ const AType* retT = (*i)->as<const AType*>();
if (!llType(retT))
return NULL;
Type* ret = new Type(*llType(retT) + " (*)(");
- const ATuple* prot = t->at(1)->to<const ATuple*>();
- for (size_t i = 0; i < prot->size(); ++i) {
- const AType* at = prot->at(i)->to<const AType*>();
+ FOREACHP(ATuple::const_iterator, i, protT) {
+ const AType* at = (*i)->to<const AType*>();
const Type* lt = llType(at);
if (!lt)
return NULL;
@@ -102,10 +103,12 @@ struct CEngine : public Engine {
f->returnType = *llType(retT);
f->name = name;
f->text += f->returnType + "\n" + f->name + "(";
- for (size_t i = 0; i != argsT.size(); ++i) {
- if (i > 0)
+ ATuple::const_iterator ai = argsT.begin();
+ vector<string>::const_iterator ni = argNames.begin();
+ for (; ai != argsT.end(); ++ai, ++ni) {
+ if (ai != argsT.begin())
f->text += ", ";
- f->text += *llType(argsT.at(i)->as<const AType*>()) + " " + argNames.at(i);
+ f->text += *llType((*ai)->as<const AType*>()) + " " + *ni;
}
f->text += ")\n{\n";
@@ -187,16 +190,16 @@ CEngine::compileFunction(CEnv& cenv, AFn* fn, const AType& argsT)
if (f)
return f;
- ATuple* protT = thisType->at(1)->as<ATuple*>();
+ ATuple* protT = thisType->prot();
vector<string> argNames;
- for (size_t i = 0; i < fn->prot()->size(); ++i)
- argNames.push_back(fn->prot()->at(i)->str());
+ for (ATuple::const_iterator i = fn->prot()->begin(); i != fn->prot()->end(); ++i)
+ argNames.push_back((*i)->str());
// Write function declaration
const string name = (fn->name == "") ? cenv.penv.gensymstr("_fn") : fn->name;
f = llFunc(cenv.engine()->startFunction(cenv, name,
- thisType->at(thisType->size()-1)->to<AType*>(),
+ thisType->last()->to<AType*>(),
*protT, argNames));
cenv.push();
@@ -205,22 +208,22 @@ CEngine::compileFunction(CEnv& cenv, AFn* fn, const AType& argsT)
// Bind argument values in CEnv
vector<Value*> args;
- AFn::const_iterator p = fn->prot()->begin();
- size_t i = 0;
- for (; p != fn->prot()->end(); ++p, ++i) {
- AType* t = protT->at(i)->as<AType*>();
+ AFn::const_iterator p = fn->prot()->begin();
+ ATuple::const_iterator pT = protT->begin();
+ for (; p != fn->prot()->end(); ++p, ++pT) {
+ AType* t = (*pT)->as<AType*>();
const Type* lt = llType(t);
THROW_IF(!lt, fn->loc, "untyped parameter\n");
- cenv.def((*p)->as<ASymbol*>(), *p, t, new string(fn->prot()->at(i)->str()));
+ cenv.def((*p)->as<ASymbol*>(), *p, t, new string((*p)->str()));
}
// Write function body
try {
fn->impls.push_back(make_pair(thisType, f));
CVal retVal = NULL;
- for (size_t i = 2; i < fn->size(); ++i)
- retVal = fn->at(i)->compile(cenv);
- cenv.engine()->finishFunction(cenv, f, cenv.type(fn->at(fn->size() - 1)), retVal);
+ for (AFn::iterator i = fn->begin() + 2; i != fn->end(); ++i)
+ retVal = (*i)->compile(cenv);
+ cenv.engine()->finishFunction(cenv, f, cenv.type(fn->last()), retVal);
} catch (Error& e) {
cenv.pop();
throw e;
@@ -236,20 +239,25 @@ CEngine::compileIf(CEnv& cenv, AIf* aif)
CEngine* engine = reinterpret_cast<CEngine*>(cenv.engine());
Value* varname = new string(cenv.penv.gensymstr("if"));
out += (format("%s %s;\n") % *llType(cenv.type(aif)) % *varname).str();
- for (size_t i = 1; i < aif->size() - 1; i += 2) {
- if (i > 1)
+ size_t idx = 1;
+ for (AIf::iterator i = aif->begin() + 1; ; ++i, idx += 2) {
+ AIf::iterator next = i;
+ if (++next == aif->end())
+ break;
+
+ if (idx > 1)
out += "else {\n";
- Value* condV = llVal(aif->at(i)->compile(cenv));
+ Value* condV = llVal((*i)->compile(cenv));
out += (format("if (%s) {\n") % *condV).str();
- Value* thenV = llVal(aif->at(i + 1)->compile(cenv));
+ Value* thenV = llVal((*next)->compile(cenv));
out += (format("%s = %s;\n}\n") % *varname % *thenV).str();
}
// Emit final else block
out += "else {\n";
- Value* elseV = llVal(aif->at(aif->size() - 1)->compile(cenv));
+ Value* elseV = llVal(aif->last()->compile(cenv));
out += (format("%s = %s;\n}\n") % *varname % *elseV).str();
for (size_t i = 1; i < (aif->size() - 1) / 2; ++i)
@@ -261,9 +269,12 @@ CEngine::compileIf(CEnv& cenv, AIf* aif)
CVal
CEngine::compilePrimitive(CEnv& cenv, APrimitive* prim)
{
+ APrimitive::iterator i = prim->begin();
+ ++i;
+
CEngine* engine = reinterpret_cast<CEngine*>(cenv.engine());
- Value* a = llVal(prim->at(1)->compile(cenv));
- Value* b = llVal(prim->at(2)->compile(cenv));
+ Value* a = llVal((*i++)->compile(cenv));
+ Value* b = llVal((*i++)->compile(cenv));
const string n = prim->head()->to<ASymbol*>()->str();
string op = n;
@@ -277,8 +288,8 @@ CEngine::compilePrimitive(CEnv& cenv, APrimitive* prim)
string val("(");
val += *a + op + *b;
- for (size_t i = 3; i < prim->size(); ++i)
- val += op + *llVal(prim->at(i)->compile(cenv));
+ while (i != prim->end())
+ val += op + *llVal((*i++)->compile(cenv));
val += ")";
Value* varname = new string(cenv.penv.gensymstr("x"));
diff --git a/src/compile.cpp b/src/compile.cpp
index e8e06b8..9a7162f 100644
--- a/src/compile.cpp
+++ b/src/compile.cpp
@@ -51,8 +51,8 @@ ACall::compile(CEnv& cenv)
if (!c) return NULL; // Primitive
AType protT(loc);
- for (size_t i = 1; i < size(); ++i)
- protT.push_back(cenv.type(at(i)));
+ for (const_iterator i = begin() + 1; i != end(); ++i)
+ protT.push_back(cenv.type(*i));
AType fnT(loc);
fnT.push_back(cenv.penv.sym("Fn"));
@@ -63,8 +63,9 @@ ACall::compile(CEnv& cenv)
THROW_IF(!f, loc, (format("callee failed to compile for type %1%") % fnT.str()).str());
vector<CVal> args(size() - 1);
+ const_iterator e = begin() + 1;
for (size_t i = 0; i < args.size(); ++i)
- args[i] = at(i + 1)->compile(cenv);
+ args[i] = (*e++)->compile(cenv);
return cenv.engine()->compileCall(cenv, f, args);
}
@@ -73,8 +74,8 @@ CVal
ADef::compile(CEnv& cenv)
{
// Define stub first for recursion
- cenv.def(sym(), at(2), cenv.type(at(2)), NULL);
- CVal val = at(size() - 1)->compile(cenv);
+ cenv.def(sym(), body(), cenv.type(body()), NULL);
+ CVal val = body()->compile(cenv);
cenv.vals.def(sym(), val);
return val;
}
diff --git a/src/constrain.cpp b/src/constrain.cpp
index 2fd3fa9..982f195 100644
--- a/src/constrain.cpp
+++ b/src/constrain.cpp
@@ -51,7 +51,7 @@ void
ATuple::constrain(TEnv& tenv, Constraints& c) const
{
AType* t = tup<AType>(loc, NULL);
- FOREACH(const_iterator, p, *this) {
+ FOREACHP(const_iterator, p, this) {
(*p)->constrain(tenv, c);
t->push_back(tenv.var(*p));
}
@@ -76,10 +76,12 @@ AFn::constrain(TEnv& tenv, Constraints& c) const
frame.push_back(make_pair(sym, tvar));
protT->push_back(tvar);
}
- c.constrain(tenv, at(1), protT);
+
+ const_iterator i = begin() + 1;
+ c.constrain(tenv, *i, protT);
// Add internal definitions to environment frame
- for (const_iterator i = begin() + 2; i != end(); ++i) {
+ for (++i; i != end(); ++i) {
const AST* exp = *i;
const ADef* def = exp->to<const ADef*>();
if (def) {
@@ -94,10 +96,11 @@ AFn::constrain(TEnv& tenv, Constraints& c) const
tenv.push(frame);
c.constrain(tenv, this, tenv.var());
- for (size_t i = 2; i < size(); ++i)
- at(i)->constrain(tenv, c);
+ AST* exp = NULL;
+ for (i = begin() + 2; i != end(); ++i)
+ (exp = *i)->constrain(tenv, c);
- AType* bodyT = tenv.var(at(size() - 1));
+ AType* bodyT = tenv.var(exp);
AType* fnT = tup<AType>(loc, tenv.penv.sym("Fn"), protT, bodyT, 0);
Object::pool.addRoot(fnT);
@@ -109,8 +112,8 @@ AFn::constrain(TEnv& tenv, Constraints& c) const
void
ACall::constrain(TEnv& tenv, Constraints& c) const
{
- for (size_t i = 0; i < size(); ++i)
- at(i)->constrain(tenv, c);
+ for (const_iterator i = begin(); i != end(); ++i)
+ (*i)->constrain(tenv, c);
const AType* fnType = tenv.var(head());
if (fnType->kind != AType::VAR) {
@@ -120,15 +123,15 @@ ACall::constrain(TEnv& tenv, Constraints& c) const
|| fnType->head()->to<const ASymbol*>()->cppstr != "Fn")
throw Error(loc, (format("call to non-function `%1%'") % head()->str()).str());
- size_t numArgs = fnType->at(1)->to<const ATuple*>()->size();
+ size_t numArgs = fnType->prot()->size();
THROW_IF(numArgs != size() - 1, loc,
(format("expected %1% arguments, got %2%") % numArgs % (size() - 1)).str());
}
AType* retT = tenv.var();
AType* argsT = tup<AType>(loc, 0);
- for (size_t i = 1; i < size(); ++i)
- argsT->push_back(tenv.var(at(i)));
+ for (const_iterator i = begin() + 1; i != end(); ++i)
+ argsT->push_back(tenv.var(*i));
c.constrain(tenv, head(), tup<AType>(head()->loc, tenv.penv.sym("Fn"), argsT, retT, 0));
c.constrain(tenv, this, retT);
@@ -141,10 +144,10 @@ ADef::constrain(TEnv& tenv, Constraints& c) const
const ASymbol* sym = this->sym();
THROW_IF(!sym, loc, "`def' has no symbol")
- AType* tvar = tenv.var(at(2));
+ AType* tvar = tenv.var(body());
tenv.def(sym, tvar);
- at(2)->constrain(tenv, c);
- c.constrain(tenv, at(1), tvar);
+ body()->constrain(tenv, c);
+ c.constrain(tenv, sym, tvar);
c.constrain(tenv, this, tenv.named("Nothing"));
}
@@ -153,16 +156,20 @@ AIf::constrain(TEnv& tenv, Constraints& c) const
{
THROW_IF(size() < 4, loc, "`if' requires at least 3 arguments");
THROW_IF(size() % 2 != 0, loc, "`if' missing final else clause")
- for (size_t i = 1; i < size(); ++i)
- at(i)->constrain(tenv, c);
+ for (const_iterator i = begin() + 1; i != end(); ++i)
+ (*i)->constrain(tenv, c);
AType* retT = tenv.var(this);
- for (size_t i = 1; i < size(); i += 2) {
- if (i == size() - 1) {
- c.constrain(tenv, at(i), retT);
+ for (const_iterator i = begin() + 1; true; ++i) {
+ const_iterator next = i;
+ ++next;
+ if (next == end()) { // final (else) expression
+ c.constrain(tenv, *i, retT);
+ break;
} else {
- c.constrain(tenv, at(i), tenv.named("Bool"));
- c.constrain(tenv, at(i+1), retT);
+ c.constrain(tenv, *i, tenv.named("Bool"));
+ c.constrain(tenv, *next, retT);
}
+ i = next; // jump 2 each iteration (to the next predicate)
}
}
@@ -182,34 +189,40 @@ APrimitive::constrain(TEnv& tenv, Constraints& c) const
else
throw Error(loc, (format("unknown primitive `%1%'") % n).str());
- for (size_t i = 1; i < size(); ++i)
- at(i)->constrain(tenv, c);
+ const_iterator i = begin();
+
+ for (++i; i != end(); ++i)
+ (*i)->constrain(tenv, c);
+
+ i = begin();
+ AType* var = NULL;
switch (type) {
case ARITHMETIC:
if (size() < 3)
throw Error(loc, (format("`%1%' requires at least 2 arguments") % n).str());
- for (size_t i = 1; i < size(); ++i)
- c.constrain(tenv, at(i), tenv.var(this));
+ for (++i; i != end(); ++i)
+ c.constrain(tenv, *i, tenv.var(this));
break;
case BINARY:
if (size() != 3)
throw Error(loc, (format("`%1%' requires exactly 2 arguments") % n).str());
- c.constrain(tenv, at(1), tenv.var(this));
- c.constrain(tenv, at(2), tenv.var(this));
+ c.constrain(tenv, *++i, tenv.var(this));
+ c.constrain(tenv, *++i, tenv.var(this));
break;
case LOGICAL:
if (size() != 3)
throw Error(loc, (format("`%1%' requires exactly 2 arguments") % n).str());
c.constrain(tenv, this, tenv.named("Bool"));
- c.constrain(tenv, at(1), tenv.named("Bool"));
- c.constrain(tenv, at(2), tenv.named("Bool"));
+ c.constrain(tenv, *++i, tenv.named("Bool"));
+ c.constrain(tenv, *++i, tenv.named("Bool"));
break;
case COMPARISON:
if (size() != 3)
throw Error(loc, (format("`%1%' requires exactly 2 arguments") % n).str());
+ var = tenv.var(*++i);
c.constrain(tenv, this, tenv.named("Bool"));
- c.constrain(tenv, at(1), tenv.var(at(2)));
+ c.constrain(tenv, *++i, var);
break;
default:
throw Error(loc, (format("unknown primitive `%1%'") % n).str());
diff --git a/src/cps.cpp b/src/cps.cpp
index eb44fd9..6711556 100644
--- a/src/cps.cpp
+++ b/src/cps.cpp
@@ -62,21 +62,24 @@ ACall::cps(TEnv& tenv, AST* cont)
// Argument evaluation continuations are not themselves in CPS.
// Each makes a tail call to the next, and the last makes a tail
// call to the continuation of this call
- ssize_t firstFn = -1;
- ssize_t index = 0;
- FOREACH(iterator, i, *this) {
+ iterator firstFnIter = end();
+ AFn* firstFn = NULL;
+ ssize_t index = 0;
+ FOREACHP(iterator, i, this) {
if (!(*i)->to<ATuple*>()) {
funcs.push_back(make_pair((AFn*)NULL, (*i)));
} else {
arg = tenv.penv.gensym("a");
- if (firstFn == -1)
- firstFn = index;
-
AFn* thisFn = tup<AFn>(loc, tenv.penv.sym("fn"),
tup<ATuple>((*i)->loc, arg, 0),
0);
+ if (firstFnIter == end()) {
+ firstFnIter = i;
+ firstFn = thisFn;
+ }
+
if (fn)
fn->push_back((*i)->cps(tenv, thisFn));
@@ -86,7 +89,7 @@ ACall::cps(TEnv& tenv, AST* cont)
++index;
}
- if (firstFn != -1) {
+ if (firstFnIter != end()) {
// Call this call's callee in the last argument evaluator
ACall* call = tup<ACall>(loc, 0);
assert(funcs.size() == size());
@@ -95,11 +98,11 @@ ACall::cps(TEnv& tenv, AST* cont)
assert(fn);
fn->push_back(call->cps(tenv, cont));
- return at(firstFn)->cps(tenv, funcs[firstFn].first);
+ return (*firstFnIter)->cps(tenv, firstFn);
} else {
assert(head()->value());
ACall* ret = tup<ACall>(loc, 0);
- FOREACH(iterator, i, *this)
+ FOREACHP(iterator, i, this)
ret->push_back((*i));
if (!to<APrimitive*>())
ret->push_back(cont);
@@ -111,10 +114,10 @@ ACall::cps(TEnv& tenv, AST* cont)
AST*
ADef::cps(TEnv& tenv, AST* cont)
{
- AST* val = at(2)->cps(tenv, cont);
+ AST* val = body()->cps(tenv, cont);
ACall* valCall = val->to<ACall*>();
- assert(valCall);
- return tup<ADef>(loc, tenv.penv.sym("def"), sym(), valCall->at(1), 0);
+ ACall::iterator i = valCall->begin();
+ return tup<ADef>(loc, tenv.penv.sym("def"), sym(), *++i, 0);
}
/** (cps (if c t ... e)) => */
@@ -122,16 +125,20 @@ AST*
AIf::cps(TEnv& tenv, AST* cont)
{
ASymbol* argSym = tenv.penv.gensym("c");
- if (at(1)->value()) {
- return tup<AIf>(loc, tenv.penv.sym("if"), at(1),
- at(2)->cps(tenv, cont),
- at(3)->cps(tenv, cont), 0);
+ const_iterator i = begin();
+ AST* cond = *++i;
+ AST* exp = *++i;
+ AST* next = *++i;
+ if (cond->value()) {
+ return tup<AIf>(loc, tenv.penv.sym("if"), cond,
+ exp->cps(tenv, cont),
+ next->cps(tenv, cont), 0);
} else {
AFn* contFn = tup<AFn>(loc, tenv.penv.sym("fn"),
- tup<ATuple>(at(1)->loc, argSym, tenv.penv.gensym("_k"), 0),
+ tup<ATuple>(cond->loc, argSym, tenv.penv.gensym("_k"), 0),
tup<AIf>(loc, tenv.penv.sym("if"), argSym,
- at(2)->cps(tenv, cont),
- at(3)->cps(tenv, cont), 0));
- return at(1)->cps(tenv, contFn);
+ exp->cps(tenv, cont),
+ next->cps(tenv, cont), 0));
+ return cond->cps(tenv, contFn);
}
}
diff --git a/src/gc.cpp b/src/gc.cpp
index 96d412a..acbcb0e 100644
--- a/src/gc.cpp
+++ b/src/gc.cpp
@@ -58,7 +58,7 @@ mark(const Object* obj)
obj->mark(true);
const ATuple* tup = dynamic_cast<const ATuple*>((AST*)obj);
if (tup)
- FOREACH(ATuple::const_iterator, i, *tup)
+ FOREACHP(ATuple::const_iterator, i, tup)
mark(*i);
}
diff --git a/src/lift.cpp b/src/lift.cpp
index f5fe607..499fadd 100644
--- a/src/lift.cpp
+++ b/src/lift.cpp
@@ -31,8 +31,8 @@ AFn::lift(CEnv& cenv)
cenv.def((*p)->as<ASymbol*>(), *p, NULL, NULL);
// Lift body
- for (size_t i = 2; i < size(); ++i)
- at(i)->lift(cenv);
+ for (iterator i = begin() + 2; i != end(); ++i)
+ (*i)->lift(cenv);
cenv.pop();
@@ -40,7 +40,7 @@ AFn::lift(CEnv& cenv)
if (impls.find(type) || !type->concrete())
return;
- AType* protT = type->at(1)->as<AType*>();
+ AType* protT = type->prot()->as<AType*>();
cenv.engine()->compileFunction(cenv, this, *protT);
}
@@ -51,9 +51,9 @@ ACall::lift(CEnv& cenv)
AType argsT(loc);
// Lift arguments
- for (size_t i = 1; i < size(); ++i) {
- at(i)->lift(cenv);
- argsT.push_back(cenv.type(at(i)));
+ for (iterator i = begin() + 1; i != end(); ++i) {
+ (*i)->lift(cenv);
+ argsT.push_back(cenv.type(*i));
}
if (!c) return; // Primitive
@@ -70,9 +70,9 @@ void
ADef::lift(CEnv& cenv)
{
// Define stub first for recursion
- cenv.def(sym(), at(2), cenv.type(at(2)), NULL);
- AFn* c = at(2)->to<AFn*>();
+ cenv.def(sym(), body(), cenv.type(body()), NULL);
+ AFn* c = body()->to<AFn*>();
if (c)
c->name = sym()->str();
- at(2)->lift(cenv);
+ body()->lift(cenv);
}
diff --git a/src/llvm.cpp b/src/llvm.cpp
index 30927d4..bb30cbc 100644
--- a/src/llvm.cpp
+++ b/src/llvm.cpp
@@ -52,14 +52,15 @@ llType(const AType* t)
if (t->head()->str() == "Float") return Type::FloatTy;
throw Error(t->loc, string("Unknown primitive type `") + t->str() + "'");
} else if (t->kind == AType::EXPR && t->head()->str() == "Fn") {
- const AType* retT = t->at(2)->as<const AType*>();
+ AType::const_iterator i = t->begin();
+ const ATuple* protT = (*++i)->to<const ATuple*>();
+ const AType* retT = (*i)->as<const AType*>();
if (!llType(retT))
return NULL;
vector<const Type*> cprot;
- const ATuple* prot = t->at(1)->to<const ATuple*>();
- for (size_t i = 0; i < prot->size(); ++i) {
- const AType* at = prot->at(i)->to<const AType*>();
+ FOREACHP(ATuple::const_iterator, i, protT) {
+ const AType* at = (*i)->to<const AType*>();
const Type* lt = llType(at);
if (!lt)
return NULL;
@@ -126,8 +127,8 @@ struct LLVMEngine : public Engine {
// Set argument names in generated code
Function::arg_iterator a = f->arg_begin();
if (!argNames.empty())
- for (size_t i = 0; i != argsT.size(); ++a, ++i)
- a->setName(argNames.at(i));
+ for (vector<string>::const_iterator i = argNames.begin(); i != argNames.end(); ++a, ++i)
+ a->setName(*i);
BasicBlock* bb = BasicBlock::Create("entry", f);
builder.SetInsertPoint(bb);
@@ -243,16 +244,16 @@ LLVMEngine::compileFunction(CEnv& cenv, AFn* fn, const AType& argsT)
if (f)
return f;
- ATuple* protT = thisType->at(1)->as<ATuple*>();
+ ATuple* protT = thisType->prot();
vector<string> argNames;
- for (size_t i = 0; i < fn->prot()->size(); ++i)
- argNames.push_back(fn->prot()->at(i)->str());
+ for (ATuple::const_iterator i = fn->prot()->begin(); i != fn->prot()->end(); ++i)
+ argNames.push_back((*i)->str());
// Write function declaration
const string name = (fn->name == "") ? cenv.penv.gensymstr("_fn") : fn->name;
f = llFunc(cenv.engine()->startFunction(cenv, name,
- thisType->at(thisType->size()-1)->to<AType*>(),
+ thisType->last()->to<AType*>(),
*protT, argNames));
cenv.push();
@@ -261,10 +262,10 @@ LLVMEngine::compileFunction(CEnv& cenv, AFn* fn, const AType& argsT)
// Bind argument values in CEnv
vector<Value*> args;
- AFn::const_iterator p = fn->prot()->begin();
- size_t i = 0;
- for (Function::arg_iterator a = f->arg_begin(); a != f->arg_end(); ++a, ++p, ++i) {
- AType* t = protT->at(i)->as<AType*>();
+ AFn::const_iterator p = fn->prot()->begin();
+ ATuple::const_iterator pT = protT->begin();
+ for (Function::arg_iterator a = f->arg_begin(); a != f->arg_end(); ++a, ++p, ++pT) {
+ AType* t = (*pT)->as<AType*>();
const Type* lt = llType(t);
THROW_IF(!lt, fn->loc, "untyped parameter\n");
cenv.def((*p)->as<ASymbol*>(), *p, t, &*a);
@@ -274,9 +275,9 @@ LLVMEngine::compileFunction(CEnv& cenv, AFn* fn, const AType& argsT)
try {
fn->impls.push_back(make_pair(thisType, f));
CVal retVal = NULL;
- for (size_t i = 2; i < fn->size(); ++i)
- retVal = fn->at(i)->compile(cenv);
- cenv.engine()->finishFunction(cenv, f, cenv.type(fn->at(fn->size() - 1)), retVal);
+ for (AFn::iterator i = fn->begin() + 2; i != fn->end(); ++i)
+ retVal = (*i)->compile(cenv);
+ cenv.engine()->finishFunction(cenv, f, cenv.type(fn->last()), retVal);
} catch (Error& e) {
f->eraseFromParent(); // Error reading body, remove function
cenv.pop();
@@ -296,28 +297,35 @@ LLVMEngine::compileIf(CEnv& cenv, AIf* aif)
BasicBlock* mergeBB = BasicBlock::Create("endif");
BasicBlock* nextBB = NULL;
Branches branches;
- for (size_t i = 1; i < aif->size() - 1; i += 2) {
- Value* condV = llVal(aif->at(i)->compile(cenv));
- BasicBlock* thenBB = BasicBlock::Create((format("then%1%") % ((i+1)/2)).str());
+ size_t idx = 1;
+ for (AIf::iterator i = aif->begin() + 1; ; ++i, idx += 2) {
+ AIf::iterator next = i;
+ if (++next == aif->end())
+ break;
- nextBB = BasicBlock::Create((format("else%1%") % ((i+1)/2)).str());
+ Value* condV = llVal((*i)->compile(cenv));
+ BasicBlock* thenBB = BasicBlock::Create((format("then%1%") % ((idx+1)/2)).str());
+
+ nextBB = BasicBlock::Create((format("else%1%") % ((idx+1)/2)).str());
engine->builder.CreateCondBr(condV, thenBB, nextBB);
// Emit then block for this condition
parent->getBasicBlockList().push_back(thenBB);
engine->builder.SetInsertPoint(thenBB);
- Value* thenV = llVal(aif->at(i + 1)->compile(cenv));
+ Value* thenV = llVal((*next)->compile(cenv));
engine->builder.CreateBr(mergeBB);
branches.push_back(make_pair(thenV, engine->builder.GetInsertBlock()));
parent->getBasicBlockList().push_back(nextBB);
engine->builder.SetInsertPoint(nextBB);
+
+ i = next; // jump 2 each iteration (to the next predicate)
}
// Emit final else block
engine->builder.SetInsertPoint(nextBB);
- Value* elseV = llVal(aif->at(aif->size() - 1)->compile(cenv));
+ Value* elseV = llVal(aif->last()->compile(cenv));
engine->builder.CreateBr(mergeBB);
branches.push_back(make_pair(elseV, engine->builder.GetInsertBlock()));
@@ -335,10 +343,12 @@ LLVMEngine::compileIf(CEnv& cenv, AIf* aif)
CVal
LLVMEngine::compilePrimitive(CEnv& cenv, APrimitive* prim)
{
+ APrimitive::iterator i = prim->begin();
+
LLVMEngine* engine = reinterpret_cast<LLVMEngine*>(cenv.engine());
- Value* a = llVal(prim->at(1)->compile(cenv));
- Value* b = llVal(prim->at(2)->compile(cenv));
- bool isFloat = cenv.type(prim->at(1))->str() == "Float";
+ bool isFloat = cenv.type(*++i)->str() == "Float";
+ Value* a = llVal((*i++)->compile(cenv));
+ Value* b = llVal((*i++)->compile(cenv));
const string n = prim->head()->to<ASymbol*>()->str();
// Binary arithmetic operations
@@ -353,8 +363,8 @@ LLVMEngine::compilePrimitive(CEnv& cenv, APrimitive* prim)
if (n == "%") op = isFloat ? Instruction::FRem : Instruction::SRem;
if (op != 0) {
Value* val = engine->builder.CreateBinOp(op, a, b);
- for (size_t i = 3; i < prim->size(); ++i)
- val = engine->builder.CreateBinOp(op, val, llVal(prim->at(i)->compile(cenv)));
+ while (i != prim->end())
+ val = engine->builder.CreateBinOp(op, val, llVal((*i++)->compile(cenv)));
return val;
}
diff --git a/src/pprint.cpp b/src/pprint.cpp
index 1632f02..3f2a5b8 100644
--- a/src/pprint.cpp
+++ b/src/pprint.cpp
@@ -56,8 +56,12 @@ operator<<(ostream& out, const AST* ast)
const ATuple* tup = ast->to<const ATuple*>();
if (tup) {
out << "(";
- for (size_t i = 0; i != tup->size(); ++i)
- out << tup->at(i) << ((i != tup->size() - 1) ? " " : "");
+ for (ATuple::const_iterator i = tup->begin(); i != tup->end(); ) {
+ ATuple::const_iterator next = i;
+ ++next;
+ out << (*i) << ((next != tup->end()) ? " " : "");
+ i = next;
+ }
return out << ")";
}
@@ -69,6 +73,7 @@ pprint_internal(ostream& out, const AST* ast, unsigned indent)
{
const ATuple* tup = ast->to<const ATuple*>();
if (tup && tup->size() > 0) {
+ ATuple::const_iterator i = tup->begin() + 1;
const string head = tup->head()->str();
const ASymbol* headSym = tup->head()->to<const ASymbol*>();
out << "(";
@@ -77,16 +82,16 @@ pprint_internal(ostream& out, const AST* ast, unsigned indent)
if (tup->size() > 1) {
out << " ";
if (headSym && headSym->cppstr == "fn") {
- out << tup->at(1);
+ out << *i;
child_indent = indent + 4;
} else {
child_indent += head.length() + 1;
- pprint_internal(out, tup->at(1), child_indent);
+ pprint_internal(out, *i, child_indent);
}
}
- for (size_t i = 2; i < tup->size(); ++i) {
+ while (++i != tup->end()) {
out << endl << string().insert(0, child_indent, ' ');
- pprint_internal(out, tup->at(i), child_indent);
+ pprint_internal(out, *i, child_indent);
}
out << ")";
if (headSym && headSym->cppstr == "fn")
diff --git a/src/tuplr.cpp b/src/tuplr.cpp
index 867897d..bc4ac43 100644
--- a/src/tuplr.cpp
+++ b/src/tuplr.cpp
@@ -38,6 +38,7 @@ print_usage(char* name, bool error)
os << " -h Display this help and exit" << endl;
os << " -r Enter REPL after evaluating files" << endl;
os << " -p Pretty-print input only" << endl;
+ os << " -b BACKEND Backend (llvm or c)" << endl;
os << " -g Debug (disable optimisation)" << endl;
os << " -d Dump assembly output" << endl;
os << " -e EXPRESSION Evaluate EXPRESSION" << endl;
diff --git a/src/tuplr.hpp b/src/tuplr.hpp
index 7494cdb..b1bb985 100644
--- a/src/tuplr.hpp
+++ b/src/tuplr.hpp
@@ -33,7 +33,8 @@
#include <vector>
#include <boost/format.hpp>
-#define FOREACH(IT, i, c) for (IT i = (c).begin(); i != (c).end(); ++i)
+#define FOREACH(IT, i, c) for (IT i = (c).begin(); i != (c).end(); ++i)
+#define FOREACHP(IT, i, c) for (IT i = (c)->begin(); i != (c)->end(); ++i)
#define THROW_IF(cond, error, ...) { if (cond) throw Error(error, __VA_ARGS__); }
using namespace std;
@@ -243,8 +244,8 @@ struct ATuple : public AST {
}
const AST* head() const { assert(_len > 0); return _vec[0]; }
AST* head() { assert(_len > 0); return _vec[0]; }
- const AST* at(size_t i) const { assert(i < _len); return _vec[i]; }
- AST*& at(size_t i) { assert(i < _len); return _vec[i]; }
+ const AST* last() const { return _vec[_len - 1]; }
+ AST* last() { return _vec[_len - 1]; }
size_t size() const { return _len; }
bool empty() const { return _len == 0; }
@@ -259,20 +260,20 @@ struct ATuple : public AST {
const ATuple* rt = rhs.to<const ATuple*>();
if (!rt || rt->size() != size()) return false;
const_iterator l = begin();
- FOREACH(const_iterator, r, *rt)
+ FOREACHP(const_iterator, r, rt)
if (!(*(*l++) == *(*r)))
return false;
return true;
}
bool contains(AST* child) const {
if (*this == *child) return true;
- FOREACH(const_iterator, p, *this)
+ FOREACHP(const_iterator, p, this)
if (**p == *child || (*p)->contains(child))
return true;
return false;
}
void constrain(TEnv& tenv, Constraints& c) const;
- void lift(CEnv& cenv) { FOREACH(iterator, t, *this) (*t)->lift(cenv); }
+ void lift(CEnv& cenv) { FOREACHP(iterator, t, this) (*t)->lift(cenv); }
CVal compile(CEnv& cenv) { throw Error(loc, "tuple compiled"); }
@@ -288,12 +289,14 @@ struct AType : public ATuple {
AType(Cursor c) : ATuple(c), kind(EXPR), id(0) {}
AType(Cursor c, AST* ast, va_list args) : ATuple(c, ast, args), kind(EXPR), id(0) {}
CVal compile(CEnv& cenv) { return NULL; }
+ const ATuple* prot() const { assert(kind == EXPR); return (*(begin() + 1))->to<const ATuple*>(); }
+ ATuple* prot() { assert(kind == EXPR); return (*(begin() + 1))->to<ATuple*>(); }
bool concrete() const {
switch (kind) {
case VAR: return false;
case PRIM: return head()->str() != "Nothing";
case EXPR:
- FOREACH(const_iterator, t, *this) {
+ FOREACHP(const_iterator, t, this) {
AType* kid = (*t)->to<AType*>();
if (kid && !kid->concrete())
return false;
@@ -365,8 +368,8 @@ struct AFn : public ATuple {
AST* cps(TEnv& tenv, AST* cont);
void lift(CEnv& cenv);
CVal compile(CEnv& cenv);
- const ATuple* prot() const { return at(1)->to<const ATuple*>(); }
- ATuple* prot() { return at(1)->to<ATuple*>(); }
+ const ATuple* prot() const { return (*(begin() + 1))->to<const ATuple*>(); }
+ ATuple* prot() { return (*(begin() + 1))->to<ATuple*>(); }
/// System level implementations of this (polymorphic) fn
struct Impls : public list< pair<AType*, CFunc> > {
CFunc find(AType* type) const {
@@ -395,14 +398,17 @@ struct ADef : public ACall {
ADef(const ATuple* exp) : ACall(exp) {}
ADef(Cursor c, AST* ast, va_list args) : ACall(c, ast, args) {}
const ASymbol* sym() const {
- const ASymbol* sym = at(1)->to<const ASymbol*>();
+ const AST* name = *(begin() + 1);
+ const ASymbol* sym = name->to<const ASymbol*>();
if (!sym) {
- const ATuple* tup = at(1)->to<const ATuple*>();
+ const ATuple* tup = name->to<const ATuple*>();
if (tup && !tup->empty())
return tup->head()->to<const ASymbol*>();
}
return sym;
}
+ const AST* body() const { return *(begin() + 2); }
+ AST* body() { return *(begin() + 2); }
void constrain(TEnv& tenv, Constraints& c) const;
AST* cps(TEnv& tenv, AST* cont);
void lift(CEnv& cenv);
@@ -476,7 +482,7 @@ struct PEnv : private map<const string, ASymbol*> {
}
ATuple* parseTuple(const ATuple* e) {
ATuple* ret = new ATuple(e->loc);
- FOREACH(ATuple::const_iterator, i, *e)
+ FOREACHP(ATuple::const_iterator, i, e)
ret->push_back(parse(*i));
return ret;
}
diff --git a/src/unify.cpp b/src/unify.cpp
index 38f2583..5284bea 100644
--- a/src/unify.cpp
+++ b/src/unify.cpp
@@ -31,7 +31,7 @@ TEnv::buildSubst(AType* genericT, const AType& argsT)
Subst subst;
// Build substitution to apply to generic type
- const ATuple* genericProtT = genericT->at(1)->as<const ATuple*>();
+ const ATuple* genericProtT = (*(genericT->begin() + 1))->as<const ATuple*>();
assert(argsT.size() == genericProtT->size());
ATuple::const_iterator g = genericProtT->begin();
AType::const_iterator a = argsT.begin();
@@ -41,9 +41,11 @@ TEnv::buildSubst(AType* genericT, const AType& argsT)
if (callArgT->kind == AType::EXPR) {
assert(genericArgT->kind == AType::EXPR);
assert(callArgT->size() == genericArgT->size());
- for (size_t i = 0; i < callArgT->size(); ++i) {
- const AType* gT = genericArgT->at(i)->to<const AType*>();
- AType* aT = callArgT->at(i)->to<AType*>();
+ ATuple::const_iterator gi = genericArgT->begin();
+ ATuple::const_iterator ci = callArgT->begin();
+ for (; gi != genericArgT->end(); ++gi, ++ci) {
+ const AType* gT = (*gi)->to<const AType*>();
+ AType* aT = (*ci)->to<AType*>();
if (gT && aT)
subst.add(gT, aT);
}
@@ -68,11 +70,11 @@ static void
substitute(ATuple* tup, const AST* from, AST* to)
{
if (!tup) return;
- for (size_t i = 0; i < tup->size(); ++i)
- if (*tup->at(i) == *from)
- tup->at(i) = to;
- else if (tup->at(i) != to)
- substitute(tup->at(i)->to<ATuple*>(), from, to);
+ FOREACHP(ATuple::iterator, i, tup)
+ if (**i == *from)
+ *i = to;
+ else if (*i != to)
+ substitute((*i)->to<ATuple*>(), from, to);
}
/// Compose two substitutions (TAPL 22.1.1)
@@ -124,11 +126,13 @@ unify(const Constraints& constraints)
cp.replace(t, s);
return Subst::compose(unify(cp), Subst(t, s));
} else if (s->kind == AType::EXPR && s->kind == t->kind && s->size() == t->size()) {
- for (size_t i = 1; i < s->size(); ++i) {
- AType* si = s->at(i)->to<AType*>();
- AType* ti = t->at(i)->to<AType*>();
- assert(si && ti);
- cp.push_back(Constraint(si, ti, si->loc));
+ AType::iterator si = s->begin() + 1;
+ AType::iterator ti = t->begin() + 1;
+ for (; si != s->end(); ++si, ++ti) {
+ AType* st = (*si)->to<AType*>();
+ AType* tt = (*ti)->to<AType*>();
+ assert(st && tt);
+ cp.push_back(Constraint(st, tt, st->loc));
}
return unify(cp);
} else {