예제 #1
0
    def test_optimize_code_obj(self):
        # Test optimize() method with a code object
        #
        # x = 3 + 5 => x = 8
        noopt = Bytecode([
            Instr("LOAD_CONST", 3),
            Instr("LOAD_CONST", 5),
            Instr("BINARY_ADD"),
            Instr("STORE_NAME", "x"),
            Instr("LOAD_CONST", None),
            Instr("RETURN_VALUE"),
        ])
        noopt = noopt.to_code()

        optimizer = peephole_opt.PeepholeOptimizer()
        optim = optimizer.optimize(noopt)

        code = Bytecode.from_code(optim)
        self.assertEqual(
            code,
            [
                Instr("LOAD_CONST", 8, lineno=1),
                Instr("STORE_NAME", "x", lineno=1),
                Instr("LOAD_CONST", None, lineno=1),
                Instr("RETURN_VALUE", lineno=1),
            ],
        )
예제 #2
0
파일: test_cfg.py 프로젝트: 0keita/configs
    def test_legalize(self):
        code = Bytecode()
        code.first_lineno = 3
        code.extend(
            [
                Instr("LOAD_CONST", 7),
                Instr("STORE_NAME", "x"),
                Instr("LOAD_CONST", 8, lineno=4),
                Instr("STORE_NAME", "y"),
                SetLineno(5),
                Instr("LOAD_CONST", 9, lineno=6),
                Instr("STORE_NAME", "z"),
            ]
        )

        blocks = ControlFlowGraph.from_bytecode(code)
        blocks.legalize()
        self.assertBlocksEqual(
            blocks,
            [
                Instr("LOAD_CONST", 7, lineno=3),
                Instr("STORE_NAME", "x", lineno=3),
                Instr("LOAD_CONST", 8, lineno=4),
                Instr("STORE_NAME", "y", lineno=4),
                Instr("LOAD_CONST", 9, lineno=5),
                Instr("STORE_NAME", "z", lineno=5),
            ],
        )
 def test_slice(self):
     code = Bytecode()
     code.first_lineno = 3
     code.extend([
         Instr("LOAD_CONST", 7),
         Instr("STORE_NAME", "x"),
         SetLineno(4),
         Instr("LOAD_CONST", 8),
         Instr("STORE_NAME", "y"),
         SetLineno(5),
         Instr("LOAD_CONST", 9),
         Instr("STORE_NAME", "z"),
     ])
     sliced_code = code[:]
     self.assertEqual(code, sliced_code)
     for name in (
             "argcount",
             "posonlyargcount",
             "kwonlyargcount",
             "first_lineno",
             "name",
             "filename",
             "docstring",
             "cellvars",
             "freevars",
             "argnames",
     ):
         self.assertEqual(getattr(code, name, None),
                          getattr(sliced_code, name, None))
예제 #4
0
    def test_extended_jump(self):
        NOP = bytes((opcode.opmap["NOP"], ))

        class BigInstr(ConcreteInstr):
            def __init__(self, size):
                super().__init__("NOP")
                self._size = size

            def copy(self):
                return self

            def assemble(self):
                return NOP * self._size

        # (invalid) code using jumps > 0xffff to test extended arg
        label = Label()
        nb_nop = 2**16
        code = Bytecode([
            Instr("JUMP_ABSOLUTE", label),
            BigInstr(nb_nop),
            label,
            Instr("LOAD_CONST", None),
            Instr("RETURN_VALUE"),
        ])

        code_obj = code.to_code()
        if WORDCODE:
            expected = b"\x90\x01\x90\x00q\x06" + NOP * nb_nop + b"d\x00S\x00"
        else:
            expected = b"\x90\x01\x00q\x06\x00" + NOP * nb_nop + b"d\x00\x00S"
        self.assertEqual(code_obj.co_code, expected)
예제 #5
0
    def test_general_constants(self):
        """Test if general object could be linked as constants.

        """
        class CustomObject:
            pass

        class UnHashableCustomObject:
            __hash__ = None

        obj1 = [1, 2, 3]
        obj2 = {1, 2, 3}
        obj3 = CustomObject()
        obj4 = UnHashableCustomObject()
        code = Bytecode([
            Instr("LOAD_CONST", obj1, lineno=1),
            Instr("LOAD_CONST", obj2, lineno=1),
            Instr("LOAD_CONST", obj3, lineno=1),
            Instr("LOAD_CONST", obj4, lineno=1),
            Instr("BUILD_TUPLE", 4, lineno=1),
            Instr("RETURN_VALUE", lineno=1),
        ])
        self.assertEqual(code.to_code().co_consts, (obj1, obj2, obj3, obj4))

        def f():
            return  # pragma: no cover

        f.__code__ = code.to_code()
        self.assertEqual(f(), (obj1, obj2, obj3, obj4))
