Example #1
0
def substituted_expression(e, env):
    """
    Return an expression with all freely occurring identifiers in E
    replaced by their corresponding value in ENV.
    """
    from pltools import Environment
    subst = Environment(env)
    rewriter = VariableSubstitute(subst)
    return rewriter.rewrite(e)
Example #2
0
    def __init__(self, globals=None, tvsupply=None):

        # Record the global Python namespace (if any) in which code is
        # defined.  This maps identifiers to values; by convention
        # Copperhead objects have a 'cu_type' slot that we will
        # use for typing information.
        #
        # This dictionary should never be modified.
        self.globals = globals or dict()

        # Supply of unique type variable names: #tv0, #tv1, #tv2, ...
        # They're known to be unique because they are illegal identifiers.
        self._tvsupply = tvsupply or name_supply(['#tv'], drop_zero=False)

        # The typings environment maps local identifiers to their
        # corresponding types.
        self.typings = Environment()

        # Type variables associated with formal parameters, both in
        # lambdas and procedures, are required to be monomorphic.  This
        # set records all introduced type variables that are known to be
        # monomorphic.  Since we make all internal variables unique, we
        # only need a single set for this, rather than a hierarchical
        # environment structure as with self.typings.
        self.monomorphs = set()

        # During inference, we accumulate a set of freely occurring
        # identifiers.  This set contains AST nodes, rather than names.
        # Thus, multiple occurrences of a given name (e.g., 'x') may be
        # found in this set if they occurred at separate source
        # locations.  For example, the expression 'x+x' will introduce
        # two free occurrences, not one.
        self.free_occurrences = set()

        # The inference system builds up a set of assumptions about the
        # types of identifiers occurring outside the current compilation
        # unit and which have no known 'cu_type' attribute.
        # This table provides a mapping from type variables created for
        # free occurrences to the AST node at which they occur.
        self.assumptions = dict()
Example #3
0
    def __init__(self,
                 globals=None,
                 tvsupply=None):

        # Record the global Python namespace (if any) in which code is
        # defined.  This maps identifiers to values; by convention
        # Copperhead objects have a 'cu_type' slot that we will
        # use for typing information.
        #
        # This dictionary should never be modified.
        self.globals = globals or dict()

        # Supply of unique type variable names: #tv0, #tv1, #tv2, ...
        # They're known to be unique because they are illegal identifiers.
        self._tvsupply = tvsupply or name_supply(['#tv'], drop_zero=False)

        # The typings environment maps local identifiers to their
        # corresponding types.
        self.typings = Environment()

        # Type variables associated with formal parameters, both in
        # lambdas and procedures, are required to be monomorphic.  This
        # set records all introduced type variables that are known to be
        # monomorphic.  Since we make all internal variables unique, we
        # only need a single set for this, rather than a hierarchical
        # environment structure as with self.typings.
        self.monomorphs = set()

        # During inference, we accumulate a set of freely occurring
        # identifiers.  This set contains AST nodes, rather than names.
        # Thus, multiple occurrences of a given name (e.g., 'x') may be
        # found in this set if they occurred at separate source
        # locations.  For example, the expression 'x+x' will introduce
        # two free occurrences, not one.
        self.free_occurrences = set()

        # The inference system builds up a set of assumptions about the
        # types of identifiers occurring outside the current compilation
        # unit and which have no known 'cu_type' attribute.
        # This table provides a mapping from type variables created for
        # free occurrences to the AST node at which they occur.
        self.assumptions = dict()
Example #4
0
class TypingContext:
    """
    Encapsulate information passed around during type inference.
    Binding everything up in a structure like this makes it possible to
    add optional annotations without rewriting the parameter lists of
    all procedures involved in inference.
    """
    def __init__(self, globals=None, tvsupply=None):

        # Record the global Python namespace (if any) in which code is
        # defined.  This maps identifiers to values; by convention
        # Copperhead objects have a 'cu_type' slot that we will
        # use for typing information.
        #
        # This dictionary should never be modified.
        self.globals = globals or dict()

        # Supply of unique type variable names: #tv0, #tv1, #tv2, ...
        # They're known to be unique because they are illegal identifiers.
        self._tvsupply = tvsupply or name_supply(['#tv'], drop_zero=False)

        # The typings environment maps local identifiers to their
        # corresponding types.
        self.typings = Environment()

        # Type variables associated with formal parameters, both in
        # lambdas and procedures, are required to be monomorphic.  This
        # set records all introduced type variables that are known to be
        # monomorphic.  Since we make all internal variables unique, we
        # only need a single set for this, rather than a hierarchical
        # environment structure as with self.typings.
        self.monomorphs = set()

        # During inference, we accumulate a set of freely occurring
        # identifiers.  This set contains AST nodes, rather than names.
        # Thus, multiple occurrences of a given name (e.g., 'x') may be
        # found in this set if they occurred at separate source
        # locations.  For example, the expression 'x+x' will introduce
        # two free occurrences, not one.
        self.free_occurrences = set()

        # The inference system builds up a set of assumptions about the
        # types of identifiers occurring outside the current compilation
        # unit and which have no known 'cu_type' attribute.
        # This table provides a mapping from type variables created for
        # free occurrences to the AST node at which they occur.
        self.assumptions = dict()

    ######################################################################
    #
    # The following methods provide convenient ways of working with the
    # state encapsulated in the TypingContext
    #

    def fresh_typevar(self):
        return T.Typevar(self._tvsupply.next())

    def fresh_typevars(self, n):
        return [T.Typevar(n) for n in islice(self._tvsupply, n)]

    def fresh_typelist(self, keys, varmap=None):
        tvs = [self.fresh_typevar() for k in keys]
        if varmap:
            for k, v in zip(keys, tvs):
                varmap[k] = v
        return tvs

    def begin_scope(self):
        self.typings.begin_scope()

    def end_scope(self):
        self.typings.end_scope()

    def assuming(self, t, ast):
        assert t not in self.assumptions.keys()
        self.assumptions[t] = ast
        self.free_occurrences.add(ast)
        # XXX because monomorphs is scoped within functions, we treat
        # assumptions specially when generalizing bindings rather than
        # accumulating them here
        #self.monomorphs.add(t)

    ######################################################################
    #
    # Following are the methods required by the unification interface.
    #

    def instantiate(tcon, t):
        'Instantiate Polytypes as Monotypes with fresh type variables'
        if isinstance(t, T.Polytype):
            vars = tcon.fresh_typelist(t.variables)
            return T.substituted_type(t.monotype(),
                                      dict(zip(t.variables, vars)))
        else:
            return t

    def resolve_variable(tcon, t):
        'Resolve current mapping (if any) of typevars'
        if isinstance(t, T.Typevar): return resolve(t, tcon.typings)
        else: return t

    def occurs_check(tcon, t1, t2):
        if T.occurs(t1, t2):
            raise InferenceError, "%s occurs in %s" % (t1, t2)

    def is_variable(tcon, t):
        return isinstance(t, T.Typevar)

    def error(tcon, msg):
        raise InferenceError, msg
