def unify_single(t1, t2, solution, remaining): """ Unify a single type equation and update the solution and remaining constraints. """ if isinstance(t1, TypeVar) and isinstance(t2, TypeVar): remaining.append((t1, t2)) elif isinstance(t1, TypeVar): if t1 in free(t2): raise error.UnificationError("Cannot unify recursive types") solution[t1].add(t2) remaining.append((t1, t2)) elif isinstance(t2, TypeVar): if t2 in free(t1): raise error.UnificationError("Cannot unify recursive types") solution[t2].add(t1) elif isinstance(t1, TypeConstructor): verify(t1, t2) elif not isinstance(t1, Mono) and not isinstance(t2, Mono): verify(t1, t2) elif getattr(t1, "cls", None) == MEASURE and getattr(t2, "cls", None) == MEASURE: # If both types are measures, verify they can be promoted promote_units(t1, t2) else: verify(t1, t2) for arg1, arg2 in zip(t1.parameters, t2.parameters): unify_single(arg1, arg2, solution, remaining)
def reify(solution, S=None): """ Reify a typing solution, returning a new solution with types as concrete types as opposed to type sets. Parameters ---------- solution : { TypeVar : set([ Type ]) } Typing solution Returns: { TypeVar : Type } Returns a solution reduced to concrete types only. """ if S is None: S = IdentityDict() seen = set() queue = deque(dict_iteritems(solution)) while queue: typevar, t = queue.popleft() t = frozenset(t) if typevar in S: continue typeset = solution[typevar] freevars = IdentityDict.fromkeys(chain(*[free(t) for t in typeset])) if not typeset: S[typevar] = typevar typeset.add(typevar) continue elif freevars and (typevar, t) not in seen: # Reify dependencies first queue.append((typevar, t)) seen.add((typevar, t)) elif freevars: typeset = set(substitute(S, t) for t in typeset) S[typevar] = promote_units(*typeset) return S