예제 #6
0
    def test_label2(self):
        bytecode = Bytecode()
        label = Label()
        bytecode.extend([
            Instr("LOAD_NAME", "test", lineno=1),
            Instr("POP_JUMP_IF_FALSE", label),
            Instr("LOAD_CONST", 5, lineno=2),
            Instr("STORE_NAME", "x"),
            Instr("JUMP_FORWARD", label),
            Instr("LOAD_CONST", 7, lineno=4),
            Instr("STORE_NAME", "x"),
            label,
            Instr("LOAD_CONST", None),
            Instr("RETURN_VALUE"),
        ])

        concrete = bytecode.to_concrete_bytecode()
        expected = [
            ConcreteInstr("LOAD_NAME", 0, lineno=1),
            ConcreteInstr("POP_JUMP_IF_FALSE",
                          14 if WORDCODE else 21,
                          lineno=1),
            ConcreteInstr("LOAD_CONST", 0, lineno=2),
            ConcreteInstr("STORE_NAME", 1, lineno=2),
            ConcreteInstr("JUMP_FORWARD", 4 if WORDCODE else 6, lineno=2),
            ConcreteInstr("LOAD_CONST", 1, lineno=4),
            ConcreteInstr("STORE_NAME", 1, lineno=4),
            ConcreteInstr("LOAD_CONST", 2, lineno=4),
            ConcreteInstr("RETURN_VALUE", lineno=4),
        ]
        self.assertListEqual(list(concrete), expected)
        self.assertListEqual(concrete.consts, [5, 7, None])
        self.assertListEqual(concrete.names, ["test", "x"])
        self.assertListEqual(concrete.varnames, [])
예제 #7
0
파일: test_cfg.py 프로젝트: 0keita/configs
    def test_setlineno(self):
        # x = 7
        # y = 8
        # z = 9
        code = Bytecode()
        code.first_lineno = 3
        code.extend(
            [
                Instr("LOAD_CONST", 7),
                Instr("STORE_NAME", "x"),
                SetLineno(4),
                Instr("LOAD_CONST", 8),
                Instr("STORE_NAME", "y"),
                SetLineno(5),
                Instr("LOAD_CONST", 9),
                Instr("STORE_NAME", "z"),
            ]
        )

        blocks = ControlFlowGraph.from_bytecode(code)
        self.assertBlocksEqual(
            blocks,
            [
                Instr("LOAD_CONST", 7),
                Instr("STORE_NAME", "x"),
                SetLineno(4),
                Instr("LOAD_CONST", 8),
                Instr("STORE_NAME", "y"),
                SetLineno(5),
                Instr("LOAD_CONST", 9),
                Instr("STORE_NAME", "z"),
            ],
        )
예제 #8
0
    def test_combined_unary_bin_ops(self):
        # x = 1 + 3 + 7
        code = Bytecode([
            Instr("LOAD_CONST", 1),
            Instr("LOAD_CONST", 3),
            Instr("BINARY_ADD"),
            Instr("LOAD_CONST", 7),
            Instr("BINARY_ADD"),
            Instr("STORE_NAME", "x"),
        ])
        self.check(code, Instr("LOAD_CONST", 11), Instr("STORE_NAME", "x"))

        # x = ~(~(5))
        code = Bytecode([
            Instr("LOAD_CONST", 5),
            Instr("UNARY_INVERT"),
            Instr("UNARY_INVERT"),
            Instr("STORE_NAME", "x"),
        ])
        self.check(code, Instr("LOAD_CONST", 5), Instr("STORE_NAME", "x"))

        # "events = [(0, 'call'), (1, 'line'), (-(3), 'call')]"
        code = Bytecode([
            Instr("LOAD_CONST", 0),
            Instr("LOAD_CONST", "call"),
            Instr("BUILD_TUPLE", 2),
            Instr("LOAD_CONST", 1),
            Instr("LOAD_CONST", "line"),
            Instr("BUILD_TUPLE", 2),
            Instr("LOAD_CONST", 3),
            Instr("UNARY_NEGATIVE"),
            Instr("LOAD_CONST", "call"),
            Instr("BUILD_TUPLE", 2),
            Instr("BUILD_LIST", 3),
            Instr("STORE_NAME", "events"),
        ])
        self.check(
            code,
            Instr("LOAD_CONST", (0, "call")),
            Instr("LOAD_CONST", (1, "line")),
            Instr("LOAD_CONST", (-3, "call")),
            Instr("BUILD_LIST", 3),
            Instr("STORE_NAME", "events"),
        )

        # 'x = (1,) + (0,) * 8'
        code = Bytecode([
            Instr("LOAD_CONST", 1),
            Instr("BUILD_TUPLE", 1),
            Instr("LOAD_CONST", 0),
            Instr("BUILD_TUPLE", 1),
            Instr("LOAD_CONST", 8),
            Instr("BINARY_MULTIPLY"),
            Instr("BINARY_ADD"),
            Instr("STORE_NAME", "x"),
        ])
        zeros = (0, ) * 8
        result = (1, ) + zeros
        self.check(code, Instr("LOAD_CONST", result), Instr("STORE_NAME", "x"))
