diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/c.cpp | 6 | ||||
-rw-r--r-- | src/compile.cpp | 14 | ||||
-rw-r--r-- | src/constrain.cpp | 22 | ||||
-rw-r--r-- | src/lift.cpp | 43 | ||||
-rw-r--r-- | src/llvm.cpp | 6 | ||||
-rw-r--r-- | src/parse.cpp | 2 | ||||
-rw-r--r-- | src/resp.cpp | 4 | ||||
-rw-r--r-- | src/resp.hpp | 32 |
8 files changed, 64 insertions, 65 deletions
@@ -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; }; |