예제 #1
0
파일: inference.py 프로젝트: WuCPMark/TFJ
    def _Bind(self, ast):
        type = self.expression_type(ast.value())

        # Convert functional types to polytypes as necessary
        if isinstance(type, T.Fn):
            free = [v for v in AST.free_variables(ast.value(), {})]
            bound = [self.tcon.typings[id] for id in free]
            bound = [resolve(t, self.tcon.environment) for t in bound]
            type = T.quantify_type(type, bound)

        ##This code allows us to unpack tuples returned from functions
        def match(binder, type):
            if isinstance(binder, AST.Name):
                self.tcon.typings[binder.id] = type
            elif isinstance(binder, AST.Tuple):
                if len(binder.parameters)!=len(type.parameters):
                    raise InferenceError, \
                            "binder and value don't match (%s)" % ast
                for b, t in zip(binder.parameters, type.parameters):
                    match(b, t)
            else:
                raise InferenceError, "illegal binder (%s)" % ast

        match(ast.binder(), type)

        return None
예제 #2
0
파일: inference.py 프로젝트: WuCPMark/TFJ
def normalize_type(t, tcon):
    """
    Return a normalized type that eliminates all free variables from 't'.
    Any type variables bound in the given context will be resolved, and
    all remaining variables will be quantified with a Polytype.
    """
    return T.quantify_type(resolve_type(t, tcon))
예제 #3
0
def infer(P, verbose=False, globals=None, context=None, input_types=None):
    'Run type inference on the given AST.  Returns the inferred type.'
    tcon = context or TypingContext(globals=globals)
    # Label every AST node with a temporary type variable
    L = TypeLabeling(tcon)
    L.verbose = verbose
    L.visit(P)

    # Generate constraints from AST
    # And chain them to constraints from input_types
    C = chain(
        ConstrainInputTypes(input_types).visit(P),
        ConstraintGenerator(tcon).visit(P))

    S = Solver1(C, tcon)
    S.verbose = verbose

    S.solve()

    if verbose:
        print "\nThe free occurrence set is:"
        print "    ", tcon.free_occurrences
        print "\nThe assumption set is:"
        print "    ", tcon.assumptions

    if len(tcon.free_occurrences) > 0:
        undef = set([x.id for x in tcon.free_occurrences])
        raise InferenceError, 'undefined variables: %s' % list(undef)

    if len(tcon.assumptions) > 0:
        assumed = set(assumptions.values())
        raise InferenceError, 'unexplored assumptions: %s' % list(assumed)

    # Resolve the AST type slots to their solved types
    TypeResolution(S.solution, S.quantified).visit(P)

    # Resolve any outstanding variables in the typing context
    # XXX it's inefficient to go through the whole typings
    # environment when we could just record which ones were
    # introduced by the program P
    for id in tcon.typings:
        t = tcon.typings[id]
        if t in S.solution:
            tcon.typings[id] = resolve_type(t, S.solution)

    if isinstance(P, list):
        result = getattr(P[-1], 'type', T.Void)
    else:
        result = getattr(P, 'type', T.Void)

    # We quantify here to normalize the result of this procedure.
    # For instance, running the solver on a polymorphic expression like
    # "op_plus" will instantiate the polytype for op_plus with fresh
    # type variables.  While what we want internally, this is not what
    # external clients expect.
    return T.quantify_type(result)
예제 #4
0
def infer(P, verbose=False, globals=None, context=None, input_types=None):
    'Run type inference on the given AST.  Returns the inferred type.'
    tcon = context or TypingContext(globals=globals)
    # Label every AST node with a temporary type variable
    L = TypeLabeling(tcon)
    L.verbose = verbose
    L.visit(P)

    # Generate constraints from AST
    # And chain them to constraints from input_types
    C = chain(ConstrainInputTypes(input_types).visit(P),
              ConstraintGenerator(tcon).visit(P))


    S = Solver1(C,tcon)
    S.verbose = verbose

    S.solve()

    if verbose:
        print "\nThe free occurrence set is:"
        print "    ", tcon.free_occurrences
        print "\nThe assumption set is:"
        print "    ", tcon.assumptions

    if len(tcon.free_occurrences) > 0:
        undef = set([x.id for x in tcon.free_occurrences])
        raise InferenceError, 'undefined variables: %s' % list(undef)

    if len(tcon.assumptions) > 0:
        assumed = set(assumptions.values())
        raise InferenceError, 'unexplored assumptions: %s' % list(assumed)

    # Resolve the AST type slots to their solved types
    TypeResolution(S.solution, S.quantified).visit(P)

    # Resolve any outstanding variables in the typing context
    # XXX it's inefficient to go through the whole typings
    # environment when we could just record which ones were
    # introduced by the program P
    for id in tcon.typings:
        t = tcon.typings[id]
        if t in S.solution:
            tcon.typings[id] = resolve_type(t, S.solution)

    if isinstance(P, list):
        result = getattr(P[-1], 'type', T.Void)
    else:
        result = getattr(P, 'type', T.Void)
        
    # We quantify here to normalize the result of this procedure.
    # For instance, running the solver on a polymorphic expression like
    # "op_plus" will instantiate the polytype for op_plus with fresh
    # type variables.  While what we want internally, this is not what
    # external clients expect.
    return T.quantify_type(result)
