diff options
Diffstat (limited to 'src/constrain.cpp')
-rw-r--r-- | src/constrain.cpp | 35 |
1 files changed, 15 insertions, 20 deletions
diff --git a/src/constrain.cpp b/src/constrain.cpp index 85f3c35..8d44487 100644 --- a/src/constrain.cpp +++ b/src/constrain.cpp @@ -123,32 +123,27 @@ AFn::constrain(TEnv& tenv, Constraints& c) const void ACall::constrain(TEnv& tenv, Constraints& c) const { - at(0)->constrain(tenv, c); - for (size_t i = 1; i < size(); ++i) + for (size_t i = 0; i < size(); ++i) at(i)->constrain(tenv, c); - const AST* callee = tenv.resolve(at(0)); - const AFn* closure = callee->to<const AFn*>(); - if (closure) { - THROW_IF(size() - 1 != closure->prot()->size(), loc, "incorrect number of arguments"); - TEnv::GenericTypes::iterator gt = tenv.genericTypes.find(closure); - if (gt != tenv.genericTypes.end()) { - const ATuple* prot = gt->second->at(1)->to<const ATuple*>(); - const_iterator i = begin(); - const_iterator prot_i = prot->begin(); - for (++i; i != end(); ++i, ++prot_i) - c.constrain(tenv, *i, (*prot_i)->as<AType*>()); - AType* retT = tenv.var(this); - c.constrain(tenv, at(0), - tup<AType>(at(0)->loc, tenv.penv.sym("Fn"), tenv.var(), retT, 0)); - c.constrain(tenv, this, retT); - return; - } + const AType* fnType = tenv.var(at(0)); + if (fnType->kind != AType::VAR) { + if (fnType == AType::PRIM + || fnType->size() < 2 + || !fnType->at(0)->to<const ASymbol*>() + || fnType->at(0)->to<const ASymbol*>()->cppstr != "Fn") + throw Error(loc, (format("call to non-function `%1%'") % at(0)->str()).str()); + + size_t numArgs = fnType->at(1)->to<const ATuple*>()->size(); + THROW_IF(numArgs != size() - 1, loc, + (format("expected %1% arguments, got %2%") % numArgs % (size() - 1)).str()); } + + AType* retT = tenv.var(); AType* argsT = tup<AType>(loc, 0); for (size_t i = 1; i < size(); ++i) argsT->push_back(tenv.var(at(i))); - AType* retT = tenv.var(); + c.constrain(tenv, at(0), tup<AType>(at(0)->loc, tenv.penv.sym("Fn"), argsT, retT, 0)); c.constrain(tenv, this, retT); } |