aboutsummaryrefslogtreecommitdiffstats
path: root/typing.cpp
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2009-03-15 03:28:14 +0000
committerDavid Robillard <d@drobilla.net>2009-03-15 03:28:14 +0000
commit361cf8ee32179f529555d992ffe17c89ca642ddb (patch)
tree72d638e5f413ff81c77f0577d2ea959f57b1f555 /typing.cpp
parent59117fc8bcd610697a45c0013fc7450de2ee512f (diff)
downloadresp-361cf8ee32179f529555d992ffe17c89ca642ddb.tar.gz
resp-361cf8ee32179f529555d992ffe17c89ca642ddb.tar.bz2
resp-361cf8ee32179f529555d992ffe17c89ca642ddb.zip
Merge 'code' and 'type' environments.
Better error reporting for bad function parameters. git-svn-id: http://svn.drobilla.net/resp/tuplr@94 ad02d1e2-f140-0410-9f75-f8b11f17cedd
Diffstat (limited to 'typing.cpp')
-rw-r--r--typing.cpp46
1 files changed, 32 insertions, 14 deletions
diff --git a/typing.cpp b/typing.cpp
index 105140e..e042283 100644
--- a/typing.cpp
+++ b/typing.cpp
@@ -35,10 +35,10 @@ ASymbol::constrain(TEnv& tenv, Constraints& c) const
addr = tenv.lookup(this);
if (!addr)
throw Error((format("undefined symbol `%1%'") % cppstr).str(), loc);
- AType* t = tenv.deref(addr);
- assert(t);
- t->addr = addr;
- c.push_back(Constraint(tenv.var(this), t, loc));
+ pair<AST*, AType*>& t = tenv.deref(addr);
+ AType* tvar = tenv.var(t.second);
+ c.push_back(Constraint(tenv.var(this), tvar, loc));
+ c.push_back(Constraint(t.second, tvar, loc));
}
void
@@ -71,7 +71,7 @@ AClosure::constrain(TEnv& tenv, Constraints& c) const
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));
+ frame.push_back(make_pair(sym, make_pair((AST*)NULL, (AType*)NULL)));
}
// Add internal definitions to environment frame
@@ -84,7 +84,7 @@ AClosure::constrain(TEnv& tenv, Constraints& c) const
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));
+ frame.push_back(make_pair(def->sym(), make_pair(def->at(2), (AType*)NULL)));
}
}
@@ -98,7 +98,8 @@ AClosure::constrain(TEnv& tenv, Constraints& c) const
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;
+ frame[i].second.first = prot()->at(i);
+ frame[i].second.second = tvar;
}
c.push_back(Constraint(tenv.var(at(1)), protT, at(1)->loc));
@@ -110,7 +111,6 @@ AClosure::constrain(TEnv& tenv, Constraints& c) const
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);
@@ -123,13 +123,28 @@ void
ACall::constrain(TEnv& tenv, Constraints& c) const
{
at(0)->constrain(tenv, c);
- AType* argsT = new AType(ATuple(), loc);
- for (size_t i = 1; i < size(); ++i) {
+ for (size_t i = 1; i < size(); ++i)
at(i)->constrain(tenv, c);
- argsT->push_back(tenv.var(at(i)));
+
+ AST* callee = tenv.resolve(at(0));
+ AClosure* closure = dynamic_cast<AClosure*>(callee);
+ if (closure) {
+ if (size() - 1 != closure->prot()->size())
+ throw Error("incorrect number of arguments", loc);
+ TEnv::GenericTypes::iterator gt = tenv.genericTypes.find(closure);
+ if (gt != tenv.genericTypes.end()) {
+ for (size_t i = 1; i < size(); ++i)
+ c.constrain(tenv, at(i), gt->second->at(1)->as<ATuple*>()->at(i-1)->as<AType*>());
+ AType* retT = tenv.var(this);
+ c.constrain(tenv, at(0), new AType(at(0)->loc, tenv.penv.sym("Fn"), tenv.var(), retT, 0));
+ c.constrain(tenv, this, retT);
+ return;
+ }
}
+ AType* argsT = new AType(ATuple(), loc);
+ for (size_t i = 1; i < size(); ++i)
+ argsT->push_back(tenv.var(at(i)));
AType* retT = tenv.var();
-
c.constrain(tenv, at(0), new AType(at(0)->loc, tenv.penv.sym("Fn"), argsT, retT, 0));
c.constrain(tenv, this, retT);
}
@@ -138,10 +153,13 @@ void
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)))
+ const ASymbol* sym = dynamic_cast<const ASymbol*>(at(1));
+ if (!sym)
throw Error("`def' name is not a symbol", loc);
+ if (tenv.lookup(sym))
+ throw Error(string("`") + at(1)->str() + "' redefined", loc);
AType* tvar = tenv.var(at(2));
- tenv.def(at(1)->as<ASymbol*>(), tvar);
+ tenv.def(sym, make_pair(at(2), tvar));
at(2)->constrain(tenv, c);
c.constrain(tenv, this, tvar);
}