Ejemplo n.º 1
0
    def visit_BoolOp_old(self, node):
        if len(node.values) > 2:
            raise ValueError(
                "cannot handle that yet. Maybe reduce in a separate step")

        left = node.values[0]
        left = self.visit(left)
        left = self.make_primitive(left)
        if isinstance(node.op, ast.And):
            condition = mk_not(left)
            condition = self.make_primitive(condition)
        else:
            condition = left

        self.start_frame()
        right = node.values[1]
        right = self.visit(right)
        right = self.make_primitive(right)
        right_statements = self.end_frame()

        result = self.id_factory("boolop")

        # if condition:
        #   result = left
        # else:
        #   right_statements
        #   result = right

        ifs = ast.If()
        ifs.test = condition
        ifs.body = [mk_assign(result, left)]
        ifs.orelse = right_statements + [mk_assign(result, right)]
        self.execute(ifs)
        return mk_name(result)
Ejemplo n.º 2
0
    def visit_FunctionDef(self, node):
        args = node.args

        if not args.defaults:
            return node

        orig_id = node.name
        node.name = self.id_factory(orig_id)

        parameters = mk_tuple(mk_str(arg.id) for arg in args.args)
        defaults = mk_tuple(args.defaults)

        parameters_id = self.id_factory("tuple")
        parameters_stmt = mk_assign(parameters_id, parameters)
        parameters = mk_name(parameters_id)

        defaults_id = self.id_factory("tuple")
        default_stmt = mk_assign(defaults_id, defaults)
        defaults = mk_name(defaults_id)

        args.defaults = []

        func_expr = mk_call("__pydron_defaults__",
                            [mk_name(node.name), parameters, defaults])
        assign_stmt = mk_assign(orig_id, func_expr)

        return [node, parameters_stmt, default_stmt, assign_stmt]
Ejemplo n.º 3
0
    def visit_BoolOp_old(self, node):
        if len(node.values) > 2:
            raise ValueError("cannot handle that yet. Maybe reduce in a separate step")

        left = node.values[0]
        left = self.visit(left)
        left = self.make_primitive(left)
        if isinstance(node.op, ast.And):
            condition = mk_not(left)
            condition = self.make_primitive(condition)
        else:
            condition = left

        self.start_frame()
        right = node.values[1]
        right = self.visit(right)
        right = self.make_primitive(right)
        right_statements = self.end_frame()

        result = self.id_factory("boolop")

        # if condition:
        #   result = left
        # else:
        #   right_statements
        #   result = right

        ifs = ast.If()
        ifs.test = condition
        ifs.body = [mk_assign(result, left)]
        ifs.orelse = right_statements + [mk_assign(result, right)]
        self.execute(ifs)
        return mk_name(result)
Ejemplo n.º 4
0
 def visit_FunctionDef(self, node):
     
     self.generic_visit(node)
            
     scopes = node.scopes
     shared = [var for var,scope in scopes.iteritems() if scope == scoping.Scope.SHARED]
     free = [var for var,scope in scopes.iteritems() if scope == scoping.Scope.FREE]
     
     # create cells first thing in body
     shared_stmts = [mk_assign(var, mk_call("__pydron_new_cell__", [mk_str(var)])) for var in shared]
     node.body = shared_stmts + node.body
     
     if free:
         # free vars become arguments
         free_args = [ast.Name(id=var, ctx=ast.Param()) for var in free]
         node.args.args = free_args + node.args.args
         
         # rename the function
         orig_name = node.name
         tmp_name = self.id_factory(node.name)
         node.name = tmp_name
         
         # wrap it
         if self._inside_class():
             wrap_args = [mk_name(naming.passthrough_var(var)) for var in free]
         else:
             wrap_args = [mk_name(var) for var in free]
         wrap_call = mk_call("__pydron_wrap_closure__", [mk_name(tmp_name), mk_tuple(wrap_args)])
         wrap_stmt = mk_assign(orig_name, wrap_call)
         
         
         return [node, wrap_stmt]
 
     else:
         return node
Ejemplo n.º 5
0
 def visit_FunctionDef(self, node):
     args = node.args
     
     if not args.defaults:
         return node
     
     orig_id = node.name
     node.name = self.id_factory(orig_id)
     
     parameters = mk_tuple(mk_str(arg.id) for arg in args.args)
     defaults = mk_tuple(args.defaults)
     
     parameters_id = self.id_factory("tuple")
     parameters_stmt = mk_assign(parameters_id, parameters)
     parameters = mk_name(parameters_id)
     
     defaults_id = self.id_factory("tuple")
     default_stmt = mk_assign(defaults_id, defaults)
     defaults = mk_name(defaults_id)
     
     args.defaults = []
     
     func_expr = mk_call("__pydron_defaults__", [mk_name(node.name), parameters, defaults])
     assign_stmt = mk_assign(orig_id, func_expr)
     
     return [node, parameters_stmt, default_stmt, assign_stmt]
Ejemplo n.º 6
0
 def visit_Return(self, node):
     node = self.generic_visit(node)
     if node.value:
         retval = mk_assign(self.retval_id, node.value)
     else:
         retval = mk_assign(self.retval_id, mk_name("None"))
     flag = mk_assign(self.flag_id, mk_str(self.RETURN))
     return [retval, flag], {"return"}, {"return"}
Ejemplo n.º 7
0
 def visit_Return(self, node):
     node = self.generic_visit(node)
     if node.value:
         retval = mk_assign(self.retval_id, node.value)
     else:
         retval = mk_assign(self.retval_id, mk_name("None"))
     flag = mk_assign(self.flag_id, mk_str(self.RETURN))
     return [retval, flag], {"return"}, {"return"}