예제 #5
0
    def generalize_binding(self, t1, t2, M):
        assert isinstance(t1, T.Typevar)
        assert isinstance(t2, (T.Typevar, T.Monotype))

        # Generalization occurs for identifiers introduced in
        # declaration statements.  This may, for instance, occur as the
        # result of a declaration:
        #     x = E
        # or a procedure definition
        #     def f(...): S
        #
        # The type variable t1 associated with the binder (e.g., 'x') is
        # allowed to become a Polytype.  We generate this polytype by
        # quantifying over the free variables of t2 that do not occur in
        # M.

        # NOTE: In general, we must be careful about when we can solve
        # Generalizing constraints.  In the current solver, where
        # constraints are generated in post-order, they can be solved
        # immediately.  In other orderings, they may need to be deferred
        # if they contain "active" type variables.

        r1 = resolve(t1, self.solution)
        r2 = resolve_type(t2, self.solution)

        if self.verbose:
            print "\tt1 =", t1
            print "\tt2 =", t2
            print "\tresolve(t1) =", r1
            print "\tresolve(t2) =", r2

        if r1 != t1 and isinstance(r2, T.Monotype):
            self.unify_monotypes(r1, r2)
            r2 = resolve_type(t2, self.solution)

        # The set of type variables associated with assumptions should
        # also be treated as monomorphs.  While we may have made
        # assumptions about a polymorphic function, we will have
        # generated a fresh type variable for each occurrence.  These
        # type variables are thus properly monomorphic.
        #
        R = set()
        for x in chain(M, self.context.assumptions.keys()):
            R |= set(T.names_in_type(resolve_type(x, self.solution)))

        if self.verbose:
            print "\tR =", R

        assert self.context.is_variable(t1)
        self.solution[t1] = T.quantify_type(r2, R, self.quantified)
        if self.verbose:
            print "\t--> Quantifying", t2, "to", self.solution[t1]
예제 #6
0
    def generalize_binding(self, t1, t2, M):
        assert isinstance(t1, T.Typevar)
        assert isinstance(t2, (T.Typevar, T.Monotype))

        # Generalization occurs for identifiers introduced in
        # declaration statements.  This may, for instance, occur as the
        # result of a declaration:
        #     x = E
        # or a procedure definition
        #     def f(...): S
        #
        # The type variable t1 associated with the binder (e.g., 'x') is
        # allowed to become a Polytype.  We generate this polytype by
        # quantifying over the free variables of t2 that do not occur in
        # M.

        # NOTE: In general, we must be careful about when we can solve
        # Generalizing constraints.  In the current solver, where
        # constraints are generated in post-order, they can be solved
        # immediately.  In other orderings, they may need to be deferred
        # if they contain "active" type variables.

        r1 = resolve(t1, self.solution)
        r2 = resolve_type(t2, self.solution)

        if self.verbose:
            print "\tt1 =", t1
            print "\tt2 =", t2
            print "\tresolve(t1) =", r1
            print "\tresolve(t2) =", r2

        if r1 != t1 and isinstance(r2, T.Monotype):
            self.unify_monotypes(r1, r2)
            r2 = resolve_type(t2, self.solution)

        # The set of type variables associated with assumptions should
        # also be treated as monomorphs.  While we may have made
        # assumptions about a polymorphic function, we will have
        # generated a fresh type variable for each occurrence.  These
        # type variables are thus properly monomorphic.
        #
        R = set()
        for x in chain(M, self.context.assumptions.keys()):
            R |= set(T.names_in_type(resolve_type(x, self.solution)))

        if self.verbose:
            print "\tR =", R

        assert self.context.is_variable(t1)
        self.solution[t1] = T.quantify_type(r2, R, self.quantified)
        if self.verbose:
            print "\t--> Quantifying", t2, "to", self.solution[t1]
예제 #7
0
def type_from_text(text):
    past = pyast.ast.parse(_pythonify_type(text), "<type string>", mode='eval')
    return T.quantify_type(_convert_type(past))