Beispiel #1
0
    def get_for_args_stmts(self, iter_name, args_list):
        '''
        Returns 3 gast stmt nodes for argument.
        1. Initailize of iterate variable
        2. Condition for the loop
        3. Statement for changing of iterate variable during the loop
        NOTE(TODO): Python allows to access iteration variable after loop, such
           as "for i in range(10)" will create i = 9 after the loop. But using
           current conversion will make i = 10. We should find a way to change it
        '''
        len_range_args = len(args_list)
        assert len_range_args >= 1 and len_range_args <= 3, "range() function takes 1 to 3 arguments"
        if len_range_args == 1:
            init_stmt = get_constant_variable_node(iter_name, 0)
        else:
            init_stmt = gast.Assign(
                targets=[
                    gast.Name(
                        id=iter_name,
                        ctx=gast.Store(),
                        annotation=None,
                        type_comment=None)
                ],
                value=args_list[0])

        range_max_node = args_list[0] if len_range_args == 1 else args_list[1]
        step_node = args_list[2] if len_range_args == 3 else gast.Constant(
            value=1, kind=None)

        cond_stmt = gast.Compare(
            left=gast.BinOp(
                left=gast.Name(
                    id=iter_name,
                    ctx=gast.Load(),
                    annotation=None,
                    type_comment=None),
                op=gast.Add(),
                right=step_node),
            ops=[gast.LtE()],
            comparators=[range_max_node])

        change_stmt = gast.AugAssign(
            target=gast.Name(
                id=iter_name,
                ctx=gast.Store(),
                annotation=None,
                type_comment=None),
            op=gast.Add(),
            value=step_node)

        return init_stmt, cond_stmt, change_stmt
  def test_ast_to_object(self):
    node = gast.FunctionDef(
        name='f',
        args=gast.arguments(
            args=[gast.Name('a', gast.Param(), None)],
            vararg=None,
            kwonlyargs=[],
            kwarg=None,
            defaults=[],
            kw_defaults=[]),
        body=[
            gast.Return(
                gast.BinOp(
                    op=gast.Add(),
                    left=gast.Name('a', gast.Load(), None),
                    right=gast.Num(1)))
        ],
        decorator_list=[],
        returns=None)

    module, source, _ = compiler.ast_to_object(node)

    expected_source = """
      # coding=utf-8
      def f(a):
        return a + 1
    """
    self.assertEqual(
        textwrap.dedent(expected_source).strip(),
        source.strip())
    self.assertEqual(2, module.f(1))
    with open(module.__file__, 'r') as temp_output:
      self.assertEqual(
          textwrap.dedent(expected_source).strip(),
          temp_output.read().strip())
Beispiel #3
0
 def _build_enum_increase_node(self):
     return gast.AugAssign(target=gast.Name(id=self.enum_idx_name,
                                            ctx=gast.Store(),
                                            annotation=None,
                                            type_comment=None),
                           op=gast.Add(),
                           value=gast.Constant(value=1, kind=None))
Beispiel #4
0
    def test_replace_code_block(self):
        template = """
      def test_fn(a):
        block
        return a
    """

        class ShouldBeReplaced(object):
            pass

        node = templates.replace(
            template,
            block=[
                gast.Assign(
                    [
                        gast.Name('a',
                                  ctx=ShouldBeReplaced,
                                  annotation=None,
                                  type_comment=None)
                    ],
                    gast.BinOp(
                        gast.Name('a',
                                  ctx=ShouldBeReplaced,
                                  annotation=None,
                                  type_comment=None), gast.Add(),
                        gast.Constant(1, kind=None)),
                ),
            ] * 2)[0]
        result, _, _ = loader.load_ast(node)
        self.assertEqual(3, result.test_fn(1))
Beispiel #5
0
 def to_ast(self):
     assert self._finalized
     if self._argspec:
         result = self._argspec[0]
         for i in range(1, len(self._argspec)):
             result = gast.BinOp(result, gast.Add(), self._argspec[i])
         return result
     return gast.Tuple([], None)
Beispiel #6
0
 def _build_index_increase_node(self, step_node):
     return gast.AugAssign(target=gast.Name(
         id=self.iter_var_name
         if self.is_for_range_iter() else self.iter_idx_name,
         ctx=gast.Store(),
         annotation=None,
         type_comment=None),
                           op=gast.Add(),
                           value=step_node)
Beispiel #7
0
class StrJoinPattern(Pattern):
    # a + "..." + b => "...".join((a, b))
    pattern = ast.BinOp(left=ast.BinOp(left=Placeholder(0),
                                       op=ast.Add(),
                                       right=ast.Constant(
                                           Placeholder(1, str), None)),
                        op=ast.Add(),
                        right=Placeholder(2))

    @staticmethod
    def sub():
        return ast.Call(
            func=ast.Attribute(
                ast.Attribute(ast.Name('__builtin__', ast.Load(), None, None),
                              'str', ast.Load()), 'join', ast.Load()),
            args=[
                ast.Constant(Placeholder(1), None),
                ast.Tuple([Placeholder(0), Placeholder(2)], ast.Load())
            ],
            keywords=[])