Ejemplo n.º 8
0
 def recursive(values):
     if len(values) == 1:
         self.start_frame()
         stmt = mk_assign(target, self.visit(values[0]))
         return self.end_frame() + [stmt]
     else:
         self.start_frame()
         value = self.make_primitive(values[0])
         orelse = recursive(values[1:])
         body = [mk_assign(target, value)]
         ifstmt = ast.If(test=value, body=body, orelse=orelse)
         return self.end_frame() + [ifstmt]
Ejemplo n.º 9
0
 def recursive(values):
     if len(values) == 1:
         self.start_frame()
         stmt = mk_assign(target, self.visit(values[0]))
         return self.end_frame() + [stmt]
     else:
         self.start_frame()
         value = self.make_primitive(values[0])
         orelse = recursive(values[1:])
         body = [mk_assign(target, value)]
         ifstmt = ast.If(test=value, body=body, orelse=orelse)
         return self.end_frame() + [ifstmt]
Ejemplo n.º 10
0
    def visit_Compare(self, node):

        if len(node.ops) == 1:
            node.left = self.make_primitive(node.left)
            node.comparators = [self.make_primitive(node.comparators[0])]
            return node

        def check(left, ops, rights):
            self.start_frame()

            op = ops.pop(0)
            right = self.make_primitive(rights.pop(0))

            if ops:
                body = check(right, ops, rights)
            else:
                body = [mk_assign(target, mk_name("True"))]

            test = self.id_factory("test")
            self.execute(
                mk_assign(
                    test, ast.Compare(left=left, ops=[op],
                                      comparators=[right])))
            self.execute(ast.If(test=mk_name(test), body=body, orelse=[]))

            return self.end_frame()

        target = self.id_factory("compare")
        self.execute(mk_assign(target, mk_name("False")))
        left = self.make_primitive(node.left)

        body = check(left, list(node.ops), list(node.comparators))

        self.execute(body)
        return mk_name(target)
Ejemplo n.º 11
0
    def visit_ListComp(self, node):

        listvar = self.id_factory("listcomp")

        self.execute(mk_assign(listvar, mk_list([])))

        self.start_frame()
        add = ast.AugAssign()
        add.target = ast.Name(id=listvar, ctx=ast.Store())
        add.value = self.make_primitive(
            mk_list([self.make_primitive(node.elt)]))
        add.op = ast.Add()
        body = self.end_frame()
        body.append(add)

        for generator in reversed(node.generators):
            loop = self.build_comprehension(generator, body)
            body = [loop]

        outermost_loop = body[0]

        # Now simplify all expressions inside the generator.
        # We can do this now as we have a proper function
        outermost_loop = self.visit(outermost_loop)
        self.execute(outermost_loop)

        return mk_name(listvar)
Ejemplo n.º 12
0
        def check(left, ops, rights):
            self.start_frame()

            op = ops.pop(0)
            right = self.make_primitive(rights.pop(0))

            if ops:
                body = check(right, ops, rights)
            else:
                body = [mk_assign(target, mk_name("True"))]

            test = self.id_factory("test")
            self.execute(mk_assign(test, ast.Compare(left=left, ops=[op], comparators=[right])))
            self.execute(ast.If(test=mk_name(test), body=body, orelse=[]))

            return self.end_frame()
Ejemplo n.º 13
0
 def visit_ImportFrom(self, node):
     
     tmp_identifier = self._unique_mod_id()
     
     module_expr = self.import_call_expr(node.module, [alias.name for alias in node.names], node.level)
     statements = [mk_assign(tmp_identifier, module_expr)]
     
     if any(alias.name == "*" for alias in node.names):
         
         statements.append(self.unpack_star(tmp_identifier))
     else:
         for alias in node.names:
             asname = alias.asname if alias.asname else alias.name
             attr_expr = mk_attr(mk_name(tmp_identifier), alias.name)
             statements.append(mk_assign(asname, attr_expr))
     return statements
Ejemplo n.º 14
0
    def visit_ListComp(self, node):

        listvar = self.id_factory("listcomp")

        self.execute(mk_assign(listvar, mk_list([])))

        self.start_frame()
        add = ast.AugAssign()
        add.target = ast.Name(id=listvar, ctx=ast.Store())
        add.value = self.make_primitive(mk_list([self.make_primitive(node.elt)]))
        add.op = ast.Add()
        body = self.end_frame()
        body.append(add)

        for generator in reversed(node.generators):
            loop = self.build_comprehension(generator, body)
            body = [loop]

        outermost_loop = body[0]

        # Now simplify all expressions inside the generator.
        # We can do this now as we have a proper function
        outermost_loop = self.visit(outermost_loop)
        self.execute(outermost_loop)

        return mk_name(listvar)
Ejemplo n.º 15
0
    def visit_Compare(self, node):

        if len(node.ops) == 1:
            node.left = self.make_primitive(node.left)
            node.comparators = [self.make_primitive(node.comparators[0])]
            return node

        def check(left, ops, rights):
            self.start_frame()

            op = ops.pop(0)
            right = self.make_primitive(rights.pop(0))

            if ops:
                body = check(right, ops, rights)
            else:
                body = [mk_assign(target, mk_name("True"))]

            test = self.id_factory("test")
            self.execute(mk_assign(test, ast.Compare(left=left, ops=[op], comparators=[right])))
            self.execute(ast.If(test=mk_name(test), body=body, orelse=[]))

            return self.end_frame()

        target = self.id_factory("compare")
        self.execute(mk_assign(target, mk_name("False")))
        left = self.make_primitive(node.left)

        body = check(left, list(node.ops), list(node.comparators))

        self.execute(body)
        return mk_name(target)
