aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2010-08-22 20:20:38 +0000
committerDavid Robillard <d@drobilla.net>2010-08-22 20:20:38 +0000
commit8338b52abc0e5a1c0893526bde2d347f1891773e (patch)
treeffea8eedbb766ff08dd6b30636b9060232d1ebb8
parentb4dba561084b7ce60a8b1cfdb4e3b9de87de8d35 (diff)
downloadresp-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.cpp49
-rw-r--r--src/compile.cpp21
-rw-r--r--src/llvm.cpp51
-rw-r--r--src/repl.cpp10
-rw-r--r--src/resp.hpp8
5 files changed, 59 insertions, 80 deletions
diff --git a/src/c.cpp b/src/c.cpp
index 77c5fbe..6bd3a2d 100644
--- a/src/c.cpp
+++ b/src/c.cpp
@@ -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;