Example #1
0
def clos(state, node):
    """closure nodes"""

    # we extend given env type, so that subsequent unifications will
    # be reflected to us (when unifying different branches, then
    # sealing)
    with state.current(node.env):
        env_type = expr(state, node.env)
        assert type(env_type) in row.types

        gen_type = closure.env_gen(env_type, state.depth)
        tool.debug("gen_type:", gen_type.show())
        state.pure(gen_type)

    def constraint(args_type):
        state.unify(gen_type, args_type[0])

    # we need to preconstrain env type, because it may contain
    # functions and we need to know whether they are regular functions
    # or closures before calling them
    with state.current(node.code):
        assert type(node.code) is ast.Abs
        code_type = abs(state, node.code, constraint)
        state.pure(code_type)

    return closure.clos(code_type, gen_type)
Example #2
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]
Example #3
0
def row_gen(state, node):

    # this will row-generalize type for node
    node_type = expr(state, node.expr)
    assert type(node_type) in row.types, "closure env should be a record: {0}".format(node_type.show())

    # copy tuple, then add a fresh row type variable
    var = row.Var(state.depth)
    if type(node_type) is row.Empty:
        gen_type = var
    else:
        gen_type = row.record(*tuple(iter(node_type)))
        gen_type.set_terminator(var)

    tool.debug("gen_type:", gen_type.show())

    return gen_type
Example #4
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]
Example #5
0
def coercion(state, node):
    """function/closure coercion"""
    node_type = expr(state, node.expr).nice(state.uf)

    assert type(node_type) is App, "cannot coerce to function type: {0}".format(node_type.show())

    if node_type.func is func:
        return node_type

    if node_type.func is closure.clos:

        # seal env types
        env_type = node_type.args[1]
        # print('env_type:', env_type.show())
        # print('variables:', env_type.variables())

        if env_type.variables():
            state.unify(env_type.var(), row.empty)

        code_type = node_type.args[0]

        tool.debug("after sealing:")
        tool.debug("env:", env_type.nice(state.uf).show())
        tool.debug("code:", code_type.nice(state.uf).show())

        # return partial application of the closure code to env
        res = code_type.args[1]

        # nullary closures:
        if not res.is_func_type():
            return unit >> res

        return res

    assert False, "cannot coerce to function type: {0}".format(node_type.show())
Example #6
0
def unify(uf, a, b):
    """unify types ta and tb"""

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

    # TODO introduce kinds ?
    ta = type(a)
    tb = type(b)

    with tool.indentation():

        if tool.DEBUG:
            na, nb = a.nice(uf), b.nice(uf)
            sa, sb = show(na, nb)

            if na.variables() or nb.variables():
                tool.debug("unify:", sa)
                tool.debug("with:", sb)

        if ta is App and tb is App and a.func == b.func:
            for ai, bi in zip(a.args, b.args):
                unify(uf, ai, bi)

        elif ta in row.types and tb in row.types:
            row.unify(uf, a, b)

        elif ta is typeclass.Var or tb is typeclass.Var:
            typeclass.unify(uf, a, b)

        elif ta is Var or tb is Var:

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

            # print('unifying:', ta, tb)

            # TODO what if we auto-unify ? is this legal ?
            # assert var is not other

            if type(other) is App:
                # TODO delay occurs_check?
                occurs_check(var, other)

            if type(other) is Var and var.depth < other.depth:
                var, other = other, var

            # TODO should we nice before linking ?
            uf.link(var, other)

            if tool.DEBUG and type(other) is Var:
                with tool.indentation():

                    tool.debug("repr:", sa if a is other else sb)

        elif a != b:
            sa, sb = show(a, b, 0, True)
            raise error.Type("""can not unify types {0} and {1}""".format(sa, sb))
Example #7
0
        out += ' : ' + str(poly)

        ts.cleanup()
        if not args.codegen:
            print(out)
            continue

        with tool.debug_scope('closure conversion'):

            # closure conversion
            node = closure.toplevel( closure.State(), node)

        # typecheck closure conversion
        with tool.debug_scope('typecheck closure conversion'):
            poly = hm.toplevel(cc, node )
            tool.debug('closure conversion type:', poly)

        with tool.debug_scope("codegen"):
            
            code = codegen.toplevel(cs, node)

            if code and type(node) in ast.expression_types:
                code = codegen.print_expr(cs, poly.body, code, out)
                
            cc.cleanup()
            
        if code:

            with open('debug', 'w') as file:
                print('file', 'lli', file = file)
                print('run',
Example #8
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