Ejemplo n.º 16
0
    def visit_FunctionDef(self, node):

        self.generic_visit(node)

        scopes = node.scopes
        shared = [
            var for var, scope in scopes.iteritems()
            if scope == scoping.Scope.SHARED
        ]
        free = [
            var for var, scope in scopes.iteritems()
            if scope == scoping.Scope.FREE
        ]

        # create cells first thing in body
        shared_stmts = [
            mk_assign(var, mk_call("__pydron_new_cell__", [mk_str(var)]))
            for var in shared
        ]
        node.body = shared_stmts + node.body

        if free:
            # free vars become arguments
            free_args = [ast.Name(id=var, ctx=ast.Param()) for var in free]
            node.args.args = free_args + node.args.args

            # rename the function
            orig_name = node.name
            tmp_name = self.id_factory(node.name)
            node.name = tmp_name

            # wrap it
            if self._inside_class():
                wrap_args = [
                    mk_name(naming.passthrough_var(var)) for var in free
                ]
            else:
                wrap_args = [mk_name(var) for var in free]
            wrap_call = mk_call(
                "__pydron_wrap_closure__",
                [mk_name(tmp_name), mk_tuple(wrap_args)])
            wrap_stmt = mk_assign(orig_name, wrap_call)

            return [node, wrap_stmt]

        else:
            return node
Ejemplo n.º 17
0
    def visit_ImportFrom(self, node):

        tmp_identifier = self._unique_mod_id()

        module_expr = self.import_call_expr(
            node.module, [alias.name for alias in node.names], node.level)
        statements = [mk_assign(tmp_identifier, module_expr)]

        if any(alias.name == "*" for alias in node.names):

            statements.append(self.unpack_star(tmp_identifier))
        else:
            for alias in node.names:
                asname = alias.asname if alias.asname else alias.name
                attr_expr = mk_attr(mk_name(tmp_identifier), alias.name)
                statements.append(mk_assign(asname, attr_expr))
        return statements
Ejemplo n.º 18
0
 def visit_Delete(self, node):
     statements = []
     for target in node.targets:
         if isinstance(target, ast.Name):
             statements.append(mk_assign(target.id, mk_name('__pydron_unbound__')))
         else:
             statements.append(ast.Delete(targets=[target]))
     return statements
Ejemplo n.º 19
0
 def visit_Delete(self, node):
     statements = []
     for target in node.targets:
         if isinstance(target, ast.Name):
             statements.append(
                 mk_assign(target.id, mk_name('__pydron_unbound__')))
         else:
             statements.append(ast.Delete(targets=[target]))
     return statements
Ejemplo n.º 20
0
        def check(left, ops, rights):
            self.start_frame()

            op = ops.pop(0)
            right = self.make_primitive(rights.pop(0))

            if ops:
                body = check(right, ops, rights)
            else:
                body = [mk_assign(target, mk_name("True"))]

            test = self.id_factory("test")
            self.execute(
                mk_assign(
                    test, ast.Compare(left=left, ops=[op],
                                      comparators=[right])))
            self.execute(ast.If(test=mk_name(test), body=body, orelse=[]))

            return self.end_frame()
Ejemplo n.º 21
0
    def visit_IfExp(self, node):
        target = self.id_factory("ifexp")

        self.start_frame()
        body = self.visit(node.body)
        body_stmts = self.end_frame()
        body_stmts.append(mk_assign(target, body))

        self.start_frame()
        orelse = self.visit(node.orelse)
        orelse_stmts = self.end_frame()
        orelse_stmts.append(mk_assign(target, orelse))

        ifstmt = ast.If()
        ifstmt.test = self.make_primitive(self.visit(node.test))
        ifstmt.body = body_stmts
        ifstmt.orelse = orelse_stmts

        self.execute(ifstmt)
        return mk_name(target)
Ejemplo n.º 22
0
    def visit_Import(self, node):
        statements = []

        for alias in node.names:
            module_expr = self.import_call_expr(alias.name)
            identifier = alias.asname if alias.asname else alias.name
            identifier = identifier.split(".")[0]
            statement = mk_assign(identifier, module_expr)
            statements.append(statement)

        return statements
Ejemplo n.º 23
0
    def visit_IfExp(self, node):
        target = self.id_factory("ifexp")

        self.start_frame()
        body = self.visit(node.body)
        body_stmts = self.end_frame()
        body_stmts.append(mk_assign(target, body))

        self.start_frame()
        orelse = self.visit(node.orelse)
        orelse_stmts = self.end_frame()
        orelse_stmts.append(mk_assign(target, orelse))

        ifstmt = ast.If()
        ifstmt.test = self.make_primitive(self.visit(node.test))
        ifstmt.body = body_stmts
        ifstmt.orelse = orelse_stmts

        self.execute(ifstmt)
        return mk_name(target)
Ejemplo n.º 24
0
 def visit_Import(self, node):
     statements = []
     
     for alias in node.names:
         module_expr = self.import_call_expr(alias.name)
         identifier = alias.asname if alias.asname else alias.name
         identifier = identifier.split(".")[0]
         statement = mk_assign(identifier, module_expr)
         statements.append(statement)
         
     return statements
Ejemplo n.º 25
0
 def _visit_block(self, node, parameters):
     node = self.generic_visit(node)
     # initialize only variables that are not initialized at this point.
     localvars = set([var for var,scope in node.scopes.iteritems() if scope == scoping.Scope.LOCAL or scope == scoping.Scope.SHARED])
     localvars -= parameters
     
     localvars = [v for v in localvars if not v.startswith("__pydron")]
     
     assignments = [mk_assign(var, mk_name('__pydron_unbound__')) for var in localvars]
     node.body = assignments + node.body
     return node
