aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/c.cpp6
-rw-r--r--src/compile.cpp14
-rw-r--r--src/constrain.cpp22
-rw-r--r--src/lift.cpp43
-rw-r--r--src/llvm.cpp6
-rw-r--r--src/parse.cpp2
-rw-r--r--src/resp.cpp4
-rw-r--r--src/resp.hpp32
8 files changed, 64 insertions, 65 deletions
diff --git a/src/c.cpp b/src/c.cpp
index c099452..44aed8d 100644
--- a/src/c.cpp
+++ b/src/c.cpp
@@ -134,7 +134,7 @@ struct CEngine : public Engine {
return f;
}
- void pushFunctionArgs(CEnv& cenv, const AFn* fn, const AType* type, CFunc f);
+ void pushFunctionArgs(CEnv& cenv, const ACall* fn, const AType* type, CFunc f);
void finishFunction(CEnv& cenv, CFunc f, CVal ret) {
out += "return " + *(Value*)ret + ";\n}\n\n";
@@ -211,7 +211,7 @@ CEngine::compileString(CEnv& cenv, const char* str)
}
void
-CEngine::pushFunctionArgs(CEnv& cenv, const AFn* fn, const AType* type, CFunc f)
+CEngine::pushFunctionArgs(CEnv& cenv, const ACall* fn, const AType* type, CFunc f)
{
cenv.push();
@@ -219,7 +219,7 @@ CEngine::pushFunctionArgs(CEnv& cenv, const AFn* fn, const AType* type, CFunc f)
// Bind argument values in CEnv
vector<Value*> args;
- AFn::const_iterator p = fn->prot()->begin();
+ ATuple::const_iterator p = fn->prot()->begin();
ATuple::const_iterator pT = argsT->begin();
for (; p != fn->prot()->end(); ++p, ++pT) {
const AType* t = (*pT)->as<const AType*>();
diff --git a/src/compile.cpp b/src/compile.cpp
index cf777f8..14cd562 100644
--- a/src/compile.cpp
+++ b/src/compile.cpp
@@ -34,7 +34,7 @@ compile_symbol(CEnv& cenv, const ASymbol* sym) throw()
}
static CVal
-compile_fn(CEnv& cenv, const AFn* fn) throw()
+compile_fn(CEnv& cenv, const ACall* fn) throw()
{
const AType* type = cenv.type(fn);
CFunc f = cenv.findImpl(fn, type);
@@ -42,7 +42,7 @@ compile_fn(CEnv& cenv, const AFn* fn) throw()
return f;
// Write function declaration
- f = cenv.engine()->startFunction(cenv, fn->name, fn->prot(), type);
+ f = cenv.engine()->startFunction(cenv, cenv.name(fn), fn->prot(), type);
// Create a new environment frame and bind argument values
cenv.engine()->pushFunctionArgs(cenv, fn, type, f);
@@ -51,7 +51,7 @@ compile_fn(CEnv& cenv, const AFn* fn) throw()
// Write function body
CVal retVal = NULL;
- for (AFn::const_iterator i = fn->iter_at(2); i != fn->end(); ++i)
+ for (ATuple::const_iterator i = fn->iter_at(2); i != fn->end(); ++i)
retVal = resp_compile(cenv, *i);
// Write function conclusion
@@ -61,7 +61,7 @@ compile_fn(CEnv& cenv, const AFn* fn) throw()
cenv.pop();
cenv.currentFn = NULL;
- cenv.vals.def(cenv.penv.sym(fn->name), f);
+ cenv.vals.def(cenv.penv.sym(cenv.name(fn)), f);
cenv.addImpl(fn, f);
return f;
}
@@ -155,10 +155,6 @@ resp_compile(CEnv& cenv, const AST* ast) throw()
if (sym)
return compile_symbol(cenv, sym);
- const AFn* fn = ast->to<const AFn*>();
- if (fn)
- return compile_fn(cenv, fn);
-
const AType* type = ast->to<const AType*>();
if (type)
return compile_type(cenv, type);
@@ -169,6 +165,8 @@ resp_compile(CEnv& cenv, const AST* ast) throw()
const std::string form = sym ? sym->cppstr : "";
if (is_primitive(cenv.penv, call))
return cenv.engine()->compilePrimitive(cenv, ast->as<const ACall*>());
+ else if (form == "fn")
+ return compile_fn(cenv, call);
else if (form == "def")
return compile_def(cenv, call);
else if (form == "if")
diff --git a/src/constrain.cpp b/src/constrain.cpp
index cb7b700..2e23f7c 100644
--- a/src/constrain.cpp
+++ b/src/constrain.cpp
@@ -65,15 +65,17 @@ ATuple::constrain(TEnv& tenv, Constraints& c) const throw(Error)
c.constrain(tenv, this, t);
}
-void
-AFn::constrain(TEnv& tenv, Constraints& c) const throw(Error)
+static void
+constrain_fn(TEnv& tenv, Constraints& c, const ACall* call) throw(Error)
{
set<const ASymbol*> defs;
TEnv::Frame frame;
+ const ATuple* const prot = call->prot();
+
// Add parameters to environment frame
TList protT;
- for (ATuple::const_iterator i = prot()->begin(); i != prot()->end(); ++i) {
+ for (ATuple::const_iterator i = prot->begin(); i != prot->end(); ++i) {
const ASymbol* sym = (*i)->to<const ASymbol*>();
THROW_IF(!sym, (*i)->loc, "parameter name is not a symbol");
THROW_IF(defs.count(sym) != 0, sym->loc,
@@ -83,13 +85,13 @@ AFn::constrain(TEnv& tenv, Constraints& c) const throw(Error)
frame.push_back(make_pair(sym, tvar));
protT.push_back(const_cast<AType*>(tvar));
}
- protT.head->loc = loc;
+ protT.head->loc = call->loc;
- const_iterator i = iter_at(1);
+ ATuple::const_iterator i = call->iter_at(1);
c.constrain(tenv, *i, protT);
// Add internal definitions to environment frame
- for (++i; i != end(); ++i) {
+ for (++i; i != call->end(); ++i) {
const AST* exp = *i;
const ACall* call = exp->to<const ACall*>();
if (call && is_form(call, "def")) {
@@ -104,18 +106,18 @@ AFn::constrain(TEnv& tenv, Constraints& c) const throw(Error)
tenv.push(frame);
const AST* exp = NULL;
- for (i = iter_at(2); i != end(); ++i) {
+ for (i = call->iter_at(2); i != call->end(); ++i) {
exp = *i;
exp->constrain(tenv, c);
}
const AType* bodyT = tenv.var(exp);
- const AType* fnT = tup<const AType>(loc, tenv.Fn, protT.head, bodyT, 0);
+ const AType* fnT = tup<const AType>(call->loc, tenv.Fn, protT.head, bodyT, 0);
Object::pool.addRoot(fnT);
tenv.pop();
- c.constrain(tenv, this, fnT);
+ c.constrain(tenv, call, fnT);
}
static void
@@ -364,6 +366,8 @@ ACall::constrain(TEnv& tenv, Constraints& c) const throw(Error)
const std::string form = sym->cppstr;
if (is_primitive(tenv.penv, this))
constrain_primitive(tenv, c, this);
+ else if (form == "fn")
+ constrain_fn(tenv, c, this);
else if (form == "def")
constrain_def(tenv, c, this);
else if (form == "def-type")
diff --git a/src/lift.cpp b/src/lift.cpp
index 739d176..2df27c9 100644
--- a/src/lift.cpp
+++ b/src/lift.cpp
@@ -31,7 +31,7 @@ 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) {
+ if (!cenv.liftStack.empty() && cppstr == cenv.name(cenv.liftStack.top().fn)) {
return cenv.penv.sym("_me"); // Reference to innermost function
} else if (!cenv.penv.handler(true, cppstr)
&& !cenv.penv.handler(false, cppstr)
@@ -50,13 +50,15 @@ lift_symbol(CEnv& cenv, Code& code, ASymbol* sym) throw()
}
static AST*
-lift_fn(CEnv& cenv, Code& code, AFn* fn) throw()
+lift_fn(CEnv& cenv, Code& code, ACall* fn) throw()
{
- AFn* impl = new AFn(fn);
- const string nameBase = cenv.penv.gensymstr(((fn->name != "") ? fn->name : "fn").c_str());
- impl->name = "_" + nameBase;
+ ACall* impl = new ACall(fn);
+ const string fnName = cenv.name(fn);
+ const string nameBase = cenv.penv.gensymstr(((fnName != "") ? fnName : "fn").c_str());
+ const string implNameStr = string("_") + nameBase;
+ cenv.setName(impl, implNameStr);
- cenv.liftStack.push(CEnv::FreeVars(fn, impl->name));
+ cenv.liftStack.push(CEnv::FreeVars(fn, implNameStr));
// Create a new stub environment frame for parameters
cenv.push();
@@ -64,7 +66,7 @@ lift_fn(CEnv& cenv, Code& code, AFn* fn) throw()
AType::const_iterator tp = type->prot()->begin();
AType* implProtT = new AType(*type->prot()->as<const AType*>());
ATuple::iterator ip = implProtT->begin();
- for (AFn::const_iterator p = fn->prot()->begin(); p != fn->prot()->end(); ++p) {
+ for (ATuple::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);
@@ -84,8 +86,8 @@ lift_fn(CEnv& cenv, Code& code, AFn* fn) throw()
// Lift body
const AType* implRetT = NULL;
- AFn::iterator ci = impl->iter_at(2);
- for (AFn::iterator i = fn->iter_at(2); i != fn->end(); ++i, ++ci) {
+ ATuple::iterator ci = impl->iter_at(2);
+ for (ATuple::iterator i = fn->iter_at(2); i != fn->end(); ++i, ++ci) {
*ci = resp_lift(cenv, code, *i);
implRetT = cenv.type(*ci);
}
@@ -96,7 +98,7 @@ lift_fn(CEnv& cenv, Code& code, AFn* fn) throw()
*impl->prot()->begin() = cenv.penv.sym("_me");
// Create definition for implementation fn
- ASymbol* implName = cenv.penv.sym(impl->name);
+ ASymbol* implName = cenv.penv.sym(implNameStr);
ACall* def = tup<ACall>(fn->loc, cenv.penv.sym("def"), implName, impl, NULL);
code.push_back(def);
@@ -122,8 +124,8 @@ lift_fn(CEnv& cenv, Code& code, AFn* fn) throw()
cenv.setType(cons, consT);
cenv.def(implName, impl, implT, NULL);
- if (fn->name != "")
- cenv.def(cenv.penv.sym(fn->name), fn, consT, NULL);
+ if (cenv.name(fn) != "")
+ cenv.def(cenv.penv.sym(cenv.name(fn)), fn, consT, NULL);
return cons;
}
@@ -142,12 +144,12 @@ lift_call(CEnv& cenv, Code& code, ACall* call) throw()
const AType* copyT = NULL;
ASymbol* sym = call->head()->to<ASymbol*>();
- if (sym && !cenv.liftStack.empty() && sym->cppstr == cenv.liftStack.top().fn->name) {
+ if (sym && !cenv.liftStack.empty() && sym->cppstr == cenv.name(cenv.liftStack.top().fn)) {
/* 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 (call->head()->to<AFn*>()) {
+ } else if (is_form(call, "fn")) {
/* Special case: ((fn ...) ...)
* Lifting (fn ...) yields: (Fn _impl ...).
* We don't want ((Fn _impl ...) (Fn _impl ...) ...),
@@ -184,9 +186,8 @@ lift_def(CEnv& cenv, Code& code, ACall* def) throw()
const ASymbol* const sym = def->list_ref(1)->as<const ASymbol*>();
AST* const body = def->list_ref(2);
cenv.def(sym, body, cenv.type(body), NULL);
- AFn* c = body->to<AFn*>();
- if (c)
- c->name = sym->str();
+ if (is_form(body, "fn"))
+ cenv.setName(body->as<const ACall*>(), sym->str());
assert(def->list_ref(1)->to<const ASymbol*>());
List<ACall, AST> copy;
@@ -198,7 +199,7 @@ lift_def(CEnv& cenv, Code& code, ACall* def) throw()
cenv.setTypeSameAs(copy, def);
if (copy.head->list_ref(1) == copy.head->list_ref(2))
- return NULL; // Definition created by AFn::lift when body was lifted
+ return NULL; // Definition created by lift_fn when body was lifted
cenv.def(copy.head->list_ref(1)->as<const ASymbol*>(),
copy.head->list_ref(2),
@@ -228,16 +229,14 @@ resp_lift(CEnv& cenv, Code& code, AST* ast) throw()
if (sym)
return lift_symbol(cenv, code, sym);
- AFn* const fn = ast->to<AFn*>();
- if (fn)
- return lift_fn(cenv, code, fn);
-
ACall* const call = ast->to<ACall*>();
if (call) {
const ASymbol* const sym = call->head()->to<const ASymbol*>();
const std::string form = sym ? sym->cppstr : "";
if (is_primitive(cenv.penv, call))
return lift_builtin_call(cenv, code, call);
+ else if (form == "fn")
+ return lift_fn(cenv, code, call);
else if (form == "def")
return lift_def(cenv, code, call);
else if (form == "if")
diff --git a/src/llvm.cpp b/src/llvm.cpp
index 4019f9c..82d2f79 100644
--- a/src/llvm.cpp
+++ b/src/llvm.cpp
@@ -166,7 +166,7 @@ struct LLVMEngine : public Engine {
return f;
}
- void pushFunctionArgs(CEnv& cenv, const AFn* fn, const AType* type, CFunc f);
+ void pushFunctionArgs(CEnv& cenv, const ACall* fn, const AType* type, CFunc f);
void finishFunction(CEnv& cenv, CFunc f, CVal ret) {
builder.CreateRet(llVal(ret));
@@ -330,7 +330,7 @@ LLVMEngine::compileString(CEnv& cenv, const char* str)
}
void
-LLVMEngine::pushFunctionArgs(CEnv& cenv, const AFn* fn, const AType* type, CFunc f)
+LLVMEngine::pushFunctionArgs(CEnv& cenv, const ACall* fn, const AType* type, CFunc f)
{
cenv.push();
@@ -338,7 +338,7 @@ LLVMEngine::pushFunctionArgs(CEnv& cenv, const AFn* fn, const AType* type, CFunc
// Bind argument values in CEnv
vector<Value*> args;
- AFn::const_iterator p = fn->prot()->begin();
+ ATuple::const_iterator p = fn->prot()->begin();
ATuple::const_iterator pT = argsT->begin();
assert(fn->prot()->size() == argsT->size());
assert(fn->prot()->size() == f->num_args());
diff --git a/src/parse.cpp b/src/parse.cpp
index 83a4934..35765a9 100644
--- a/src/parse.cpp
+++ b/src/parse.cpp
@@ -154,7 +154,7 @@ parseFn(PEnv& penv, const AST* exp, void* arg)
while (a != texp->end())
ret.push_back(penv.parse(*a++));
ret.head->loc = exp->loc;
- return new AFn(ret.head);
+ return new ACall(ret.head);
}
inline AST*
diff --git a/src/resp.cpp b/src/resp.cpp
index c1684e2..478c738 100644
--- a/src/resp.cpp
+++ b/src/resp.cpp
@@ -31,10 +31,6 @@ GC Object::pool(8 * 1024 * 1024);
bool
is_form(const AST* ast, const std::string& form)
{
- const AFn* fn = ast->to<const AFn*>();
- if (fn)
- return form == "fn";
-
const ACall* call = ast->to<const ACall*>();
if (!call)
return false;
diff --git a/src/resp.hpp b/src/resp.hpp
index ff1bc19..0f372a1 100644
--- a/src/resp.hpp
+++ b/src/resp.hpp
@@ -525,15 +525,6 @@ struct List {
typedef List<AType, AType> TList;
-/// Fn (first-class function with captured lexical bindings)
-struct AFn : public ATuple {
- AFn(const ATuple* exp) : ATuple(*exp) {}
- AFn(Cursor c, AST* ast, va_list args) : ATuple(c, ast, args) {}
- bool operator==(const AST& rhs) const { return this == &rhs; }
- void constrain(TEnv& tenv, Constraints& c) const throw(Error);
- string name;
-};
-
/// Function call/application, e.g. "(func arg1 arg2)"
struct ACall : public ATuple {
ACall(const ATuple* exp) : ATuple(*exp) {}
@@ -727,7 +718,7 @@ struct Engine {
const ATuple* args,
const AType* type) = 0;
- virtual void pushFunctionArgs(CEnv& cenv, const AFn* fn, const AType* type, CFunc f) = 0;
+ virtual void pushFunctionArgs(CEnv& cenv, const ACall* 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;
@@ -809,15 +800,15 @@ struct CEnv {
Env<const ASymbol*, const AST*> code;
- typedef map<const AFn*, CFunc> Impls;
+ typedef map<const ACall*, CFunc> Impls;
Impls impls;
- CFunc findImpl(const AFn* fn, const AType* type) {
+ CFunc findImpl(const ACall* fn, const AType* type) {
Impls::const_iterator i = impls.find(fn);
return (i != impls.end()) ? i->second : NULL;
}
- void addImpl(const AFn* fn, CFunc impl) {
+ void addImpl(const ACall* fn, CFunc impl) {
impls.insert(make_pair(fn, impl));
}
@@ -826,8 +817,8 @@ struct CEnv {
CFunc currentFn; ///< Currently compiling function
struct FreeVars : public std::vector<ASymbol*> {
- FreeVars(AFn* f, const std::string& n) : fn(f), implName(n) {}
- AFn* const fn;
+ FreeVars(ACall* f, const std::string& n) : fn(f), implName(n) {}
+ ACall* const fn;
const std::string implName;
int32_t index(ASymbol* sym) {
const_iterator i = find(begin(), end(), sym);
@@ -842,6 +833,17 @@ struct CEnv {
typedef std::stack<FreeVars> LiftStack;
LiftStack liftStack;
+ typedef map<const ACall*, std::string> Names;
+ Names names;
+
+ const std::string name(const ACall* fn) const {
+ Names::const_iterator i = names.find(fn);
+ return (i != names.end()) ? i->second : "";
+ }
+
+ void setName(const ACall* fn, const std::string& name) {
+ names.insert(make_pair(fn, name));
+ }
private:
Engine* _engine;
};