diff options
author | David Robillard <d@drobilla.net> | 2010-08-22 20:20:38 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2010-08-22 20:20:38 +0000 |
commit | 8338b52abc0e5a1c0893526bde2d347f1891773e (patch) | |
tree | ffea8eedbb766ff08dd6b30636b9060232d1ebb8 | |
parent | b4dba561084b7ce60a8b1cfdb4e3b9de87de8d35 (diff) | |
download | resp-8338b52abc0e5a1c0893526bde2d347f1891773e.tar.gz resp-8338b52abc0e5a1c0893526bde2d347f1891773e.tar.bz2 resp-8338b52abc0e5a1c0893526bde2d347f1891773e.zip |
Simplify Engine function compilation interface.
Removes duplicated code in various backends and reduces Engine code
knowledge of AFn specifics (which belongs in compile.cpp).
git-svn-id: http://svn.drobilla.net/resp/resp@268 ad02d1e2-f140-0410-9f75-f8b11f17cedd
-rw-r--r-- | src/c.cpp | 49 | ||||
-rw-r--r-- | src/compile.cpp | 21 | ||||
-rw-r--r-- | src/llvm.cpp | 51 | ||||
-rw-r--r-- | src/repl.cpp | 10 | ||||
-rw-r--r-- | src/resp.hpp | 8 |
5 files changed, 59 insertions, 80 deletions
@@ -101,10 +101,13 @@ struct CEngine : public Engine { } CFunc startFunction(CEnv& cenv, - const std::string& name, const ATuple* args, const AType* retT, const ATuple& argsT) + const std::string& name, const ATuple* args, const AType* type) { + const AType* argsT = type->prot()->as<const AType*>(); + const AType* retT = type->last()->as<const AType*>(); + vector<const Type*> cprot; - FOREACH(ATuple::const_iterator, i, argsT) { + FOREACHP(ATuple::const_iterator, i, argsT) { AType* at = (*i)->as<AType*>(); THROW_IF(!llType(at), Cursor(), string("non-concrete parameter :: ") + at->str()) @@ -118,10 +121,10 @@ struct CEngine : public Engine { f->returnType = *llType(retT); f->name = name; f->text += f->returnType + "\n" + f->name + "("; - ATuple::const_iterator ai = argsT.begin(); + ATuple::const_iterator ai = argsT->begin(); ATuple::const_iterator ni = args->begin(); - for (; ai != argsT.end(); ++ai, ++ni) { - if (ai != argsT.begin()) + for (; ai != argsT->end(); ++ai, ++ni) { + if (ai != argsT->begin()) f->text += ", "; f->text += *llType((*ai)->as<const AType*>()) + " " + (*ni)->as<const ASymbol*>()->cppstr; } @@ -131,6 +134,8 @@ struct CEngine : public Engine { return f; } + void pushFunctionArgs(CEnv& cenv, const AFn* fn, const AType* type, CFunc f); + void finishFunction(CEnv& cenv, CFunc f, CVal ret) { out += "return " + *(Value*)ret + ";\n}\n\n"; } @@ -149,8 +154,6 @@ struct CEngine : public Engine { return varname; } - CFunc compileFunction(CEnv& cenv, const AFn* fn, const AType* type); - CVal compileTup(CEnv& cenv, const AType* type, const vector<CVal>& fields); CVal compileDot(CEnv& cenv, CVal tup, int32_t index); CVal compileLiteral(CEnv& cenv, const AST* lit); @@ -206,22 +209,12 @@ CEngine::compileString(CEnv& cenv, const char* str) return new Value(string("\"") + str + "\""); } -CFunc -CEngine::compileFunction(CEnv& cenv, const AFn* fn, const AType* type) +void +CEngine::pushFunctionArgs(CEnv& cenv, const AFn* fn, const AType* type, CFunc f) { - assert(type->concrete()); - - const AType* argsT = type->prot()->as<const AType*>(); - const AType* retT = type->last()->as<const AType*>(); - Subst argsSubst = cenv.tenv.buildSubst(type, *argsT); - - // Write function declaration - const string name = (fn->name == "") ? cenv.penv.gensymstr("_fn") : fn->name; - Function* f = llFunc(cenv.engine()->startFunction(cenv, name, fn->prot(), retT, *argsT)); - cenv.push(); - Subst oldSubst = cenv.tsubst; - cenv.tsubst = Subst::compose(cenv.tsubst, argsSubst); + + const AType* argsT = type->prot()->as<const AType*>(); // Bind argument values in CEnv vector<Value*> args; @@ -233,20 +226,6 @@ CEngine::compileFunction(CEnv& cenv, const AFn* fn, const AType* type) THROW_IF(!lt, fn->loc, "untyped parameter\n"); cenv.def((*p)->as<ASymbol*>(), *p, t, new string((*p)->str())); } - - // Write function body - try { - CVal retVal = NULL; - for (AFn::const_iterator i = fn->begin() + 2; i != fn->end(); ++i) - retVal = (*i)->compile(cenv); - cenv.engine()->finishFunction(cenv, f, retVal); - } catch (Error& e) { - cenv.pop(); - throw e; - } - cenv.tsubst = oldSubst; - cenv.pop(); - return f; } CVal diff --git a/src/compile.cpp b/src/compile.cpp index 66c3abe..f954b8e 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -67,7 +67,26 @@ AFn::compile(CEnv& cenv) const throw() if (f) return f; - f = cenv.engine()->compileFunction(cenv, this, type); + // Write function declaration + f = cenv.engine()->startFunction(cenv, name, prot(), type); + + // Create a new environment frame and bind argument values + cenv.engine()->pushFunctionArgs(cenv, this, type, f); + assert(!cenv.currentFn); + cenv.currentFn = f; + + // Write function body + CVal retVal = NULL; + for (AFn::const_iterator i = begin() + 2; i != end(); ++i) + retVal = (*i)->compile(cenv); + + // Write function conclusion + cenv.engine()->finishFunction(cenv, f, retVal); + + // Pop environment frame + cenv.pop(); + cenv.currentFn = NULL; + cenv.vals.def(cenv.penv.sym(name), f); cenv.addImpl(this, f); return f; diff --git a/src/llvm.cpp b/src/llvm.cpp index 7ba3d54..8b4deaa 100644 --- a/src/llvm.cpp +++ b/src/llvm.cpp @@ -128,12 +128,15 @@ struct LLVMEngine : public Engine { } CFunc startFunction(CEnv& cenv, - const std::string& name, const ATuple* args, const AType* retT, const ATuple& argsT) + const std::string& name, const ATuple* args, const AType* type) { + const AType* argsT = type->prot()->as<const AType*>(); + const AType* retT = type->last()->as<const AType*>(); + Function::LinkageTypes linkage = Function::ExternalLinkage; vector<const Type*> cprot; - FOREACH(ATuple::const_iterator, i, argsT) { + FOREACHP(ATuple::const_iterator, i, argsT) { AType* at = (*i)->as<AType*>(); THROW_IF(!llType(at), Cursor(), string("non-concrete parameter :: ") + at->str()) @@ -143,10 +146,12 @@ struct LLVMEngine : public Engine { THROW_IF(!llType(retT), Cursor(), (format("return has non-concrete type `%1%'") % retT->str()).str()); + const string llName = (name == "") ? cenv.penv.gensymstr("_fn") : name; + FunctionType* fT = FunctionType::get(llType(retT), cprot, false); - Function* f = Function::Create(fT, linkage, name, module); + Function* f = Function::Create(fT, linkage, llName, module); - // Note f->getName() may be different from name + // Note f->getName() may be different from llName // however LLVM chooses to mangle is fine, we keep a pointer // Set argument names in generated code @@ -159,6 +164,8 @@ struct LLVMEngine : public Engine { return f; } + + void pushFunctionArgs(CEnv& cenv, const AFn* fn, const AType* type, CFunc f); void finishFunction(CEnv& cenv, CFunc f, CVal ret) { builder.CreateRet(llVal(ret)); @@ -184,8 +191,6 @@ struct LLVMEngine : public Engine { return builder.CreateCall(llFunc(f), llArgs.begin(), llArgs.end()); } - CFunc compileFunction(CEnv& cenv, const AFn* fn, const AType* type); - CVal compileTup(CEnv& cenv, const AType* type, const vector<CVal>& fields); CVal compileDot(CEnv& cenv, CVal tup, int32_t index); CVal compileLiteral(CEnv& cenv, const AST* lit); @@ -320,19 +325,12 @@ LLVMEngine::compileString(CEnv& cenv, const char* str) return builder.CreateGlobalStringPtr(str); } -CFunc -LLVMEngine::compileFunction(CEnv& cenv, const AFn* fn, const AType* type) +void +LLVMEngine::pushFunctionArgs(CEnv& cenv, const AFn* fn, const AType* type, CFunc f) { - assert(type->concrete()); + cenv.push(); const AType* argsT = type->prot()->as<const AType*>(); - const AType* retT = type->last()->as<const AType*>(); - - // Write function declaration - const string name = (fn->name == "") ? cenv.penv.gensymstr("_fn") : fn->name; - Function* f = llFunc(cenv.engine()->startFunction(cenv, name, fn->prot(), retT, *argsT)); - - cenv.push(); // Bind argument values in CEnv vector<Value*> args; @@ -340,31 +338,12 @@ LLVMEngine::compileFunction(CEnv& cenv, const AFn* fn, const AType* type) ATuple::const_iterator pT = argsT->begin(); assert(fn->prot()->size() == argsT->size()); assert(fn->prot()->size() == f->num_args()); - for (Function::arg_iterator a = f->arg_begin(); a != f->arg_end(); ++a, ++p, ++pT) { + for (Function::arg_iterator a = llFunc(f)->arg_begin(); a != llFunc(f)->arg_end(); ++a, ++p, ++pT) { const AType* t = (*pT)->as<const AType*>(); const Type* lt = llType(t); THROW_IF(!lt, fn->loc, "untyped parameter\n"); cenv.def((*p)->as<ASymbol*>(), *p, t, &*a); } - - assert(!cenv.currentFn); - - // Write function body - try { - cenv.currentFn = f; - CVal retVal = NULL; - for (AFn::const_iterator i = fn->begin() + 2; i != fn->end(); ++i) - retVal = (*i)->compile(cenv); - cenv.engine()->finishFunction(cenv, f, retVal); - } catch (Error& e) { - f->eraseFromParent(); // Error reading body, remove function - cenv.pop(); - cenv.currentFn = NULL; - throw e; - } - cenv.pop(); - cenv.currentFn = NULL; - return f; } CVal diff --git a/src/repl.cpp b/src/repl.cpp index d2b8270..5850e66 100644 --- a/src/repl.cpp +++ b/src/repl.cpp @@ -147,10 +147,11 @@ eval(CEnv& cenv, const string& name, istream& is, bool execute) } const AType* type = cenv.type(exprs.back()); - + const AType* fnT = tup<const AType>(cursor, cenv.tenv.Fn, new AType(cursor), type, 0); + // Create function for top-level of program - f = cenv.engine()->startFunction(cenv, "main", new ATuple(cursor), type, ATuple(cursor)); - + f = cenv.engine()->startFunction(cenv, "main", new ATuple(cursor), fnT); + // Compile expressions (other than function definitions) into it for (list<AST*>::const_iterator i = exprs.begin(); i != exprs.end(); ++i) val = (*i)->compile(cenv); @@ -188,10 +189,11 @@ repl(CEnv& cenv) Code lifted; ast = ast->lift(cenv, lifted); const AType* type = cenv.type(ast); + const AType* fnT = tup<const AType>(cursor, cenv.tenv.Fn, new AType(cursor), type, 0); CFunc f = NULL; try { // Create function for this repl loop - f = cenv.engine()->startFunction(cenv, replFnName, new ATuple(cursor), type, ATuple(cursor)); + f = cenv.engine()->startFunction(cenv, replFnName, new ATuple(cursor), fnT); cenv.engine()->finishFunction(cenv, f, ast->compile(cenv)); callPrintCollect(cenv, f, ast, type, true); if (cenv.args.find("-d") != cenv.args.end()) diff --git a/src/resp.hpp b/src/resp.hpp index 5d3a93c..6e4dc77 100644 --- a/src/resp.hpp +++ b/src/resp.hpp @@ -654,18 +654,18 @@ Subst unify(const Constraints& c); struct Engine { virtual ~Engine() {} + typedef const vector<CVal> ValVec; + virtual CFunc startFunction( CEnv& cenv, const std::string& name, const ATuple* args, - const AType* retT, - const ATuple& argsT) = 0; + const AType* type) = 0; - typedef const vector<CVal> ValVec; + virtual void pushFunctionArgs(CEnv& cenv, const AFn* fn, const AType* type, CFunc f) = 0; virtual void finishFunction(CEnv& cenv, CFunc f, CVal ret) = 0; virtual void eraseFunction(CEnv& cenv, CFunc f) = 0; - virtual CFunc compileFunction(CEnv& cenv, const AFn* fn, const AType* type) = 0; virtual CVal compileTup(CEnv& cenv, const AType* t, ValVec& f) = 0; virtual CVal compileDot(CEnv& cenv, CVal tup, int32_t index) = 0; virtual CVal compileLiteral(CEnv& cenv, const AST* lit) = 0; |