Ejemplo n.º 26
0
 def visit_TryFinally(self, node):
     body, body_interrupts, _ = self.process_body(node.body)
     finalbody, finalbody_interrupts, _ = self.process_body(node.finalbody)
     
     orig_flag = self.id_factory("interrupted")
     
     # The finalbody statements are executed even if an interrupt was triggered.
     # Those statements might overwrite or reset the flag. We store
     # the original flag in a new variable so that we can 'merge' the two
     # flags afterwards.
     store = mk_assign(orig_flag, mk_name(self.flag_id))
     finalbody.insert(0, store)
     
     # pick the flag with higher priority:
     # None < continue < break < return
     maxflag = mk_call('__pydron_max__', [mk_name(self.flag_id), mk_name(orig_flag)])
     finalbody.append(mk_assign(self.flag_id, maxflag))
     
     node.body = body
     node.finalbody = finalbody
     return node, body_interrupts | finalbody_interrupts, set()
Ejemplo n.º 27
0
 def make_primitive(self, expr):
     if expr is None:
         return None
     if isinstance(expr, str):
         return expr
     expr = self.visit(expr)
     if isinstance(expr, ast.expr) and not is_primitive(expr):
         nicename = expr.__class__.__name__.lower()
         var = self.id_factory(nicename)
         self.execute(mk_assign(var, expr))
         return mk_name(var)
     else:
         return expr
Ejemplo n.º 28
0
 def make_primitive(self, expr):
     if expr is None:
         return None
     if isinstance(expr, str):
         return expr
     expr = self.visit(expr)
     if isinstance(expr, ast.expr) and not is_primitive(expr):
         nicename = expr.__class__.__name__.lower()
         var = self.id_factory(nicename)
         self.execute(mk_assign(var, expr))
         return mk_name(var)
     else:
         return expr
Ejemplo n.º 29
0
    def visit_TryFinally(self, node):
        body, body_interrupts, _ = self.process_body(node.body)
        finalbody, finalbody_interrupts, _ = self.process_body(node.finalbody)

        orig_flag = self.id_factory("interrupted")

        # The finalbody statements are executed even if an interrupt was triggered.
        # Those statements might overwrite or reset the flag. We store
        # the original flag in a new variable so that we can 'merge' the two
        # flags afterwards.
        store = mk_assign(orig_flag, mk_name(self.flag_id))
        finalbody.insert(0, store)

        # pick the flag with higher priority:
        # None < continue < break < return
        maxflag = mk_call(
            '__pydron_max__',
            [mk_name(self.flag_id), mk_name(orig_flag)])
        finalbody.append(mk_assign(self.flag_id, maxflag))

        node.body = body
        node.finalbody = finalbody
        return node, body_interrupts | finalbody_interrupts, set()
Ejemplo n.º 30
0
    def process_body(self, stmts):
        """
        Processes a sequence of statements.
        
        The returned code contains no interrupt statements
        and acts the same way the original code would, assuming
        that the first statement is executed (we don't handle
        interrupts that happen before).
        
        Returns a list of statements and a set with all interrupts
        that might be triggered within those statements.
        """
        stmt_iter = iter(stmts)
        body = []
        for stmt in stmt_iter:

            stmt, candidates, guaranteed = self.visit_with_interrupts(stmt)

            # If we know for sure that an interrupt will trigger, we
            # can remove the reminder of the statements.
            if guaranteed:
                self._merge(body, stmt)
                return body, candidates, guaranteed

            # If the previous statement might have interrupted,
            # we wrap all the remaining statements in an `if`
            # statement.
            elif candidates:

                # initialize the flag varible, so that it is defined
                # even if the interrupt does not trigger.
                # This happens before the statement that might trigger.
                init = mk_assign(self.flag_id, mk_str(self.NONE))
                body.insert(-1, init)

                self._merge(body, stmt)

                ifstmts, more_candidates, _ = self.wrap_with_if(
                    stmt_iter, candidates)
                body.extend(ifstmts)

                # The rest of the body might trigger other
                # interrupts as well.
                return body, candidates | more_candidates, set()

            else:
                self._merge(body, stmt)

        return body, set(), set()
Ejemplo n.º 31
0
 def process_body(self, stmts):
     """
     Processes a sequence of statements.
     
     The returned code contains no interrupt statements
     and acts the same way the original code would, assuming
     that the first statement is executed (we don't handle
     interrupts that happen before).
     
     Returns a list of statements and a set with all interrupts
     that might be triggered within those statements.
     """
     stmt_iter = iter(stmts)
     body = []
     for stmt in stmt_iter:
         
         stmt, candidates, guaranteed = self.visit_with_interrupts(stmt)
         
         
         # If we know for sure that an interrupt will trigger, we
         # can remove the reminder of the statements.
         if guaranteed:
             self._merge(body, stmt)
             return body, candidates, guaranteed
         
         # If the previous statement might have interrupted,
         # we wrap all the remaining statements in an `if`
         # statement.
         elif candidates:
             
             # initialize the flag varible, so that it is defined
             # even if the interrupt does not trigger.
             # This happens before the statement that might trigger.
             init = mk_assign(self.flag_id, mk_str(self.NONE))
             body.insert(-1, init)
             
             self._merge(body, stmt)
            
             ifstmts, more_candidates, _ = self.wrap_with_if(stmt_iter, candidates)
             body.extend(ifstmts)
             
             # The rest of the body might trigger other
             # interrupts as well.
             return body, candidates | more_candidates, set()
         
         else:
             self._merge(body, stmt)
         
     return body, set(), set()
Ejemplo n.º 32
0
 def visit_FunctionDef(self, node):
     body, interrupts, guaranteed = self.process_body(node.body)
     
     if "return" in interrupts:
         if "return" not in guaranteed:
             init = mk_assign(self.retval_id, mk_name("None"))
             body.insert(0, init)
             
         ret = ast.Return(value=mk_name(self.retval_id))
         body.append(ret)
     else:
         ret = ast.Return(value=mk_name("None"))
         body.append(ret)
         
     node.body = body
     return node