Beispiel #8
0
    def get_for_args_stmts(self, iter_name, args_list):
        '''
        Returns 3 gast stmt nodes for argument.
        1. Initailize of iterate variable
        2. Condition for the loop
        3. Statement for changing of iterate variable during the loop
        '''
        len_range_args = len(args_list)
        assert len_range_args >= 1 and len_range_args <= 3, "range() function takes 1 to 3 arguments"
        if len_range_args == 1:
            init_stmt = get_constant_variable_node(iter_name, 0)
        else:
            init_stmt = gast.Assign(targets=[
                gast.Name(id=iter_name,
                          ctx=gast.Store(),
                          annotation=None,
                          type_comment=None)
            ],
                                    value=args_list[0])

        range_max_node = args_list[0] if len_range_args == 1 else args_list[1]
        step_node = args_list[2] if len_range_args == 3 else gast.Constant(
            value=1, kind=None)

        old_cond_stmt = gast.Compare(left=gast.BinOp(left=gast.Name(
            id=iter_name, ctx=gast.Load(), annotation=None, type_comment=None),
                                                     op=gast.Add(),
                                                     right=step_node),
                                     ops=[gast.LtE()],
                                     comparators=[range_max_node])
        cond_stmt = gast.BoolOp(op=gast.And(),
                                values=[old_cond_stmt, self.condition_node])

        change_stmt = gast.AugAssign(target=gast.Name(id=iter_name,
                                                      ctx=gast.Store(),
                                                      annotation=None,
                                                      type_comment=None),
                                     op=gast.Add(),
                                     value=step_node)

        return init_stmt, cond_stmt, change_stmt
Beispiel #9
0
    def visit_Subscript(self, node):
        """
        >>> import gast as ast
        >>> from pythran import passmanager, backend
        >>> pm = passmanager.PassManager("test")

        >>> node = ast.parse("def foo(a): a[1:][3]")
        >>> _, node = pm.apply(PartialConstantFolding, node)
        >>> _, node = pm.apply(ConstantFolding, node)
        >>> print(pm.dump(backend.Python, node))
        def foo(a):
            a[4]

        >>> node = ast.parse("def foo(a): a[::2][3]")
        >>> _, node = pm.apply(PartialConstantFolding, node)
        >>> _, node = pm.apply(ConstantFolding, node)
        >>> print(pm.dump(backend.Python, node))
        def foo(a):
            a[6]

        >>> node = ast.parse("def foo(a): a[-4:][5]")
        >>> _, node = pm.apply(PartialConstantFolding, node)
        >>> _, node = pm.apply(ConstantFolding, node)
        >>> print(pm.dump(backend.Python, node))
        def foo(a):
            a[1]
        """
        self.generic_visit(node)
        if not isinstance(node.value, ast.Subscript):
            return node
        if not isinstance(node.value.slice, ast.Slice):
            return node
        if not isinstance(node.slice, ast.Index):
            return node

        if not isnum(node.slice.value):
            return node

        slice_ = node.value.slice
        index = node.slice
        node = node.value

        node.slice = index
        lower = slice_.lower or ast.Constant(0, None)
        step = slice_.step or ast.Constant(1, None)
        node.slice.value = ast.BinOp(lower,
                                     ast.Add(),
                                     ast.BinOp(index.value,
                                               ast.Mult(),
                                               step))
        self.update = True
        return node
Beispiel #10
0
 def _build_cond_stmt(self, step_node, compare_node):
     return gast.Compare(
         left=gast.BinOp(
             left=gast.Name(
                 id=self.iter_var_name
                 if self.is_for_range_iter() else self.iter_idx_name,
                 ctx=gast.Load(),
                 annotation=None,
                 type_comment=None),
             op=gast.Add(),
             right=step_node),
         ops=[gast.LtE()],
         comparators=[compare_node])
Beispiel #11
0
    def test_code_block(self):
        def template(block):  # pylint:disable=unused-argument
            def test_fn(a):  # pylint:disable=unused-variable
                block  # pylint:disable=pointless-statement
                return a

        node = templates.replace(
            template,
            block=[
                gast.Assign([gast.Name('a', gast.Store(), None)],
                            gast.BinOp(gast.Name('a', gast.Load(), None),
                                       gast.Add(), gast.Num(1))),
            ] * 2)[0]
        result = compiler.ast_to_object(node)
        self.assertEquals(3, result.test_fn(1))