예제 #9
0
    def check(self, source, function=False):
        ref_code = get_code(source, function=function)

        code = ConcreteBytecode.from_code(ref_code).to_code()
        self.assertEqual(code, ref_code)

        code = Bytecode.from_code(ref_code).to_code()
        self.assertEqual(code, ref_code)

        bytecode = Bytecode.from_code(ref_code)
        blocks = ControlFlowGraph.from_bytecode(bytecode)
        code = blocks.to_bytecode().to_code()
        self.assertEqual(code, ref_code)
예제 #10
0
    def test_build_list_unpack_seq(self):
        for build_list in ("BUILD_TUPLE", "BUILD_LIST"):
            # x, = [a]
            code = Bytecode([
                Instr("LOAD_NAME", "a"),
                Instr(build_list, 1),
                Instr("UNPACK_SEQUENCE", 1),
                Instr("STORE_NAME", "x"),
            ])
            self.check(code, Instr("LOAD_NAME", "a"), Instr("STORE_NAME", "x"))

            # x, y = [a, b]
            code = Bytecode([
                Instr("LOAD_NAME", "a"),
                Instr("LOAD_NAME", "b"),
                Instr(build_list, 2),
                Instr("UNPACK_SEQUENCE", 2),
                Instr("STORE_NAME", "x"),
                Instr("STORE_NAME", "y"),
            ])
            self.check(
                code,
                Instr("LOAD_NAME", "a"),
                Instr("LOAD_NAME", "b"),
                Instr("ROT_TWO"),
                Instr("STORE_NAME", "x"),
                Instr("STORE_NAME", "y"),
            )

            # x, y, z = [a, b, c]
            code = Bytecode([
                Instr("LOAD_NAME", "a"),
                Instr("LOAD_NAME", "b"),
                Instr("LOAD_NAME", "c"),
                Instr(build_list, 3),
                Instr("UNPACK_SEQUENCE", 3),
                Instr("STORE_NAME", "x"),
                Instr("STORE_NAME", "y"),
                Instr("STORE_NAME", "z"),
            ])
            self.check(
                code,
                Instr("LOAD_NAME", "a"),
                Instr("LOAD_NAME", "b"),
                Instr("LOAD_NAME", "c"),
                Instr("ROT_THREE"),
                Instr("ROT_TWO"),
                Instr("STORE_NAME", "x"),
                Instr("STORE_NAME", "y"),
                Instr("STORE_NAME", "z"),
            )