Ejemplo n.º 33
0
    def visit_FunctionDef(self, node):
        body, interrupts, guaranteed = self.process_body(node.body)

        if "return" in interrupts:
            if "return" not in guaranteed:
                init = mk_assign(self.retval_id, mk_name("None"))
                body.insert(0, init)

            ret = ast.Return(value=mk_name(self.retval_id))
            body.append(ret)
        else:
            ret = ast.Return(value=mk_name("None"))
            body.append(ret)

        node.body = body
        return node
Ejemplo n.º 34
0
    def _visit_block(self, node, parameters):
        node = self.generic_visit(node)
        # initialize only variables that are not initialized at this point.
        localvars = set([
            var for var, scope in node.scopes.iteritems()
            if scope == scoping.Scope.LOCAL or scope == scoping.Scope.SHARED
        ])
        localvars -= parameters

        localvars = [v for v in localvars if not v.startswith("__pydron")]

        assignments = [
            mk_assign(var, mk_name('__pydron_unbound__')) for var in localvars
        ]
        node.body = assignments + node.body
        return node
Ejemplo n.º 35
0
 def visit_For(self, node):
     
     node = self.generic_visit(node)
     
     iterator_id = self.id_factory("iterator")
     iter_stmt = mk_assign(iterator_id, mk_call("__pydron_iter__", [node.iter]))
 
     test = mk_call("__pydron_hasnext__", [mk_name(iterator_id)])
     
     lhs = ast.Tuple(elts=[node.target, ast.Name(id=iterator_id, ctx=ast.Store())], ctx=ast.Store())
     next_stmt = ast.Assign(targets=[lhs], value=mk_call("__pydron_next__",  [mk_name(iterator_id)]))
     node.body.insert(0, next_stmt)
     
     while_stmt = ast.While(test=test, body=node.body, orelse=node.orelse)
     ast.copy_location(while_stmt, node)
     
     return [iter_stmt, while_stmt]
Ejemplo n.º 36
0
    def visit_Assign(self, node):
        if len(node.targets) <= 1:
            return node

        stmts = []
        if not (isinstance(node.value, ast.Name) or isinstance(
                node.value, ast.Str) or isinstance(node.value, ast.Num)):
            value_id = self.id_factory("value")
            stmts.append(mk_assign(value_id, node.value))
            value = mk_name(value_id)
        else:
            value = node.value

        for target in node.targets:
            s = ast.Assign(targets=[target], value=value)
            stmts.append(s)

        return stmts
Ejemplo n.º 37
0
 def visit_Assign(self, node):
     if len(node.targets) <= 1:
         return node
     
     stmts = []
     if not (isinstance(node.value, ast.Name) or 
             isinstance(node.value, ast.Str) or 
             isinstance(node.value, ast.Num)):
         value_id = self.id_factory("value")
         stmts.append(mk_assign(value_id, node.value))
         value = mk_name(value_id)
     else:
         value = node.value
         
     for target in node.targets:
         s = ast.Assign(targets=[target], value=value)
         stmts.append(s)
 
     return stmts
Ejemplo n.º 38
0
 def _dedecorate(self, node):
     if not node.decorator_list:
         return node
     
     # use a temporary name
     orig_id = node.name
     node.name = self.id_factory(orig_id)
     
     # call the decorators
     obj = mk_name(node.name)
     for decorator_expr in reversed(node.decorator_list):
         obj = mk_call_expr(decorator_expr, [obj])
         
     # assign to the original name
     assignment_stmt = mk_assign(orig_id, obj)
     
     node.decorator_list = []
     
     return [node, assignment_stmt]
Ejemplo n.º 39
0
    def _dedecorate(self, node):
        if not node.decorator_list:
            return node

        # use a temporary name
        orig_id = node.name
        node.name = self.id_factory(orig_id)

        # call the decorators
        obj = mk_name(node.name)
        for decorator_expr in reversed(node.decorator_list):
            obj = mk_call_expr(decorator_expr, [obj])

        # assign to the original name
        assignment_stmt = mk_assign(orig_id, obj)

        node.decorator_list = []

        return [node, assignment_stmt]
Ejemplo n.º 40
0
 def visit_ClassDef(self, node):
     node = self.generic_visit(node)
     
     # free variables of the class block become parameters of the function
     scopes = getattr(node, 'scopes', {})
     free = [var for var,scope in scopes.iteritems() if scope == scoping.Scope.FREE]
     free_param = [ast.Name(id=var, ctx=ast.Param()) for var in free]
     free_args = [ast.Name(id=var, ctx=ast.Load()) for var in free]
     
     # free variables of sub-blocks. Those need name mangling to avoid
     # collisions with variables local to the class block.
     passthrough = self.find_passthrough_vars(node)
     pt_param = [ast.Name(id=naming.passthrough_var(var), ctx=ast.Param()) for var in passthrough]
     pt_args = [ast.Name(id=var, ctx=ast.Load()) for var in passthrough]
     
     # function to execute the class body and collect the attributes
     func = ast.FunctionDef()
     func.name = self.id_factory("class_" + node.name)
     func.args = ast.arguments(args=free_param + pt_param, vararg=None, kwarg=None, defaults=[])
     func.body = node.body + [ast.Return(value=mk_name('__pydron_members__')) ]
     func.decorator_list = []
     
     # replicate name mangling of `LocalizeFreeVariables`
     all_args = free_args + pt_args
     if self._inside_class():
         for arg in all_args:
             arg.id = naming.passthrough_var(arg.id)
     
     # create the class
     typefunc = mk_call('__pydron_read_global__', [mk_str('type')])
     class_expr = mk_call_expr(typefunc, [mk_str(node.name), mk_tuple(node.bases), mk_call(func.name, all_args)])
     
     for decorator in reversed(node.decorator_list):
         class_expr = mk_call_expr(decorator, [class_expr])
     
     stmt = mk_assign(node.name, class_expr)
     
     return [func, stmt]
