示例#1
0
    def find_instance(self, mono):
        '''find typeclass instance matching mono'''

        tool.debug('finding instance of:', self.name, mono.show())
        
        # print('finding instance of:', self.name, 'for:', mono.show())
        t = type(mono)

        matches = []
        
        for scheme, instance in self.instances.items():

            # TODO what about depth ?
            fresh = hm.instantiate( scheme )

            try:
                # note: we unify in a fresh union_find
                hm.unify(tool.UnionFind(), fresh, mono)
                matches.append( (scheme, instance) )
                
            except error.Type:
                pass

        if not matches:
            raise error.Type('typeclass {0} has no instance for type {1}'
                             .format( self.name, mono.show() ))                

        if len(matches) > 1:
            raise error.Type('ambiguous {0} instances for {1}'.format(self.name, mono.show()))
        
        return matches[0]
示例#2
0
def unify(uf, a, b):

    a = uf.find(a)
    b = uf.find(b)

    ta = type(a)
    tb = type(b)

    # sa, sb = hm.show(a, b)
    # print('typeclass unify', a.show(), 'with:', b.show() )
    
    assert ta is Var or tb is Var
    
    if ta is Var and tb is Var:

        # create a fresh constrained variable with constraint union
        depth = min(a.depth, b.depth)
        c = Var(depth, a.context | b.context )

        # and link both
        uf.link(a, c)
        uf.link(b, c)

        return
    
    var = a if ta is Var else b
    other = a if tb is Var else b

    if type(other) is hm.Var:
        # constrained variable becomes representant
        uf.link(other, var)
        return
    
    # check instances
    for tc in var.context:

        # find a type scheme that matches 'other' in the
        # instances for this type constructor
        scheme, instance = tc.find_instance( other.nice(uf) )

        # context reduction happens here: we instantiate the
        # type scheme (possibly containing bounded variables)
        # and unify with other

        # propagate further constraints, if any
        if any( type(b) is Var for b in scheme.bound ):

            # TODO what about the depth when instantiating scheme ?
            hm.unify(uf, hm.instantiate(scheme), other)

    # we made it so far, we may link now
    uf.link(var, other)
    return
示例#3
0
    def find_overload(self, identifier, mono):

        tool.debug('finding overload for:', identifier, ':', mono.show())
                   
        proto = self.definition[identifier]
        uf = tool.UnionFind()

        fresh = hm.instantiate(hm.generalize(proto))
        vars = fresh.variables()
        assert len(vars) == 1

        hm.unify(uf, fresh, mono)

        a = next(iter(vars))
        t = uf.find( a )

        scheme, instance = self.find_instance(t)
        return instance[identifier]
示例#4
0
def unify(uf, a, b):
    """unify row types ra and rb"""

    a = uf.find(a)
    b = uf.find(b)

    ta = type(a)
    tb = type(b)

    assert ta in types and tb in types

    # print( ra, rb)
    if ta is Extension and tb is Extension:

        if a.label == b.label:
            # unify heads
            hm.unify(uf, a.mono, b.mono)

            # unify tails
            unify(uf, a.tail, b.tail)
        else:
            try:
                # try pulling b's head in a
                tool.debug("pulling", b.label)
                pa = a.pull(b.label)
                unify(uf, pa, b)

                # it worked: remember pa is originially a
                uf.link(pa, a)

            except PullError:
                try:
                    # try pulling a's head in b
                    tool.debug("pulling", a.label)
                    pb = b.pull(a.label)
                    unify(uf, a, pb)

                    # it worked: remember pa is originially b
                    uf.link(pb, b)

                except PullError:
                    tool.debug("union")
                    # none of it worked: neither heads is present in
                    # other type. try to unify both to record union

                    # unify a's tail var with a fresh copy of b

                    try:
                        unify(uf, a.var(), b.fresh())
                        unify(uf, b.var(), a.fresh())
                    except FreshError:
                        sa, sb = hm.show(a, b)
                        raise error.Type("can not unify row type {0} with {1}".format(sa, sb))

    elif ta is Var or tb is Var:

        var = a if ta is Var else b
        other = a if tb is Var else b

        uf.link(var, other)
        # tool.debug('repr:', other.show())

    elif a != b:
        raise error.Type("can not unify row type {0} with {1}".format(a.show(), b.show()))

    else:
        assert ta is Empty and tb is Empty