diff options
Diffstat (limited to 'llvm.cpp')
-rw-r--r-- | llvm.cpp | 158 |
1 files changed, 88 insertions, 70 deletions
@@ -124,6 +124,7 @@ CEnv::compile(AST* obj) void CEnv::optimise(CFunction f) { + _pimpl->module->dump(); verifyFunction(*static_cast<Function*>(f)); _pimpl->opt.run(*static_cast<Function*>(f)); } @@ -139,13 +140,24 @@ CEnv::write(std::ostream& os) template<> CValue \ ALiteral<CT>::compile(CEnv& cenv) { return (COMPILED); } \ template<> void \ -ALiteral<CT>::constrain(TEnv& tenv, Constraints& c) { c.constrain(tenv, this, tenv.named(NAME)); } +ALiteral<CT>::constrain(TEnv& tenv, Constraints& c) const { c.constrain(tenv, this, tenv.named(NAME)); } /// Literal template instantiations LITERAL(int32_t, "Int", ConstantInt::get(Type::Int32Ty, val, true)) LITERAL(float, "Float", ConstantFP::get(Type::FloatTy, val)) LITERAL(bool, "Bool", ConstantInt::get(Type::Int1Ty, val, false)) +template<typename T> +T +checked_cast(AST* ast) +{ + T t = dynamic_cast<T>(ast); + if (!t) + throw Error((format("internal error: `%1%' should be a `%2%'") + % typeid(ast).name() % typeid(T).name()).str(), ast->loc); + return t; +} + static Function* compileFunction(CEnv& cenv, const std::string& name, const Type* retT, const ATuple& protT, const vector<string> argNames=vector<string>()) @@ -154,8 +166,7 @@ compileFunction(CEnv& cenv, const std::string& name, const Type* retT, const ATu vector<const Type*> cprot; for (size_t i = 0; i < protT.size(); ++i) { - AType* at = dynamic_cast<AType*>(protT.at(i)); - if (!at) throw Error("function parameter type isn't"); + AType* at = checked_cast<AType*>(protT.at(i)); if (!lltype(at)) throw Error("function parameter is untyped"); cprot.push_back(lltype(at)); } @@ -215,10 +226,8 @@ AClosure::lift(CEnv& cenv) vector<Value*> args; const_iterator p = prot()->begin(); size_t i = 0; - for (Function::arg_iterator a = f->arg_begin(); a != f->arg_end(); ++a, ++p) { - cenv.tenv.def(*p, dynamic_cast<AType*>(protT->at(i++))); - cenv.vals.def(dynamic_cast<ASymbol*>(*p), &*a); - } + for (Function::arg_iterator a = f->arg_begin(); a != f->arg_end(); ++a, ++p) + cenv.def(checked_cast<ASymbol*>(*p), *p, checked_cast<AType*>(protT->at(i++)), &*a); // Write function body try { @@ -240,65 +249,71 @@ AClosure::lift(CEnv& cenv) } void -AClosure::liftPoly(CEnv& cenv, const vector<AType*>& argsT) +AClosure::liftCall(CEnv& cenv, const vector<AType*>& argsT) { - if (type->concrete()) - return; - - throw Error("No polymorphism"); + TEnv::GenericTypes::const_iterator gt = cenv.tenv.genericTypes.find(this); + assert(gt != cenv.tenv.genericTypes.end()); + AType* genericType = gt->second; -#if 0 - //Subst tsubst; + // Find type and build substitution assert(argsT.size() == prot()->size()); - for (size_t i = 0; i < argsT.size(); ++i) { - cenv.err << " " << argsT.at(i)->str(); - //tsubst[*cenv.tenv.ref(prot()->at(i))] = argsT.at(i); - } - cenv.err << endl; -#endif -} + Subst argsSubst; + ATuple* genericProtT = dynamic_cast<ATuple*>(genericType->at(1)); + assert(genericProtT); + for (size_t i = 0; i < argsT.size(); ++i) + argsSubst[dynamic_cast<AType*>(genericProtT->at(i))] = dynamic_cast<AType*>(argsT.at(i)); + + AType* thisType = new AType(*dynamic_cast<ATuple*>(argsSubst.apply(genericType)), loc); + cenv.err << "THIS TYPE: " << thisType << endl; -CValue -AClosure::compile(CEnv& cenv) -{ - /* - cenv.err << "***********************************************" << endl; - cenv.err << cenv.type(this) << endl; + //if (!thisType->concrete()) + // throw Error("unable to resolve concrete type for function", loc); - cenv.err << "COMPILING FOR TYPE:"; - Subst tsubst; - assert(cenv.code.front().size() == prot()->size()); - for (size_t i = 0; i < cenv.code.front().size(); ++i) { - cenv.err << " (" << cenv.type(prot()->at(i))->str() - << " -> " << cenv.type(cenv.code.front().at(i).second)->str() << ")"; - tsubst[cenv.tenv.types[prot()->at(i)]] = - cenv.type(cenv.code.front().at(i).second); - } - cenv.err << endl; + if (funcs.find(thisType)) + return; - Subst subst = Subst::compose(tsubst, cenv.tsubst); - AType* concreteType = subst.apply(type); - if (!concreteType->concrete()) - throw Error("compiled function has non-concrete type", loc); + ATuple* protT = dynamic_cast<ATuple*>(thisType->at(1)); - cenv.err << "*********** CONCRETE TYPE: " << concreteType->str() << endl; - */ + // Write function declaration + string name = this->name == "" ? cenv.gensym("_fn") : this->name; + Function* f = compileFunction(cenv, name, + lltype(dynamic_cast<AType*>(thisType->at(thisType->size() - 1))), + *protT); - //CValue ret = funcs.find(concreteType); - //cenv.err << "VALUE FOR TYPE " << concreteType->str() << " : " << ret << endl; - //return ret; - return NULL; + cenv.push(); + Subst oldSubst = cenv.tsubst; + cenv.tsubst = Subst::compose(cenv.tsubst, Subst::compose(argsSubst, *subst)); + + // Bind argument values in CEnv + vector<Value*> args; + const_iterator p = prot()->begin(); + size_t i = 0; + for (Function::arg_iterator a = f->arg_begin(); a != f->arg_end(); ++a, ++p) + cenv.def(checked_cast<ASymbol*>(*p), *p, checked_cast<AType*>(protT->at(i++)), &*a); + + // Write function body + try { + // Define value first for recursion + cenv.precompile(this, f); + funcs.push_back(make_pair(thisType, f)); + + CValue retVal = cenv.compile(at(2)); + llengine(cenv)->builder.CreateRet(LLVal(retVal)); // Finish function + cenv.optimise(LLFunc(f)); + + } catch (Error& e) { + f->eraseFromParent(); // Error reading body, remove function + cenv.pop(); + throw e; + } + cenv.tsubst = oldSubst; + cenv.pop(); } -template<typename T> -T -checked_cast(AST* ast) +CValue +AClosure::compile(CEnv& cenv) { - T t = dynamic_cast<T>(ast); - if (!t) - throw Error((format("internal error: `%1%' should be a `%2%'") - % typeid(ast).name() % typeid(T).name()).str(), ast->loc); - return t; + return NULL; } static @@ -306,7 +321,7 @@ AST* maybeLookup(CEnv& cenv, AST* ast) { ASymbol* s = dynamic_cast<ASymbol*>(ast); - if (s) + if (s && s->addr) return cenv.code.deref(s->addr); return ast; } @@ -325,18 +340,19 @@ ACall::lift(CEnv& cenv) } if (!c) return; // Primitive - - // Extend environment with bound and typed parameters - cenv.push(); + if (c->prot()->size() < size() - 1) throw Error((format("too many arguments to function `%1%'") % at(0)->str()).str(), loc); if (c->prot()->size() > size() - 1) throw Error((format("too few arguments to function `%1%'") % at(0)->str()).str(), loc); + // Extend environment with bound and typed parameters + cenv.push(); + for (size_t i = 1; i < size(); ++i) - cenv.code.def(checked_cast<ASymbol*>(c->prot()->at(i-1)), at(i)); + cenv.def(checked_cast<ASymbol*>(c->prot()->at(i-1)), at(i), cenv.type(at(i)), NULL); - c->liftPoly(cenv, argsT); // Lift called closure + c->liftCall(cenv, argsT); // Lift called closure cenv.pop(); // Restore environment } @@ -347,16 +363,13 @@ ACall::compile(CEnv& cenv) if (!c) return NULL; // Primitive - if (c->prot()->size() < size() - 1) - throw Error((format("too many arguments to function `%1%'") % at(0)->str()).str(), loc); - if (c->prot()->size() > size() - 1) - throw Error((format("too few arguments to function `%1%'") % at(0)->str()).str(), loc); - AType* protT = new AType(loc, NULL); for (size_t i = 1; i < size(); ++i) protT->push_back(cenv.type(at(i))); - - AType* polyT = c->type; + + TEnv::GenericTypes::const_iterator gt = cenv.tenv.genericTypes.find(c); + assert(gt != cenv.tenv.genericTypes.end()); + AType* polyT = gt->second; AType* fnT = new AType(loc, cenv.penv.sym("Fn"), protT, polyT->at(2), 0); Function* f = (Function*)c->funcs.find(fnT); @@ -374,7 +387,8 @@ ADefinition::lift(CEnv& cenv) { if (cenv.code.lookup(checked_cast<ASymbol*>(at(1)))) throw Error(string("`") + at(1)->str() + "' redefined", loc); - cenv.code.def((ASymbol*)at(1), at(2)); // Define first for recursion + // Define first for recursion + cenv.def(checked_cast<ASymbol*>(at(1)), at(2), cenv.type(at(2)), NULL); at(2)->lift(cenv); } @@ -630,11 +644,11 @@ eval(CEnv& cenv, const string& name, istream& is) int repl(CEnv& cenv) { - Constraints c; while (1) { cenv.out << "() "; cenv.out.flush(); Cursor cursor("(stdin)"); + Constraints c; try { SExp exp = readExpression(cursor, std::cin); @@ -643,6 +657,10 @@ repl(CEnv& cenv) AST* body = cenv.penv.parse(exp); // Parse input body->constrain(cenv.tenv, c); // Constrain types + + for (TEnv::GenericTypes::const_iterator i = cenv.tenv.genericTypes.begin(); + i != cenv.tenv.genericTypes.end(); ++i) + c.push_back(Constraint(cenv.tenv.var(i->first), i->second, i->first->loc)); cenv.tsubst = Subst::compose(cenv.tsubst, TEnv::unify(c)); // Solve type constraints |