Ejemplo n.º 41
0
    def visit_ClassDef(self, node):
        node = self.generic_visit(node)

        # free variables of the class block become parameters of the function
        scopes = getattr(node, "scopes", {})
        free = [var for var, scope in scopes.iteritems() if scope == scoping.Scope.FREE]
        free_param = [ast.Name(id=var, ctx=ast.Param()) for var in free]
        free_args = [ast.Name(id=var, ctx=ast.Load()) for var in free]

        # free variables of sub-blocks. Those need name mangling to avoid
        # collisions with variables local to the class block.
        passthrough = self.find_passthrough_vars(node)
        pt_param = [ast.Name(id=naming.passthrough_var(var), ctx=ast.Param()) for var in passthrough]
        pt_args = [ast.Name(id=var, ctx=ast.Load()) for var in passthrough]

        # function to execute the class body and collect the attributes
        func = ast.FunctionDef()
        func.name = self.id_factory("class_" + node.name)
        func.args = ast.arguments(args=free_param + pt_param, vararg=None, kwarg=None, defaults=[])
        func.body = node.body + [ast.Return(value=mk_name("__pydron_members__"))]
        func.decorator_list = []

        # replicate name mangling of `LocalizeFreeVariables`
        all_args = free_args + pt_args
        if self._inside_class():
            for arg in all_args:
                arg.id = naming.passthrough_var(arg.id)

        # create the class
        typefunc = mk_call("__pydron_read_global__", [mk_str("type")])
        class_expr = mk_call_expr(typefunc, [mk_str(node.name), mk_tuple(node.bases), mk_call(func.name, all_args)])

        for decorator in reversed(node.decorator_list):
            class_expr = mk_call_expr(decorator, [class_expr])

        stmt = mk_assign(node.name, class_expr)

        return [func, stmt]
Ejemplo n.º 42
0
 def visit_ClassDef(self, node):
     self.generic_visit(node)
     stmt = mk_assign('__pydron_members__', mk_call('locals'))
     node.body.append(stmt)
     return node
Ejemplo n.º 43
0
 def visit_With(self, node):
     node = self.generic_visit(node)
     
     # Build equivalent code with try catch finally.
     # PEP-0343 provides the equivalent code for us.
     
     statements = []
     
     # mgr = node.expr
     mgr_id = self.id_factory("mgr")
     s = mk_assign(mgr_id, node.context_expr)
     statements.append(s)
     
     # exit = type(msg).__exit__
     exit_id = self.id_factory("exit")
     s = mk_assign(exit_id, mk_attr(mk_call('type', [mk_name(mgr_id)]), "__exit__"))
     statements.append(s)
     
     # value = type(msg).__enter__(mgr)
     value_id = self.id_factory("value")
     s = mk_assign(value_id, mk_call_expr(mk_attr(mk_call('type', [mk_name(mgr_id)]), "__enter__"), [mk_name(mgr_id)]))
     statements.append(s)
     
     # exc = True
     exc_id = self.id_factory("exc")
     s = mk_assign(exc_id, mk_name("True"))
     statements.append(s)
     
     # try:
     tryfinally_body = []
     tryfinally_finalbody = []
     s = ast.TryFinally(body=tryfinally_body, finalbody=tryfinally_finalbody)
     statements.append(s)
     
     #     try:
     tryexcept_body = []
     tryexcept_except = []
     expt_handler = ast.ExceptHandler(type=None,name=None,body=tryexcept_except)
     s = ast.TryExcept(body=tryexcept_body, handlers=[expt_handler], orelse=[])
     tryfinally_body.append(s)
     
     #         node.optional_vars = value
     if node.optional_vars:
         s = ast.Assign(targets=[node.optional_vars], value=mk_name(value_id))
         tryexcept_body.append(s)
         
     #         body
     tryexcept_body.extend(node.body)
         
     #     except:
 
     #         exc = False
     s = mk_assign(exc_id, mk_name("False"))
     tryexcept_except.append(s)
     
     #         sys.exc_info()
     sys_exc_info = mk_call_expr(mk_attr(mk_name('sys'), "exc_info"), [])
     #         exit(mgr, *sys.exc_info())
     exit_call = mk_call(exit_id, [mk_name(mgr_id)], vararg=sys_exc_info)
     #         not exit(mgr, *sys.exc_info())
     test = ast.UnaryOp(op=ast.Not(), operand=exit_call)
     
     #        if not exit(mgr, *sys.exc_info()):
     #            raise
     s = ast.If(test=test, body=[ast.Raise(type=None, inst=None, tback=None)], orelse=[])
     tryexcept_except.append(s)
     
     # finally:
     
     #     if exc:
     #       exit(mgr, None, None, None)
     exit_call = mk_call(exit_id, [mk_name(mgr_id), mk_name("None"), mk_name("None"), mk_name("None")])
     s = ast.If(test=mk_name(exc_id), body=[ast.Expr(value=exit_call)], orelse=[])
     tryfinally_finalbody.append(s)
     
     return statements
Ejemplo n.º 44
0
 def visit_Break(self, node):
     node = self.generic_visit(node)
     return mk_assign(self.flag_id, mk_str(self.BREAK)), {"break"}, {"break"}
Ejemplo n.º 45
0
 def visit_ClassDef(self, node):
     self.generic_visit(node)
     stmt = mk_assign('__pydron_members__', mk_call('locals'))
     node.body.append(stmt)
     return node
