From 361cf8ee32179f529555d992ffe17c89ca642ddb Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sun, 15 Mar 2009 03:28:14 +0000 Subject: 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 --- typing.cpp | 46 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 14 deletions(-) (limited to 'typing.cpp') 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& 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(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(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()->at(i-1)->as()); + 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(at(1))) + const ASymbol* sym = dynamic_cast(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(), tvar); + tenv.def(sym, make_pair(at(2), tvar)); at(2)->constrain(tenv, c); c.constrain(tenv, this, tvar); } -- cgit v1.2.1