diff options
author | David Robillard <d@drobilla.net> | 2009-03-15 01:09:19 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2009-03-15 01:09:19 +0000 |
commit | 117b9fbb3d0737f44cf3f8f3f1a3f964b1f9e777 (patch) | |
tree | 56c089fcfa6b1f6a510cdbd013a38363bea19fd0 /typing.cpp | |
parent | 053a6e588b143bdd765113cdcd53ae7ef39c1a6c (diff) | |
download | resp-117b9fbb3d0737f44cf3f8f3f1a3f964b1f9e777.tar.gz resp-117b9fbb3d0737f44cf3f8f3f1a3f964b1f9e777.tar.bz2 resp-117b9fbb3d0737f44cf3f8f3f1a3f964b1f9e777.zip |
Fix recursion.
git-svn-id: http://svn.drobilla.net/resp/tuplr@89 ad02d1e2-f140-0410-9f75-f8b11f17cedd
Diffstat (limited to 'typing.cpp')
-rw-r--r-- | typing.cpp | 148 |
1 files changed, 77 insertions, 71 deletions
@@ -30,28 +30,24 @@ Constraints::constrain(TEnv& tenv, const AST* o, AType* t) ***************************************************************************/ void -ASymbol::lookup(TEnv& tenv) +ASymbol::constrain(TEnv& tenv, Constraints& c) const { addr = tenv.lookup(this); if (!addr) throw Error((format("undefined symbol `%1%'") % cppstr).str(), loc); -} - -void -ASymbol::constrain(TEnv& tenv, Constraints& c) -{ - lookup(tenv); AType* t = tenv.deref(addr); if (!t) throw Error((format("unresolved symbol `%1%'") % cppstr).str(), loc); - c.push_back(Constraint(tenv.var(this), tenv.deref(addr), loc)); + AType* var = tenv.deref(addr); + var->addr = addr; + c.push_back(Constraint(tenv.var(this), var, loc)); } void -ATuple::constrain(TEnv& tenv, Constraints& c) +ATuple::constrain(TEnv& tenv, Constraints& c) const { AType* t = new AType(ATuple(), loc); - FOREACH(iterator, p, *this) { + FOREACH(const_iterator, p, *this) { (*p)->constrain(tenv, c); t->push_back(tenv.var(*p)); } @@ -59,95 +55,105 @@ ATuple::constrain(TEnv& tenv, Constraints& c) } void -AClosure::constrain(TEnv& tenv, Constraints& c) +AClosure::constrain(TEnv& tenv, Constraints& c) const { - set<ASymbol*> defined; - TEnv::Frame frame; - - // Add parameters to environment frame - for (size_t i = 0; i < prot()->size(); ++i) { - ASymbol* sym = dynamic_cast<ASymbol*>(prot()->at(i)); - if (!sym) - throw Error("parameter name is not a symbol", prot()->at(i)->loc); - if (defined.find(sym) != defined.end()) - throw Error((format("duplicate parameter `%1%'") % sym->str()).str(), sym->loc); - defined.insert(sym); - frame.push_back(make_pair(sym, (AType*)NULL)); - } - - // Add internal definitions to environment frame - size_t e = 2; - for (; e < size(); ++e) { - AST* exp = at(e); - ADefinition* def = dynamic_cast<ADefinition*>(exp); - if (def) { - ASymbol* sym = def->sym(); + AType* genericType; + TEnv::GenericTypes::const_iterator gt = tenv.genericTypes.find(this); + if (gt != tenv.genericTypes.end()) { + genericType = gt->second; + } else { + set<ASymbol*> defined; + TEnv::Frame frame; + + // Add parameters to environment frame + for (size_t i = 0; i < prot()->size(); ++i) { + ASymbol* sym = dynamic_cast<ASymbol*>(prot()->at(i)); + if (!sym) + throw Error("parameter name is not a symbol", prot()->at(i)->loc); if (defined.find(sym) != defined.end()) - throw Error((format("`%1%' defined twice") % sym->str()).str(), def->loc); - defined.insert(def->sym()); - frame.push_back(make_pair(def->sym(), (AType*)NULL)); + throw Error((format("duplicate parameter `%1%'") % sym->str()).str(), sym->loc); + defined.insert(sym); + frame.push_back(make_pair(sym, (AType*)NULL)); } - } - - tenv.push(frame); - - Constraints cp; - cp.push_back(Constraint(tenv.var(this), tenv.var(), loc)); - - AType* protT = new AType(ATuple(), loc); - for (size_t i = 0; i < prot()->size(); ++i) { - AType* tvar = tenv.fresh(dynamic_cast<ASymbol*>(prot()->at(i))); - protT->push_back(tvar); - assert(frame[i].first == prot()->at(i)); - frame[i].second = tvar; - } - c.push_back(Constraint(tenv.var(at(1)), protT, at(1)->loc)); - for (size_t i = 2; i < size(); ++i) - at(i)->constrain(tenv, cp); + // Add internal definitions to environment frame + size_t e = 2; + for (; e < size(); ++e) { + AST* exp = at(e); + ADefinition* def = dynamic_cast<ADefinition*>(exp); + if (def) { + ASymbol* sym = def->sym(); + if (defined.find(sym) != defined.end()) + throw Error((format("`%1%' defined twice") % sym->str()).str(), def->loc); + defined.insert(def->sym()); + frame.push_back(make_pair(def->sym(), (AType*)NULL)); + } + } - AType* bodyT = tenv.var(at(e-1)); - Subst tsubst = TEnv::unify(cp); - type = new AType(loc, tenv.penv.sym("Fn"), tsubst.apply(protT), tsubst.apply(bodyT), 0); + tenv.push(frame); - tenv.pop(); + Constraints cp; + cp.push_back(Constraint(tenv.var(this), tenv.var(), loc)); - c.constrain(tenv, this, type); - subst = new Subst(tsubst); + AType* protT = new AType(ATuple(), loc); + for (size_t i = 0; i < prot()->size(); ++i) { + AType* tvar = tenv.fresh(dynamic_cast<ASymbol*>(prot()->at(i))); + protT->push_back(tvar); + assert(frame[i].first == prot()->at(i)); + frame[i].second = tvar; + } + c.push_back(Constraint(tenv.var(at(1)), protT, at(1)->loc)); + + for (size_t i = 2; i < size(); ++i) + at(i)->constrain(tenv, cp); + + AType* bodyT = tenv.var(at(e-1)); + Subst tsubst = TEnv::unify(cp); + genericType = new AType(loc, tenv.penv.sym("Fn"), + tsubst.apply(protT), tsubst.apply(bodyT), 0); + tenv.genericTypes.insert(make_pair(this, genericType)); + tenv.def(this, genericType); + + tenv.pop(); + subst = new Subst(tsubst); + } + + c.constrain(tenv, this, genericType); + //for (Constraints::const_iterator i = cp.begin(); i != cp.end(); ++i) + // c.push_back(*i); } void -ACall::constrain(TEnv& tenv, Constraints& c) +ACall::constrain(TEnv& tenv, Constraints& c) const { + std::cerr << "CONSTRAIN CALL" << endl; + + at(0)->constrain(tenv, c); AType* argsT = new AType(ATuple(), loc); - TEnv::Frame frame; for (size_t i = 1; i < size(); ++i) { at(i)->constrain(tenv, c); argsT->push_back(tenv.var(at(i))); - frame.push_back(make_pair((AST*)NULL, tenv.var(at(i)))); } AType* retT = tenv.var(); - - at(0)->constrain(tenv, c); c.constrain(tenv, at(0), new AType(at(0)->loc, tenv.penv.sym("Fn"), argsT, retT, 0)); c.constrain(tenv, this, retT); } void -ADefinition::constrain(TEnv& tenv, Constraints& c) +ADefinition::constrain(TEnv& tenv, Constraints& c) const { if (size() != 3) throw Error("`def' requires exactly 2 arguments", loc); if (!dynamic_cast<const ASymbol*>(at(1))) throw Error("`def' name is not a symbol", loc); - AType* tvar = tenv.var(this); + AType* tvar = tenv.var(at(2)); tenv.def(at(1), tvar); at(2)->constrain(tenv, c); - c.constrain(tenv, at(2), tvar); + c.constrain(tenv, this, tvar); } void -AIf::constrain(TEnv& tenv, Constraints& c) +AIf::constrain(TEnv& tenv, Constraints& c) const { if (size() < 3) throw Error("`if' requires exactly 3 arguments", loc); if (size() % 2 != 0) throw Error("`if' missing final else clause", loc); @@ -165,7 +171,7 @@ AIf::constrain(TEnv& tenv, Constraints& c) } void -APrimitive::constrain(TEnv& tenv, Constraints& c) +APrimitive::constrain(TEnv& tenv, Constraints& c) const { const string n = dynamic_cast<ASymbol*>(at(0))->str(); enum { ARITHMETIC, BINARY, LOGICAL, COMPARISON } type; @@ -215,7 +221,7 @@ APrimitive::constrain(TEnv& tenv, Constraints& c) } void -AConsCall::constrain(TEnv& tenv, Constraints& c) +AConsCall::constrain(TEnv& tenv, Constraints& c) const { if (size() != 3) throw Error("`cons' requires exactly 2 arguments", loc); AType* t = new AType(loc, tenv.penv.sym("Pair"), 0); @@ -227,7 +233,7 @@ AConsCall::constrain(TEnv& tenv, Constraints& c) } void -ACarCall::constrain(TEnv& tenv, Constraints& c) +ACarCall::constrain(TEnv& tenv, Constraints& c) const { if (size() != 2) throw Error("`car' requires exactly 1 argument", loc); at(1)->constrain(tenv, c); @@ -238,7 +244,7 @@ ACarCall::constrain(TEnv& tenv, Constraints& c) } void -ACdrCall::constrain(TEnv& tenv, Constraints& c) +ACdrCall::constrain(TEnv& tenv, Constraints& c) const { if (size() != 2) throw Error("`cdr' requires exactly 1 argument", loc); at(1)->constrain(tenv, c); |