diff options
Diffstat (limited to 'typing.cpp')
-rw-r--r-- | typing.cpp | 50 |
1 files changed, 49 insertions, 1 deletions
@@ -83,6 +83,54 @@ ASTIf::constrain(TEnv& tenv) const } void +ASTPrimitive::constrain(TEnv& tenv) const +{ + const string n = dynamic_cast<ASTSymbol*>(at(0))->str(); + enum { ARITHMETIC, BINARY, BITWISE, COMPARISON } type; + if (n == "+" || n == "-" || n == "*" || n == "/") + type = ARITHMETIC; + else if (n == "%") + type = BINARY; + else if (n == "&" || n == "|" || n == "^") + type = BITWISE; + else if (n == "=" || n == "!=" || n == ">" || n == ">=" || n == "<" || n == "<=") + type = COMPARISON; + else + throw Error((format("unknown primitive `%1%'") % n).str(), exp.loc); + + FOREACH(const_iterator, p, *this) + (*p)->constrain(tenv); + + switch (type) { + case ARITHMETIC: + if (size() < 3) + throw Error((format("`%1%' requires at least 2 arguments") % n).str(), exp.loc); + for (size_t i = 1; i < size(); ++i) + tenv.constrain(this, tenv.type(at(i))); + break; + case BINARY: + if (size() != 3) + throw Error((format("`%1%' requires exactly 2 arguments") % n).str(), exp.loc); + tenv.constrain(this, tenv.type(at(1))); + tenv.constrain(this, tenv.type(at(2))); + break; + case BITWISE: + if (size() != 3) + throw Error((format("`%1%' requires exactly 2 arguments") % n).str(), exp.loc); + tenv.constrain(this, tenv.named("Bool")); + tenv.constrain(at(1), tenv.named("Bool")); + tenv.constrain(at(2), tenv.named("Bool")); + break; + case COMPARISON: + if (size() != 3) + throw Error((format("`%1%' requires exactly 2 arguments") % n).str(), exp.loc); + tenv.constrain(this, tenv.named("Bool")); + tenv.constrain(at(1), tenv.type(at(2))); + break; + } +} + +void ASTConsCall::constrain(TEnv& tenv) const { AType* t = new AType(ASTTuple(tenv.penv.sym("Pair"), 0)); @@ -174,7 +222,7 @@ TEnv::unify(const Constraints& constraints) // TAPL 22.4 } else if (t->var() && !s->contains(t)) { substConstraints(cp, t, s); return compose(unify(cp), TSubst(t, s)); - } else if (s->size() == t->size()) { + } else if (s->kind == AType::EXPR && s->kind == t->kind && s->size() == t->size()) { for (size_t i = 0; i < s->size(); ++i) { AType* si = dynamic_cast<AType*>(s->at(i)); AType* ti = dynamic_cast<AType*>(t->at(i)); |