예제 #11
0
    def test_flag_inference(self):

        # Check no loss of non-infered flags
        code = ControlFlowGraph()
        code.flags |= (CompilerFlags.NEWLOCALS
                       | CompilerFlags.VARARGS
                       | CompilerFlags.VARKEYWORDS
                       | CompilerFlags.NESTED
                       | CompilerFlags.FUTURE_GENERATOR_STOP)
        code.update_flags()
        for f in (
                CompilerFlags.NEWLOCALS,
                CompilerFlags.VARARGS,
                CompilerFlags.VARKEYWORDS,
                CompilerFlags.NESTED,
                CompilerFlags.NOFREE,
                CompilerFlags.OPTIMIZED,
                CompilerFlags.FUTURE_GENERATOR_STOP,
        ):
            self.assertTrue(bool(code.flags & f))

        # Infer optimized and nofree
        code = Bytecode()
        flags = infer_flags(code)
        self.assertTrue(bool(flags & CompilerFlags.OPTIMIZED))
        self.assertTrue(bool(flags & CompilerFlags.NOFREE))
        code.append(ConcreteInstr("STORE_NAME", 1))
        flags = infer_flags(code)
        self.assertFalse(bool(flags & CompilerFlags.OPTIMIZED))
        self.assertTrue(bool(flags & CompilerFlags.NOFREE))
        code.append(ConcreteInstr("STORE_DEREF", 2))
        code.update_flags()
        self.assertFalse(bool(code.flags & CompilerFlags.OPTIMIZED))
        self.assertFalse(bool(code.flags & CompilerFlags.NOFREE))
예제 #12
0
파일: test_cfg.py 프로젝트: 0keita/configs
    def test_stack_size_computation_nested_try_except_else_finally(self):
        def test(*args, **kwargs):
            try:
                v = args[1]
            except IndexError:
                try:
                    w = kwargs["value"]
                except KeyError:
                    return -1
                else:
                    return w
                finally:
                    print("second finally")
            else:
                return v
            finally:
                print("first finally")

        # A direct comparison of the stack depth fails because CPython
        # generate dead code that is used in stack computation.
        cpython_stacksize = test.__code__.co_stacksize
        test.__code__ = Bytecode.from_code(test.__code__).to_code()
        self.assertLessEqual(test.__code__.co_stacksize, cpython_stacksize)
        with contextlib.redirect_stdout(io.StringIO()) as stdout:
            self.assertEqual(test(1, 4), 4)
            self.assertEqual(stdout.getvalue(), "first finally\n")

        with contextlib.redirect_stdout(io.StringIO()) as stdout:
            self.assertEqual(test([], value=3), 3)
            self.assertEqual(stdout.getvalue(), "second finally\nfirst finally\n")

        with contextlib.redirect_stdout(io.StringIO()) as stdout:
            self.assertEqual(test([], name=None), -1)
            self.assertEqual(stdout.getvalue(), "second finally\nfirst finally\n")
예제 #13
0
    def test_not_jump_if_false(self):
        # Replace UNARY_NOT+POP_JUMP_IF_FALSE with POP_JUMP_IF_TRUE
        #
        # if not x:
        #     y = 9
        label = Label()
        code = Bytecode([
            Instr("LOAD_NAME", "x"),
            Instr("UNARY_NOT"),
            Instr("POP_JUMP_IF_FALSE", label),
            Instr("LOAD_CONST", 9),
            Instr("STORE_NAME", "y"),
            label,
        ])

        code = self.optimize_blocks(code)
        label = Label()
        self.check(
            code,
            Instr("LOAD_NAME", "x"),
            Instr("POP_JUMP_IF_TRUE", label),
            Instr("LOAD_CONST", 9),
            Instr("STORE_NAME", "y"),
            label,
        )
예제 #14
0
    def test_unconditional_jumps(self):
        # def func():
        #     if x:
        #         if y:
        #             func()
        label_instr7 = Label()
        code = Bytecode([
            Instr("LOAD_GLOBAL", "x", lineno=2),
            Instr("POP_JUMP_IF_FALSE", label_instr7, lineno=2),
            Instr("LOAD_GLOBAL", "y", lineno=3),
            Instr("POP_JUMP_IF_FALSE", label_instr7, lineno=3),
            Instr("LOAD_GLOBAL", "func", lineno=4),
            Instr("CALL_FUNCTION", 0, lineno=4),
            Instr("POP_TOP", lineno=4),
            label_instr7,
            Instr("LOAD_CONST", None, lineno=4),
            Instr("RETURN_VALUE", lineno=4),
        ])

        label_return = Label()
        self.check(
            code,
            Instr("LOAD_GLOBAL", "x", lineno=2),
            Instr("POP_JUMP_IF_FALSE", label_return, lineno=2),
            Instr("LOAD_GLOBAL", "y", lineno=3),
            Instr("POP_JUMP_IF_FALSE", label_return, lineno=3),
            Instr("LOAD_GLOBAL", "func", lineno=4),
            Instr("CALL_FUNCTION", 0, lineno=4),
            Instr("POP_TOP", lineno=4),
            label_return,
            Instr("LOAD_CONST", None, lineno=4),
            Instr("RETURN_VALUE", lineno=4),
        )