Beispiel #12
0
    def test_replace_code_block(self):
        template = """
      def test_fn(a):
        block
        return a
    """

        node = templates.replace(
            template,
            block=[
                gast.Assign([gast.Name('a', None, None)],
                            gast.BinOp(gast.Name('a', None, None), gast.Add(),
                                       gast.Num(1))),
            ] * 2)[0]
        result, _ = compiler.ast_to_object(node)
        self.assertEquals(3, result.test_fn(1))
  def test_load_ast(self):
    node = gast.FunctionDef(
        name='f',
        args=gast.arguments(
            args=[
                gast.Name(
                    'a', ctx=gast.Param(), annotation=None, type_comment=None)
            ],
            posonlyargs=[],
            vararg=None,
            kwonlyargs=[],
            kw_defaults=[],
            kwarg=None,
            defaults=[]),
        body=[
            gast.Return(
                gast.BinOp(
                    op=gast.Add(),
                    left=gast.Name(
                        'a',
                        ctx=gast.Load(),
                        annotation=None,
                        type_comment=None),
                    right=gast.Constant(1, kind=None)))
        ],
        decorator_list=[],
        returns=None,
        type_comment=None)

    module, source, _ = loader.load_ast(node)

    expected_source = """
      # coding=utf-8
      def f(a):
          return (a + 1)
    """
    self.assertEqual(
        textwrap.dedent(expected_source).strip(),
        source.strip())
    self.assertEqual(2, module.f(1))
    with open(module.__file__, 'r') as temp_output:
      self.assertEqual(
          textwrap.dedent(expected_source).strip(),
          temp_output.read().strip())
Beispiel #14
0
                      args=[
                          ast.BinOp(left=Placeholder(0),
                                    op=ast.Sub(),
                                    right=ast.Num(n=1)),
                          ast.Num(n=-1),
                          ast.Num(n=-1)
                      ],
                      keywords=[])),

    # X * X => X ** 2
    (ast.BinOp(left=Placeholder(0), op=ast.Mult(), right=Placeholder(0)),
     lambda: ast.BinOp(left=Placeholder(0), op=ast.Pow(), right=ast.Num(n=2))),

    # a + "..." + b => "...".join((a, b))
    (ast.BinOp(left=ast.BinOp(left=Placeholder(0),
                              op=ast.Add(),
                              right=ast.Str(Placeholder(1))),
               op=ast.Add(),
               right=Placeholder(2)),
     lambda: ast.Call(func=ast.Attribute(
         ast.Attribute(ast.Name('__builtin__', ast.Load(), None), 'str',
                       ast.Load()), 'join', ast.Load()),
                      args=[
                          ast.Str(Placeholder(1)),
                          ast.Tuple([Placeholder(0),
                                     Placeholder(2)], ast.Load())
                      ],
                      keywords=[])),
]

Beispiel #15
0
    def visit_BinOp(self, node):
        if not isinstance(node.op, ast.Mod):
            return self.generic_visit(node)

        # check that right is a name defined once outside of loop
        # TODO: handle expression instead of names
        if not isinstance(node.right, ast.Name):
            return self.generic_visit(node)

        right_def = self.single_def(node.right)
        if not right_def:
            return self.generic_visit(node)

        if self.range_values[node.right.id].low < 0:
            return self.generic_visit(node)

        # same for lhs
        if not isinstance(node.left, ast.Name):
            return self.generic_visit(node)

        head = self.single_def(node.left)
        if not head:
            return self.generic_visit(node)

        # check lhs is the actual index of a loop
        head = head['name']
        loop = self.ancestors[head][-1]

        if not isinstance(loop, ast.For):
            return self.generic_visit(node)

        if not isinstance(loop.iter, ast.Call):
            return self.generic_visit(node)

        # make sure rhs is defined out of the loop
        if loop in self.ancestors[right_def['name']]:
            return self.generic_visit(node)

        # gather range informations
        range_ = None
        for alias in self.aliases[loop.iter.func]:
            if alias is MODULES['__builtin__']['range']:
                range_ = alias
            elif alias is MODULES['__builtin__']['xrange']:
                range_ = alias
            else:
                break

        if range_ is None:
            return self.generic_visit(node)

        # everything is setup for the transformation!
        new_id = node.left.id + '_m'
        i = 0
        while new_id in self.identifiers:
            new_id = '{}_m{}'.format(node.left.id, i)
            i += 1

        rargs = range_.args.args
        lower = rargs[0] if len(rargs) > 1 else ast.Num(0)
        header = ast.Assign([ast.Name(new_id, ast.Store(), None)],
                            ast.BinOp(
                                ast.BinOp(deepcopy(lower), ast.Sub(),
                                          ast.Num(1)), ast.Mod(),
                                deepcopy(node.right)))
        incr = ast.BinOp(ast.Name(new_id, ast.Load(), None), ast.Add(),
                         ast.Num(1))
        step = ast.Assign([ast.Name(new_id, ast.Store(), None)],
                          ast.IfExp(
                              ast.Compare(incr, [ast.Eq()],
                                          [deepcopy(node.right)]), ast.Num(0),
                              deepcopy(incr)))

        self.loops_mod.setdefault(loop, []).append((header, step))
        self.update = True
        return ast.Name(new_id, ast.Load(), None)