Ejemplo n.º 1
0
 def _Closure(self, c):
     closed_over_literal = any(
         map(lambda x: not isinstance(x, S.Name), c.closed_over()))
     if not closed_over_literal:
         return c
     #Find procedure being closed over
     proc_name = c.body().id
     proc = self.procedures[proc_name]
     proc_args = proc.formals()
     closed_args = c.closed_over()
     #Construct new set of arguments, with literals closed over removed
     replaced_args = proc_args[:-len(closed_args)]
     replaced_closed_over = []
     #Also record what replacements to make
     replacement = {}
     for orig_arg, closed_arg in zip(proc_args[-len(closed_args):],
                                     closed_args):
         if isinstance(closed_arg, S.Name):
             replaced_args.append(orig_arg)
             replaced_closed_over.append(closed_arg)
         else:
             replacement[orig_arg.id] = closed_arg
     #If we are only closing over literals, we will return a name
     #rather than a reduced closure. Check.
     fully_opened = len(replacement) == len(closed_args)
     replaced_stmts = [
         S.substituted_expression(si, replacement) \
             for si in proc.body()]
     replaced_name = S.Name(proc_name + self.name_supply.next())
     self.propagated.append(
         S.Procedure(replaced_name, replaced_args, replaced_stmts))
     if fully_opened:
         return replaced_name
     else:
         return S.Closure(replaced_closed_over, replaced_name)
Ejemplo n.º 2
0
    def _Lambda(self, e):
        fn = S.Name(self.names.next())

        self.rewrite_children(e)
        body = S.Return(e.parameters[0])
        self.proclist.append(S.Procedure(fn, e.variables, [body]))

        return fn
Ejemplo n.º 3
0
 def _Apply(self, ast):
     fn_id = ast.function().id
     if fn_id in self.applies:
         args = ast.arguments()
         arity = len(args)
         return S.Apply(S.Name(fn_id + str(arity)), args)
     else:
         return ast
Ejemplo n.º 4
0
 def make_name(arg):
     if not isinstance(arg, S.Tuple):
         return arg
     else:
         made_name = S.Name(names.next())
         assembled = S.Bind(S.Tuple(*[make_name(x) for x in arg]),
                            made_name)
         disassembly.insert(0, assembled)
         return made_name
Ejemplo n.º 5
0
 def _Return(self, stmt):
     e = self.rewrite(stmt.value())
     if isinstance(e, S.Name):
         stmt.parameters = [e]
         self.emit(stmt)
         return
     # If we're returning a tuple, we always copy the value into a return
     # variable.  We may undo this later on, for entry-point procedures.
     ret = S.Name("result")
     self.emit(S.Bind(ret, e))
     stmt.parameters = [ret]
     self.emit(stmt)
Ejemplo n.º 6
0
    def _Bind(self, stmt):
        var = stmt.binder()
        varNames = [x.id for x in flatten(var)]
        operation = S.substituted_expression(stmt.value(), self.env)
        for name in varNames:
            if name not in self.exceptions:
                rename = '%s_%s' % (name, self.serial.next())
            else:
                rename = name

            self.env[name] = S.Name(rename)
        result = S.Bind(S.substituted_expression(var, self.env), operation)
        return result
Ejemplo n.º 7
0
    def _Lambda(self, e):
        _ClosureRecursion._Lambda(self, e)

        formals = [v.id for v in flatten(e.formals())]
        # Take the free variable list, stick it in a set to make sure we don't
        # duplicate a variable, and then put it back in a list to make sure
        # it's got a defined ordering, which sets don't have
        free = list(
            set([
                v for v in S.free_variables(e.body(), formals) if v in self.env
            ]))

        if free:
            bound = [S.Name("_K%d" % i) for i in range(len(free))]
            body = S.substituted_expression(e.body(), dict(zip(free, bound)))

            e.parameters = [body]
            e.variables = e.variables + bound

            return S.Closure([S.Name(x) for x in free], e)
        else:
            return e
Ejemplo n.º 8
0
    def _Apply(self, ast):
        fn_id = ast.function().id
        arity = -1
        if fn_id in self.applies:
            args = ast.arguments()
            arity = len(args)
        elif fn_id in self.binders:
            arity = self.arity
            assert (arity > 0)

        if arity > 0:
            return S.Apply(S.Name(fn_id + str(arity)), ast.arguments())
        else:
            return ast
Ejemplo n.º 9
0
 def _Expression(self, e):
     subexpressions = e.parameters
     e.parameters = []
     for sub in subexpressions:
         sub = self.rewrite(sub)
         # XXX It doesn't seem right to include Closure on this list
         #     of "atomic" values.  But phase_assignment breaks if I
         #     don't do this.
         if not isinstance(sub, (S.Name, S.Literal, S.Closure)):
             tn = S.Name(self.names.next())
             self.emit(S.Bind(tn, sub))
         else:
             tn = sub
         e.parameters.append(tn)
     return e
Ejemplo n.º 10
0
    def _Procedure(self, ast):
        binders = [v.id
                   for v in flatten(ast.variables)]  # NOTE: this includes name

        _ClosureRecursion._Procedure(self, ast)

        # Take the free variable list, stick it in a set to make sure we don't
        # duplicate a variable, and then put it back in a list to make sure
        # it's got a defined ordering, which sets don't have
        free = list(
            set([
                v for v in S.free_variables(ast.body(), binders)
                if v in self.env
            ]))

        if free:
            bound = [S.Name("_K%d" % i) for i in range(len(free))]
            ast.variables = ast.variables + bound
            ast.parameters = S.substituted_expression(ast.parameters,
                                                      dict(zip(free, bound)))

            # Transform recursive calls of this procedure within its own body.
            recursive = _ClosureRecursion(self.env)
            self.env[ast.name().id] = bound
            ast.parameters = recursive.rewrite(ast.parameters)

            # Register rewrite for calls to this procedure in later
            # parts of the defining scope
            self.env[ast.name().id] = S.Closure([S.Name(x) for x in free],
                                                ast.name())
        # else:


#             self.locally_bound([ast.name()])

        return ast
Ejemplo n.º 11
0
 def _Return(self, stmt):
     e = self.rewrite(stmt.value())
     if isinstance(e, S.Name):
         # If we're returning one of the procedure formals unchanged,
         # we need to copy its value into a return variable.
         # Here is where we check:
         if e.id not in self.formals:
             #No need to copy value into a return variable
             stmt.parameters = [e]
             self.emit(stmt)
             return
     # If we're returning a tuple, we always copy the value into a return
     # variable.  We may undo this later on, for entry-point procedures.
     ret = S.Name("result")
     self.emit(S.Bind(ret, e))
     stmt.parameters = [ret]
     self.emit(stmt)
Ejemplo n.º 12
0
 def build_cast(cast_name, args):
     "Helper function to build cast expressions"
     return S.Apply(S.Name(cast_name), args)
Ejemplo n.º 13
0
 def _Map(self, ast):
     args = ast.parameters
     arity = len(args) - 1
     assert (arity > 0)
     return S.Apply(S.Name('map' + str(arity)), args)
Ejemplo n.º 14
0
 def mark_user(x):
     return S.mark_user(S.Name(x)).id