Ejemplo n.º 46
0
    def visit_FunctionDef(self, node):

        self.generic_visit(node)

        scopes = node.scopes
        shared = [
            var for var, scope in scopes.iteritems()
            if scope == scoping.Scope.SHARED
        ]
        free = [
            var for var, scope in scopes.iteritems()
            if scope == scoping.Scope.FREE
        ]

        # create cells first thing in body
        shared_stmts = [
            mk_assign(var, mk_call("__pydron_new_cell__", [mk_str(var)]))
            for var in shared
        ]

        fixed_arguments = []
        for arg in node.args.args:
            if isinstance(arg, ast.Attribute) and arg.attr == "cell_contents":
                # the generic_visit above made a mess. The attribute is
                # a free/shared variable and visit_Name replaced it with
                # an attribute. This makes no sense, so lets repair the damage.
                #
                # We don't want to change the parameter name. And I don't
                # want to change the variable name either. To solve this
                # we temporarily assign it to another variable:
                #
                # def foo(freevar):
                #    freevar__U0 = freevar
                #    freevar = __pydron_new_cell__('freevar')
                #    freevar.cell_contents = freevar__U0

                varname = arg.value.id

                tmp = self.id_factory(varname)

                # freevar__U0 = freevar
                shared_stmts.insert(0, mk_assign(tmp, mk_name(varname)))

                # freevar = __pydron_new_cell__('freevar')
                # is already in shared_stmts

                # reevar.cell_contents = freevar__U0
                arg.ctx = ast.Store()
                shared_stmts.append(
                    ast.Assign(targets=[arg], value=mk_name(tmp)))

                fixed_arguments.append(ast.Name(id=varname, ctx=ast.Param()))
            else:
                fixed_arguments.append(arg)
        node.args.args = fixed_arguments

        node.body = shared_stmts + node.body

        if free:
            # free vars become arguments
            free_args = [ast.Name(id=var, ctx=ast.Param()) for var in free]
            node.args.args = free_args + node.args.args

            # rename the function
            orig_name = node.name
            tmp_name = self.id_factory(node.name)
            node.name = tmp_name

            # wrap it
            if self._inside_class():
                wrap_args = [
                    mk_name(naming.passthrough_var(var)) for var in free
                ]
            else:
                wrap_args = [mk_name(var) for var in free]
            wrap_call = mk_call(
                "__pydron_wrap_closure__",
                [mk_name(tmp_name), mk_tuple(wrap_args)])
            wrap_stmt = mk_assign(orig_name, wrap_call)

            return [node, wrap_stmt]

        else:
            return node
Ejemplo n.º 47
0
 def visit_Continue(self, node):
     node = self.generic_visit(node)
     return mk_assign(self.flag_id, mk_str(self.CONTINUE)), {"continue"}, {"continue"}
Ejemplo n.º 48
0
    def _visit_loop(self, node, stop_iteration):

        body, body_interrupts, body_guranteed = self.process_body(node.body)
        orelse, orelse_interrupts, orelse_guranteed = self.process_body(
            node.orelse)

        # All interrupts of `orelse` propagate. Of `body` both `break` and `continue` are consumed
        # and only `return` goes on.
        for_interrupts = orelse_interrupts
        if "return" in body_interrupts:
            for_interrupts.add("return")

        if "break" not in body_interrupts and "return" not in body_interrupts:
            for_guranteed = orelse_guranteed
        else:
            for_guranteed = set()

        statements = []

        # Clear the 'continue' at the end of the body
        if "continue" in body_interrupts:
            # if flag == "continue":
            #    flag == None
            clearflag = mk_assign(self.flag_id, mk_str(self.NONE))
            if "continue" not in body_guranteed:
                comparison = ast.Compare(left=mk_name(self.flag_id),
                                         ops=[ast.Eq()],
                                         comparators=[mk_str(self.CONTINUE)])
                ifstmt = ast.If(test=comparison, body=[clearflag], orelse=[])
                body.append(ifstmt)
            else:
                body.append(clearflag)

        # init the flags for "break" for the case when there isn't a single iteration.
        # If we 'pass on' some interrupts then body_visit will take care of this.
        if "break" in body_interrupts and "return" not in for_interrupts:
            statements.append(mk_assign(self.flag_id, mk_str(self.NONE)))

        # Assemble modified loop.
        node.body = body
        node.orelse = []

        # make the loop stop on 'break' and 'return'
        if "break" in body_interrupts or "return" in body_interrupts:
            stop_iteration(node)

        # Add the loop to the result
        statements.append(node)

        # `orelse`
        if "break" in body_interrupts or "return" in body_interrupts:
            # the `orelse` section may or may not execute

            if "break" in body_interrupts:
                # if flag == "break":
                #    flag == None
                clearflag = mk_assign(self.flag_id, mk_str(self.NONE))
                comparison = ast.Compare(left=mk_name(self.flag_id),
                                         ops=[ast.Eq()],
                                         comparators=[mk_str(self.BREAK)])
                clear_break = [
                    ast.If(test=comparison, body=[clearflag], orelse=[])
                ]
            else:
                clear_break = []

            if not orelse:
                statements.extend(clear_break)
            else:
                # if flag == None
                #     ORELSSE
                # else:
                #     clear_break
                comparison = ast.Compare(left=mk_name(self.flag_id),
                                         ops=[ast.Eq()],
                                         comparators=[mk_str(self.NONE)])
                orelse_if = ast.If(test=comparison,
                                   body=orelse,
                                   orelse=clear_break)
                statements.append(orelse_if)
        else:
            # there is no `break` therefore `orelse` is always executed.
            statements.extend(orelse)

        return statements, for_interrupts, for_guranteed
Ejemplo n.º 49
0
 def visit_Break(self, node):
     node = self.generic_visit(node)
     return mk_assign(self.flag_id,
                      mk_str(self.BREAK)), {"break"}, {"break"}
Ejemplo n.º 50
0
 def visit_Continue(self, node):
     node = self.generic_visit(node)
     return mk_assign(self.flag_id,
                      mk_str(self.CONTINUE)), {"continue"}, {"continue"}
