예제 #1
0
    def closing_over(self, t, closed, body):
        # NOTE: Like the Generalizing constraint, we're implicitly
        #       assuming that due to constraint ordering the body
        #       referenced here has already been solved.

        fntype = self.context.instantiate(resolve_type(body, self.solution))
        if not isinstance(fntype, T.Fn):
            raise InferenceError, "closure must be over functional types"

        # Get the list of argument types from the Fn type
        innertypes = fntype.input_types()

        # Partition the inner argument types into the outer types
        # exported to the world and those corresponding to the closed
        # arguments
        outertypes, closedtypes = innertypes[:-len(closed)], \
                                  innertypes[-len(closed):]

        for v, t2 in zip(closed, closedtypes):
            if self.verbose:
                print "\tt1 =", v.type
                print "\tt2 =", t2
            t1 = resolve(v.type, self.solution)
            t1 = self.context.instantiate(t1)
            if self.verbose:
                print "\tresolve(t1) =", t1
                print "\tresolve(t2) =", resolve_type(t2, self.solution)
            self.unify_monotypes(t1, t2)

        self.unify_monotypes(t, T.Fn(outertypes, fntype.result_type()))
예제 #2
0
    def _Apply(self, ast):
        for c in self.visit_children(ast):
            yield c
        fntype = ast.function().type
        argtypes = [x.type for x in ast.arguments()]

        yield Equality(fntype, T.Fn(argtypes, ast.type), ast)
예제 #3
0
    def _Procedure(self, ast):
        con = self.context

        # Create a new type variable for the return type of the procedure
        restype = con.fresh_typevar()
        restype.source = None

        # Get the names and type variables for the formal parameters
        argnames = [arg.id for arg in flatten(ast.formals())]
        argtypes = [arg.type for arg in flatten(ast.formals())]

        # Make the definition of this function visible within its body
        # to allow for recursive calls
        con.typings[ast.name().id] = ast.name().type

        con.begin_scope()

        # Make the formals visible
        con.typings.update(dict(zip(argnames, argtypes)))
        prior_monomorphs = con.monomorphs
        con.monomorphs = prior_monomorphs | set(argtypes)

        argtypeit = iter(argtypes)

        # Construct the formals types
        def make_type(formal):
            if hasattr(formal, '__iter__'):
                return T.Tuple(*[make_type(x) for x in iter(formal)])
            else:
                return argtypeit.next()

        formals_types = make_type(ast.formals())

        # XXX This makes the restriction that recursive invocations of F
        # in the body of F must have the same type signature.  Probably
        # not strictly necessary, but allowing the more general case
        # might prove problematic, especially in tail recursive cases.
        # For now, we will forbid this.
        con.monomorphs.add(ast.name().type)

        # Produce all constraints for arguments
        # Tuple arguments, for example, will produce constraints
        for a in ast.formals():
            for c in self.visit(a):
                yield c

        # Produce all the constraints for the body
        for c in self.visit_block(ast, restype, ast.body()):
            yield c

        con.monomorphs = prior_monomorphs

        M = set(self.context.monomorphs)
        yield Generalizing(ast.name().type, T.Fn(formals_types, restype), M,
                           ast)

        con.end_scope()
예제 #4
0
    def _Lambda(self, ast):
        restype = ast.parameters[0].type
        argnames = [arg.id for arg in ast.variables]
        argtypes = [arg.type for arg in ast.variables]

        con = self.context
        con.begin_scope()
        con.typings.update(dict(zip(argnames, argtypes)))
        con.monomorphs.update(argtypes)

        for c in self.visit_children(ast):
            yield c

        self.context.end_scope()

        yield Equality(ast.type, T.Fn(argtypes, restype), ast)
예제 #5
0
    def _Map(self, ast):
        for c in self.visit_children(ast):
            yield c

        fn, args = ast.parameters[0], ast.parameters[1:]
        argtypes = [x.type for x in args]

        # Type variables that name the element types for each of the
        # argument sequences
        items = self.context.fresh_typelist(args)

        for itemtype, seqtype in zip(items, argtypes):
            itemtype.source = None
            yield Equality(seqtype, T.Seq(itemtype), ast)

        restype = self.context.fresh_typevar()
        restype.source = None

        yield Equality(fn.type, T.Fn(items, restype), ast)
        yield Equality(ast.type, T.Seq(restype), ast)
예제 #6
0
 def _BinOp(self, tree):
     if type(tree.op) != pyast.ast.RShift:
         raise SyntaxError, "illegal type operator (%s)" % tree.op
     L = self.visit(tree.left)
     R = self.visit(tree.right)
     return T.Fn(L, R)