aboutsummaryrefslogtreecommitdiffstats
path: root/typing.cpp
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2009-03-15 01:09:19 +0000
committerDavid Robillard <d@drobilla.net>2009-03-15 01:09:19 +0000
commit117b9fbb3d0737f44cf3f8f3f1a3f964b1f9e777 (patch)
tree56c089fcfa6b1f6a510cdbd013a38363bea19fd0 /typing.cpp
parent053a6e588b143bdd765113cdcd53ae7ef39c1a6c (diff)
downloadresp-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.cpp148
1 files changed, 77 insertions, 71 deletions
diff --git a/typing.cpp b/typing.cpp
index ef28409..1d86f3d 100644
--- a/typing.cpp
+++ b/typing.cpp
@@ -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);