Ejemplo n.º 51
0
    def visit_With(self, node):
        node = self.generic_visit(node)

        # Build equivalent code with try catch finally.
        # PEP-0343 provides the equivalent code for us.

        statements = []

        # mgr = node.expr
        mgr_id = self.id_factory("mgr")
        s = mk_assign(mgr_id, node.context_expr)
        statements.append(s)

        # exit = type(msg).__exit__
        exit_id = self.id_factory("exit")
        s = mk_assign(exit_id,
                      mk_attr(mk_call('type', [mk_name(mgr_id)]), "__exit__"))
        statements.append(s)

        # value = type(msg).__enter__(mgr)
        value_id = self.id_factory("value")
        s = mk_assign(
            value_id,
            mk_call_expr(
                mk_attr(mk_call('type', [mk_name(mgr_id)]), "__enter__"),
                [mk_name(mgr_id)]))
        statements.append(s)

        # exc = True
        exc_id = self.id_factory("exc")
        s = mk_assign(exc_id, mk_name("True"))
        statements.append(s)

        # try:
        tryfinally_body = []
        tryfinally_finalbody = []
        s = ast.TryFinally(body=tryfinally_body,
                           finalbody=tryfinally_finalbody)
        statements.append(s)

        #     try:
        tryexcept_body = []
        tryexcept_except = []
        expt_handler = ast.ExceptHandler(type=None,
                                         name=None,
                                         body=tryexcept_except)
        s = ast.TryExcept(body=tryexcept_body,
                          handlers=[expt_handler],
                          orelse=[])
        tryfinally_body.append(s)

        #         node.optional_vars = value
        if node.optional_vars:
            s = ast.Assign(targets=[node.optional_vars],
                           value=mk_name(value_id))
            tryexcept_body.append(s)

        #         body
        tryexcept_body.extend(node.body)

        #     except:

        #         exc = False
        s = mk_assign(exc_id, mk_name("False"))
        tryexcept_except.append(s)

        #         sys.exc_info()
        sys_exc_info = mk_call_expr(mk_attr(mk_name('sys'), "exc_info"), [])
        #         exit(mgr, *sys.exc_info())
        exit_call = mk_call(exit_id, [mk_name(mgr_id)], vararg=sys_exc_info)
        #         not exit(mgr, *sys.exc_info())
        test = ast.UnaryOp(op=ast.Not(), operand=exit_call)

        #        if not exit(mgr, *sys.exc_info()):
        #            raise
        s = ast.If(test=test,
                   body=[ast.Raise(type=None, inst=None, tback=None)],
                   orelse=[])
        tryexcept_except.append(s)

        # finally:

        #     if exc:
        #       exit(mgr, None, None, None)
        exit_call = mk_call(exit_id, [
            mk_name(mgr_id),
            mk_name("None"),
            mk_name("None"),
            mk_name("None")
        ])
        s = ast.If(test=mk_name(exc_id),
                   body=[ast.Expr(value=exit_call)],
                   orelse=[])
        tryfinally_finalbody.append(s)

        return statements
Ejemplo n.º 52
0
    def _visit_loop(self, node, stop_iteration):
        
        body, body_interrupts, body_guranteed = self.process_body(node.body)
        orelse, orelse_interrupts, orelse_guranteed = self.process_body(node.orelse)
        
        # All interrupts of `orelse` propagate. Of `body` both `break` and `continue` are consumed
        # and only `return` goes on.
        for_interrupts = orelse_interrupts
        if "return" in body_interrupts:
            for_interrupts.add("return")
            
        if "break" not in body_interrupts and "return" not in body_interrupts:
            for_guranteed = orelse_guranteed
        else:
            for_guranteed = set()
        
        statements = []
        

        # Clear the 'continue' at the end of the body
        if "continue" in body_interrupts:
            # if flag == "continue":
            #    flag == None
            clearflag = mk_assign(self.flag_id, mk_str(self.NONE))
            if "continue" not in body_guranteed:
                comparison = ast.Compare(left=mk_name(self.flag_id), ops=[ast.Eq()], comparators=[mk_str(self.CONTINUE)])
                ifstmt = ast.If(test=comparison, body=[clearflag], orelse=[])
                body.append(ifstmt)
            else:
                body.append(clearflag)
                
        # init the flags for "break" for the case when there isn't a single iteration.
        # If we 'pass on' some interrupts then body_visit will take care of this.
        if "break" in body_interrupts and "return" not in for_interrupts:
            statements.append(mk_assign(self.flag_id, mk_str(self.NONE)))

        
        # Assemble modified loop.
        node.body = body
        node.orelse = []
        
        # make the loop stop on 'break' and 'return'
        if "break" in body_interrupts or "return" in body_interrupts:
            stop_iteration(node)
            
        # Add the loop to the result
        statements.append(node)

        # `orelse`
        if "break" in body_interrupts or "return" in body_interrupts:
            # the `orelse` section may or may not execute
            
            if "break" in body_interrupts:
                # if flag == "break":
                #    flag == None
                clearflag = mk_assign(self.flag_id, mk_str(self.NONE))
                comparison = ast.Compare(left=mk_name(self.flag_id), ops=[ast.Eq()], comparators=[mk_str(self.BREAK)])
                clear_break = [ast.If(test=comparison, body=[clearflag], orelse=[])]
            else:
                clear_break = []
                
            if not orelse:
                statements.extend(clear_break)
            else:
                # if flag == None
                #     ORELSSE
                # else:
                #     clear_break
                comparison = ast.Compare(left=mk_name(self.flag_id), ops=[ast.Eq()], comparators=[mk_str(self.NONE)])
                orelse_if = ast.If(test=comparison, body=orelse, orelse=clear_break)
                statements.append(orelse_if)
        else:
            # there is no `break` therefore `orelse` is always executed.
            statements.extend(orelse)

        return statements, for_interrupts, for_guranteed