예제 #15
0
    def test_from_code_freevars(self):
        ns = {}
        exec(
            textwrap.dedent("""
            def create_func():
                x = 1
                def func():
                    return x
                return func

            func = create_func()
        """),
            ns,
            ns,
        )
        code = ns["func"].__code__

        bytecode = Bytecode.from_code(code)
        self.assertEqual(
            bytecode,
            [
                Instr("LOAD_DEREF", FreeVar("x"), lineno=5),
                Instr("RETURN_VALUE", lineno=5),
            ],
        )
예제 #16
0
    def test_jump_to_return(self):
        # def func(condition):
        #     return 'yes' if condition else 'no'
        label_instr4 = Label()
        label_instr6 = Label()
        code = Bytecode([
            Instr("LOAD_FAST", "condition"),
            Instr("POP_JUMP_IF_FALSE", label_instr4),
            Instr("LOAD_CONST", "yes"),
            Instr("JUMP_FORWARD", label_instr6),
            label_instr4,
            Instr("LOAD_CONST", "no"),
            label_instr6,
            Instr("RETURN_VALUE"),
        ])

        label = Label()
        self.check(
            code,
            Instr("LOAD_FAST", "condition"),
            Instr("POP_JUMP_IF_FALSE", label),
            Instr("LOAD_CONST", "yes"),
            Instr("RETURN_VALUE"),
            label,
            Instr("LOAD_CONST", "no"),
            Instr("RETURN_VALUE"),
        )
예제 #17
0
 def test_from_code(self):
     code = get_code("""
         if test:
             x = 1
         else:
             x = 2
     """)
     bytecode = Bytecode.from_code(code)
     label_else = Label()
     label_exit = Label()
     self.assertEqual(
         bytecode,
         [
             Instr("LOAD_NAME", "test", lineno=1),
             Instr("POP_JUMP_IF_FALSE", label_else, lineno=1),
             Instr("LOAD_CONST", 1, lineno=2),
             Instr("STORE_NAME", "x", lineno=2),
             Instr("JUMP_FORWARD", label_exit, lineno=2),
             label_else,
             Instr("LOAD_CONST", 2, lineno=4),
             Instr("STORE_NAME", "x", lineno=4),
             label_exit,
             Instr("LOAD_CONST", None, lineno=4),
             Instr("RETURN_VALUE", lineno=4),
         ],
     )
예제 #18
0
    def test_nop(self):
        code = Bytecode([
            Instr("LOAD_NAME", "x"),
            Instr("NOP"),
            Instr("STORE_NAME", "test")
        ])

        self.check(code, Instr("LOAD_NAME", "x"), Instr("STORE_NAME", "test"))
예제 #19
0
 def check_unary_op(op, value, result):
     code = Bytecode([
         Instr("LOAD_CONST", value),
         Instr(op),
         Instr("STORE_NAME", "x")
     ])
     self.check(code, Instr("LOAD_CONST", result),
                Instr("STORE_NAME", "x"))
예제 #20
0
    def test_legalize(self):
        code = Bytecode()
        code.first_lineno = 3
        code.extend([
            Instr("LOAD_CONST", 7),
            Instr("STORE_NAME", "x"),
            Instr("LOAD_CONST", 8, lineno=4),
            Instr("STORE_NAME", "y"),
            Label(),
            SetLineno(5),
            Instr("LOAD_CONST", 9, lineno=6),
            Instr("STORE_NAME", "z"),
        ])

        code.legalize()
        self.assertListEqual(
            code,
            [
                Instr("LOAD_CONST", 7, lineno=3),
                Instr("STORE_NAME", "x", lineno=3),
                Instr("LOAD_CONST", 8, lineno=4),
                Instr("STORE_NAME", "y", lineno=4),
                Label(),
                Instr("LOAD_CONST", 9, lineno=5),
                Instr("STORE_NAME", "z", lineno=5),
            ],
        )
예제 #21
0
    def optimize(self, code_obj):
        bytecode = Bytecode.from_code(code_obj)
        cfg = ControlFlowGraph.from_bytecode(bytecode)

        self.optimize_cfg(cfg)

        bytecode = cfg.to_bytecode()
        code = bytecode.to_code()
        return code
