def _makeContextType(self): fContext, fType = self.function.contextType() aContext, aType = self.argument.contextType() # the type variables of f and a # must be independent for the rest to work aTypeVars = set(aType.variable) for t in aContext: aTypeVars.update(t.variable) freshener = {x : typ.Variable() for x in aTypeVars} aContext = [typ.substituted(freshener, t) for t in aContext] aType = typ.substituted(freshener, aType) # determine the types the variables must have z = zip(fContext, aContext) eq = [p for p in z if not any(t is None for t in p)] t = typ.Variable() eq += [(fType, Function(aType, t))] mgu = typ.unifyAll(*eq) z = itertools.zip_longest(fContext, aContext) context = (p[1] if p[0] is None else p[0] for p in z) context = [typ.substituted(mgu, u) for u in context] type = typ.substituted(mgu, t) return (context, type)
def _typeAndContextForce(self): try: FType, FContext = self._function.typeAndContext AType, AContext = self._argument.typeAndContext except NotWellTypedError: raise # the F and A type variables must be independent # for the rest to work ATypeVariables = set(AType.variable) for t in AContext.values(): ATypeVariables.update(t.variable) freshener = {x : _unif.Variable() for x in ATypeVariables} AType = _unif.substituted(freshener, AType) AContext = _unif.substituted(freshener, AContext) if __debug__: FTypeVariables = set(FType.variable) for t in FContext.values(): FTypeVariables.update(t.variable) ATypeVariables = set(AType.variable) for t in AContext.values(): ATypeVariables.update(t.variable) assert FTypeVariables.isdisjoint(ATypeVariables) # unify the contexts and such commonVariables = FContext.keys() & AContext.keys() equations = [(FContext[x], AContext[x]) for x in commonVariables] t = _unif.Variable() equations += [(FType, Function(AType, t))] try: subs = _unif.unifyAll(*equations) except _unif.UnificationError: raise NotWellTypedError("the application {} is not well typed.".format(self) + " its parts have types {} and {}".format(self._function.typeAndContext, self._function.typeAndContext)) type_ = _unif.substituted(subs, t) context = _unif.substituted(subs, FContext) context.update( _unif.substituted(subs, AContext) ) return (type_, context)