diff options
Diffstat (limited to 'src/constrain.cpp')
-rw-r--r-- | src/constrain.cpp | 87 |
1 files changed, 37 insertions, 50 deletions
diff --git a/src/constrain.cpp b/src/constrain.cpp index 97af0af..b4afe09 100644 --- a/src/constrain.cpp +++ b/src/constrain.cpp @@ -61,62 +61,49 @@ ATuple::constrain(TEnv& tenv, Constraints& c) const void AFn::constrain(TEnv& tenv, Constraints& c) const { - const AType* genericType; - TEnv::GenericTypes::const_iterator gt = tenv.genericTypes.find(this); - if (gt != tenv.genericTypes.end()) { - genericType = gt->second; - } else { - set<const ASymbol*> defs; - TEnv::Frame frame; - - // Add parameters to environment frame - AType* protT = tup<AType>(loc, NULL); - for (ATuple::const_iterator i = prot()->begin(); i != prot()->end(); ++i) { - const ASymbol* sym = (*i)->to<const ASymbol*>(); - THROW_IF(!sym, (*i)->loc, "parameter name is not a symbol"); - THROW_IF(defs.count(sym) != 0, sym->loc, - (format("duplicate parameter `%1%'") % sym->str()).str()); - defs.insert(sym); - AType* tvar = tenv.fresh(sym); - frame.push_back(make_pair(sym, tvar)); - protT->push_back(tvar); - } - c.constrain(tenv, at(1), protT); - - // Add internal definitions to environment frame - size_t e = 2; - for (; e < size(); ++e) { - const AST* exp = at(e); - const ADef* def = exp->to<const ADef*>(); - if (def) { - const ASymbol* sym = def->sym(); - THROW_IF(defs.count(sym) != 0, def->loc, - (format("`%1%' defined twice") % sym->str()).str()); - defs.insert(def->sym()); - frame.push_back(make_pair(def->sym(), (AType*)NULL)); - } + set<const ASymbol*> defs; + TEnv::Frame frame; + + // Add parameters to environment frame + AType* protT = tup<AType>(loc, NULL); + for (ATuple::const_iterator i = prot()->begin(); i != prot()->end(); ++i) { + const ASymbol* sym = (*i)->to<const ASymbol*>(); + THROW_IF(!sym, (*i)->loc, "parameter name is not a symbol"); + THROW_IF(defs.count(sym) != 0, sym->loc, + (format("duplicate parameter `%1%'") % sym->str()).str()); + defs.insert(sym); + AType* tvar = tenv.fresh(sym); + frame.push_back(make_pair(sym, tvar)); + protT->push_back(tvar); + } + c.constrain(tenv, at(1), protT); + + // Add internal definitions to environment frame + for (const_iterator i = begin() + 2; i != end(); ++i) { + const AST* exp = *i; + const ADef* def = exp->to<const ADef*>(); + if (def) { + const ASymbol* sym = def->sym(); + THROW_IF(defs.count(sym) != 0, def->loc, + (format("`%1%' defined twice") % sym->str()).str()); + defs.insert(def->sym()); + frame.push_back(make_pair(def->sym(), (AType*)NULL)); } + } - tenv.push(frame); - - Constraints cp; - cp.push_back(Constraint(tenv.var(this), tenv.var(), loc)); + tenv.push(frame); - for (size_t i = 2; i < size(); ++i) - at(i)->constrain(tenv, cp); + c.constrain(tenv, this, tenv.var()); + for (size_t i = 2; i < size(); ++i) + at(i)->constrain(tenv, c); - AType* bodyT = tenv.var(at(e-1)); - subst = unify(cp); - genericType = tup<AType>(loc, tenv.penv.sym("Fn"), - subst.apply(protT), subst.apply(bodyT), 0); - tenv.genericTypes.insert(make_pair(this, genericType)); - Object::pool.addRoot(genericType); + AType* bodyT = tenv.var(at(size() - 1)); + AType* fnT = tup<AType>(loc, tenv.penv.sym("Fn"), protT, bodyT, 0); + Object::pool.addRoot(fnT); - tenv.pop(); - } + tenv.pop(); - AType* t = new AType(*genericType); // FIXME: deep copy - c.constrain(tenv, this, t); + c.constrain(tenv, this, fnT); } void |