예제 #22
0
    def test_label(self):
        code = Bytecode()
        label = Label()
        code.extend([
            Instr("LOAD_CONST", "hello", lineno=1),
            Instr("JUMP_FORWARD", label, lineno=1),
            label,
            Instr("POP_TOP", lineno=1),
        ])

        code = code.to_concrete_bytecode()
        expected = [
            ConcreteInstr("LOAD_CONST", 0, lineno=1),
            ConcreteInstr("JUMP_FORWARD", 0, lineno=1),
            ConcreteInstr("POP_TOP", lineno=1),
        ]
        self.assertListEqual(list(code), expected)
        self.assertListEqual(code.consts, ["hello"])
예제 #23
0
 def check_bin_op(left, op, right, result):
     code = Bytecode([
         Instr("LOAD_CONST", left),
         Instr("LOAD_CONST", right),
         Instr(op),
         Instr("STORE_NAME", "x"),
     ])
     self.check(code, Instr("LOAD_CONST", result),
                Instr("STORE_NAME", "x"))
예제 #24
0
    def test_bin_op_dont_optimize(self):
        # 1 / 0
        code = Bytecode([
            Instr("LOAD_CONST", 1),
            Instr("LOAD_CONST", 0),
            Instr("BINARY_TRUE_DIVIDE"),
            Instr("POP_TOP"),
            Instr("LOAD_CONST", None),
            Instr("RETURN_VALUE"),
        ])
        self.check_dont_optimize(code)

        # 1 // 0
        code = Bytecode([
            Instr("LOAD_CONST", 1),
            Instr("LOAD_CONST", 0),
            Instr("BINARY_FLOOR_DIVIDE"),
            Instr("POP_TOP"),
            Instr("LOAD_CONST", None),
            Instr("RETURN_VALUE"),
        ])
        self.check_dont_optimize(code)

        # 1 % 0
        code = Bytecode([
            Instr("LOAD_CONST", 1),
            Instr("LOAD_CONST", 0),
            Instr("BINARY_MODULO"),
            Instr("POP_TOP"),
            Instr("LOAD_CONST", None),
            Instr("RETURN_VALUE"),
        ])
        self.check_dont_optimize(code)

        # 1 % 1j
        code = Bytecode([
            Instr("LOAD_CONST", 1),
            Instr("LOAD_CONST", 1j),
            Instr("BINARY_MODULO"),
            Instr("POP_TOP"),
            Instr("LOAD_CONST", None),
            Instr("RETURN_VALUE"),
        ])
        self.check_dont_optimize(code)
예제 #25
0
 def test_cellvars(self):
     code = Bytecode()
     code.cellvars = ["x"]
     code.freevars = ["y"]
     code.extend([
         Instr("LOAD_DEREF", CellVar("x"), lineno=1),
         Instr("LOAD_DEREF", FreeVar("y"), lineno=1),
     ])
     concrete = code.to_concrete_bytecode()
     self.assertEqual(concrete.cellvars, ["x"])
     self.assertEqual(concrete.freevars, ["y"])
     code.extend([
         ConcreteInstr("LOAD_DEREF", 0, lineno=1),
         ConcreteInstr("LOAD_DEREF", 1, lineno=1),
     ])
예제 #26
0
 def test_negative_size_build_const_map(self):
     code = Bytecode()
     code.first_lineno = 1
     code.extend(
         [Instr("LOAD_CONST", ("a", )),
          Instr("BUILD_CONST_KEY_MAP", 1)])
     with self.assertRaises(RuntimeError):
         code.compute_stacksize()
