diff options
author | David Robillard <d@drobilla.net> | 2009-10-15 19:24:00 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2009-10-15 19:24:00 +0000 |
commit | c139e62f1fa1341eaa9c6f7b7d8e54601721a329 (patch) | |
tree | a20204e68f4ed3128973cd32f443cb9a8f91a9c4 | |
parent | 7743d332e41c7795dcbaa49511293f22597e4db7 (diff) | |
download | resp-c139e62f1fa1341eaa9c6f7b7d8e54601721a329.tar.gz resp-c139e62f1fa1341eaa9c6f7b7d8e54601721a329.tar.bz2 resp-c139e62f1fa1341eaa9c6f7b7d8e54601721a329.zip |
Remove all use of ATuple::at().
git-svn-id: http://svn.drobilla.net/resp/tuplr@229 ad02d1e2-f140-0410-9f75-f8b11f17cedd
-rw-r--r-- | src/c.cpp | 67 | ||||
-rw-r--r-- | src/compile.cpp | 11 | ||||
-rw-r--r-- | src/constrain.cpp | 73 | ||||
-rw-r--r-- | src/cps.cpp | 47 | ||||
-rw-r--r-- | src/gc.cpp | 2 | ||||
-rw-r--r-- | src/lift.cpp | 18 | ||||
-rw-r--r-- | src/llvm.cpp | 66 | ||||
-rw-r--r-- | src/pprint.cpp | 17 | ||||
-rw-r--r-- | src/tuplr.cpp | 1 | ||||
-rw-r--r-- | src/tuplr.hpp | 30 | ||||
-rw-r--r-- | src/unify.cpp | 32 |
11 files changed, 211 insertions, 153 deletions
@@ -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); } } @@ -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 { |