diff options
author | David Robillard <d@drobilla.net> | 2010-04-13 17:37:01 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2010-04-13 17:37:01 +0000 |
commit | 58170e475a1a35685ccb180767c4f86489be5733 (patch) | |
tree | f119bfb983202d4a50ab74d5dccf0af950390511 /src/unify.cpp | |
parent | d15593d1cda3e7c56cccc4958d6e07f8f15c90f3 (diff) | |
download | resp-58170e475a1a35685ccb180767c4f86489be5733.tar.gz resp-58170e475a1a35685ccb180767c4f86489be5733.tar.bz2 resp-58170e475a1a35685ccb180767c4f86489be5733.zip |
Better error reporting when unification fails (report both locations, and preserve locations during substitution).
git-svn-id: http://svn.drobilla.net/resp/resp@256 ad02d1e2-f140-0410-9f75-f8b11f17cedd
Diffstat (limited to 'src/unify.cpp')
-rw-r--r-- | src/unify.cpp | 38 |
1 files changed, 24 insertions, 14 deletions
diff --git a/src/unify.cpp b/src/unify.cpp index 1b25861..aadc032 100644 --- a/src/unify.cpp +++ b/src/unify.cpp @@ -61,7 +61,7 @@ Constraints::constrain(TEnv& tenv, const AST* o, const AType* t) assert(o); assert(t); assert(!o->to<const AType*>()); - push_back(Constraint(tenv.var(o), t, o->loc)); + push_back(Constraint(tenv.var(o), t)); } template<typename T, typename E> @@ -73,7 +73,9 @@ substitute(const T* tup, const E* from, const E* to) typename T::iterator ri = ret->begin(); FOREACHP(typename T::const_iterator, i, tup) { if (**i == *from) { - *ri++ = const_cast<E*>(to); + T* type = new T(*to); + type->loc = (*i)->loc; + *ri++ = type; } else if (static_cast<const E*>(*i) != static_cast<const E*>(to)) { const T* subTup = dynamic_cast<const T*>(*i); if (subTup) @@ -104,17 +106,24 @@ Subst::compose(const Subst& delta, const Subst& gamma) } /// Replace all occurrences of @a s with @a t -Constraints +Constraints& Constraints::replace(const AType* s, const AType* t) { - Constraints cp(*this); - for (Constraints::iterator c = begin(); c != end();) { - Constraints::iterator next = c; ++next; - if (*c->first == *s) c->first = t; - if (*c->second == *s) c->second = t; - c->first = substitute(c->first, s, t); - c->second = substitute(c->second, s, t); - c = next; + for (Constraints::iterator c = begin(); c != end(); ++c) { + if (*c->first == *s) { + AType* type = new AType(*t); + type->loc = c->first->loc; + c->first = type; + } else { + c->first = substitute(c->first, s, t); + } + if (*c->second == *s) { + AType* type = new AType(*t); + type->loc = c->second->loc; + c->second = type; + } else { + c->second = substitute(c->second, s, t); + } } return *this; } @@ -146,12 +155,13 @@ unify(const Constraints& constraints) if (st->kind == AType::DOTS || tt->kind == AType::DOTS) return unify(cp); else - cp.push_back(Constraint(st, tt, st->loc)); + cp.push_back(Constraint(st, tt)); } if (si == s->end() && (ti == t->end() || (*ti)->as<AType*>()->kind == AType::DOTS) || ti == t->end() && (*si)->as<AType*>()->kind == AType::DOTS) return unify(cp); } - throw Error(s->loc ? s->loc : t->loc, - (format("type is `%1%' but should be `%2%'") % s->str() % t->str()).str()); + throw Error(s->loc, + (format("type is `%1%' but should be `%2%'\n%3%: error: to match `%4%' here") + % s->str() % t->str() % t->loc.str() % t->str()).str()); } |