예제 #27
0
    def test_unconditional_jump_to_return(self):
        # def func():
        #     if test:
        #         if test2:
        #             x = 10
        #         else:
        #             x = 20
        #     else:
        #         x = 30

        label_instr11 = Label()
        label_instr14 = Label()
        label_instr7 = Label()
        code = Bytecode([
            Instr("LOAD_GLOBAL", "test", lineno=2),
            Instr("POP_JUMP_IF_FALSE", label_instr11, lineno=2),
            Instr("LOAD_GLOBAL", "test2", lineno=3),
            Instr("POP_JUMP_IF_FALSE", label_instr7, lineno=3),
            Instr("LOAD_CONST", 10, lineno=4),
            Instr("STORE_FAST", "x", lineno=4),
            Instr("JUMP_ABSOLUTE", label_instr14, lineno=4),
            label_instr7,
            Instr("LOAD_CONST", 20, lineno=6),
            Instr("STORE_FAST", "x", lineno=6),
            Instr("JUMP_FORWARD", label_instr14, lineno=6),
            label_instr11,
            Instr("LOAD_CONST", 30, lineno=8),
            Instr("STORE_FAST", "x", lineno=8),
            label_instr14,
            Instr("LOAD_CONST", None, lineno=8),
            Instr("RETURN_VALUE", lineno=8),
        ])

        label1 = Label()
        label3 = Label()
        label4 = Label()
        self.check(
            code,
            Instr("LOAD_GLOBAL", "test", lineno=2),
            Instr("POP_JUMP_IF_FALSE", label3, lineno=2),
            Instr("LOAD_GLOBAL", "test2", lineno=3),
            Instr("POP_JUMP_IF_FALSE", label1, lineno=3),
            Instr("LOAD_CONST", 10, lineno=4),
            Instr("STORE_FAST", "x", lineno=4),
            Instr("JUMP_ABSOLUTE", label4, lineno=4),
            label1,
            Instr("LOAD_CONST", 20, lineno=6),
            Instr("STORE_FAST", "x", lineno=6),
            Instr("JUMP_FORWARD", label4, lineno=6),
            label3,
            Instr("LOAD_CONST", 30, lineno=8),
            Instr("STORE_FAST", "x", lineno=8),
            label4,
            Instr("LOAD_CONST", None, lineno=8),
            Instr("RETURN_VALUE", lineno=8),
        )
예제 #28
0
    def test_dont_merge_constants(self):
        # test two constants which are equal but have a different type
        code = Bytecode()
        code.extend([
            Instr("LOAD_CONST", 5, lineno=1),
            Instr("LOAD_CONST", 5.0, lineno=1),
            Instr("LOAD_CONST", -0.0, lineno=1),
            Instr("LOAD_CONST", +0.0, lineno=1),
        ])

        code = code.to_concrete_bytecode()
        expected = [
            ConcreteInstr("LOAD_CONST", 0, lineno=1),
            ConcreteInstr("LOAD_CONST", 1, lineno=1),
            ConcreteInstr("LOAD_CONST", 2, lineno=1),
            ConcreteInstr("LOAD_CONST", 3, lineno=1),
        ]
        self.assertListEqual(list(code), expected)
        self.assertListEqual(code.consts, [5, 5.0, -0.0, +0.0])
예제 #29
0
    def test_jumps(self):
        # if test:
        #     x = 12
        # else:
        #     x = 37
        code = Bytecode()
        label_else = Label()
        label_return = Label()
        code.extend([
            Instr("LOAD_NAME", "test", lineno=1),
            Instr("POP_JUMP_IF_FALSE", label_else),
            Instr("LOAD_CONST", 12, lineno=2),
            Instr("STORE_NAME", "x"),
            Instr("JUMP_FORWARD", label_return),
            label_else,
            Instr("LOAD_CONST", 37, lineno=4),
            Instr("STORE_NAME", "x"),
            label_return,
            Instr("LOAD_CONST", None, lineno=4),
            Instr("RETURN_VALUE"),
        ])

        code = code.to_concrete_bytecode()
        expected = [
            ConcreteInstr("LOAD_NAME", 0, lineno=1),
            ConcreteInstr("POP_JUMP_IF_FALSE",
                          5 if OFFSET_AS_INSTRUCTION else 10,
                          lineno=1),
            ConcreteInstr("LOAD_CONST", 0, lineno=2),
            ConcreteInstr("STORE_NAME", 1, lineno=2),
            ConcreteInstr("JUMP_FORWARD",
                          2 if OFFSET_AS_INSTRUCTION else 4,
                          lineno=2),
            ConcreteInstr("LOAD_CONST", 1, lineno=4),
            ConcreteInstr("STORE_NAME", 1, lineno=4),
            ConcreteInstr("LOAD_CONST", 2, lineno=4),
            ConcreteInstr("RETURN_VALUE", lineno=4),
        ]
        self.assertListEqual(list(code), expected)
        self.assertListEqual(code.consts, [12, 37, None])
        self.assertListEqual(code.names, ["test", "x"])
        self.assertListEqual(code.varnames, [])
예제 #30
0
 def test_invalid_types(self):
     code = Bytecode()
     code.append(123)
     with self.assertRaises(ValueError):
         list(code)
     with self.assertRaises(ValueError):
         code.legalize()
     with self.assertRaises(ValueError):
         Bytecode([123])