Example #5
0
class TypingContext:
    """
    Encapsulate information passed around during type inference.
    Binding everything up in a structure like this makes it possible to
    add optional annotations without rewriting the parameter lists of
    all procedures involved in inference.
    """

    def __init__(self,
                 globals=None,
                 tvsupply=None):

        # Record the global Python namespace (if any) in which code is
        # defined.  This maps identifiers to values; by convention
        # Copperhead objects have a 'cu_type' slot that we will
        # use for typing information.
        #
        # This dictionary should never be modified.
        self.globals = globals or dict()

        # Supply of unique type variable names: #tv0, #tv1, #tv2, ...
        # They're known to be unique because they are illegal identifiers.
        self._tvsupply = tvsupply or name_supply(['#tv'], drop_zero=False)

        # The typings environment maps local identifiers to their
        # corresponding types.
        self.typings = Environment()

        # Type variables associated with formal parameters, both in
        # lambdas and procedures, are required to be monomorphic.  This
        # set records all introduced type variables that are known to be
        # monomorphic.  Since we make all internal variables unique, we
        # only need a single set for this, rather than a hierarchical
        # environment structure as with self.typings.
        self.monomorphs = set()

        # During inference, we accumulate a set of freely occurring
        # identifiers.  This set contains AST nodes, rather than names.
        # Thus, multiple occurrences of a given name (e.g., 'x') may be
        # found in this set if they occurred at separate source
        # locations.  For example, the expression 'x+x' will introduce
        # two free occurrences, not one.
        self.free_occurrences = set()

        # The inference system builds up a set of assumptions about the
        # types of identifiers occurring outside the current compilation
        # unit and which have no known 'cu_type' attribute.
        # This table provides a mapping from type variables created for
        # free occurrences to the AST node at which they occur.
        self.assumptions = dict()


    ######################################################################
    #
    # The following methods provide convenient ways of working with the
    # state encapsulated in the TypingContext
    #

    def fresh_typevar(self):
        return T.Typevar(self._tvsupply.next())

    def fresh_typevars(self, n):
        return [T.Typevar(n) for n in islice(self._tvsupply, n)]

    def fresh_typelist(self, keys, varmap=None):
        tvs = [self.fresh_typevar() for k in keys]
        if varmap:
            for k, v in zip(keys, tvs):
                varmap[k] = v
        return tvs

    def begin_scope(self):
        self.typings.begin_scope()
       
    def end_scope(self):
        self.typings.end_scope()

    def assuming(self, t, ast):
        assert t not in self.assumptions.keys()
        self.assumptions[t] = ast
        self.free_occurrences.add(ast)
        # XXX because monomorphs is scoped within functions, we treat
        # assumptions specially when generalizing bindings rather than
        # accumulating them here
        #self.monomorphs.add(t)

    ######################################################################
    #
    # Following are the methods required by the unification interface.
    #
       
    def instantiate(tcon, t):
        'Instantiate Polytypes as Monotypes with fresh type variables'
        if isinstance(t, T.Polytype):
            vars = tcon.fresh_typelist(t.variables)
            return T.substituted_type(t.monotype(),
                                      dict(zip(t.variables, vars)))
        else:
            return t

    def resolve_variable(tcon, t):
        'Resolve current mapping (if any) of typevars'
        if isinstance(t, T.Typevar): return resolve(t, tcon.typings)
        else: return t
        
    def occurs_check(tcon, t1, t2):
        if T.occurs(t1, t2):
            raise InferenceError, "%s occurs in %s" % (t1,t2)

    def is_variable(tcon, t):  return isinstance(t, T.Typevar)

    def error(tcon, msg):  raise InferenceError, msg
Example #6
0
def closure_conversion(ast, M):
    'Perform closure conversion'
    env = Environment(M.globals, __builtin__.__dict__)
    return Front.closure_conversion(ast, env)
Example #7
0
def free_variables(e, env={}):
    'Generates all freely occurring identifiers in E not bound in ENV.'
    from pltools import Environment
    return FreeVariables(Environment(env)).visit(e)