mirror of
https://github.com/python/cpython.git
synced 2026-01-06 07:22:09 +00:00
gh-126835: Refine constant folding tests in test_peepholer.py::TestTranforms (#131826)
This commit is contained in:
parent
8bd88e2827
commit
674dbf3b3a
1 changed files with 231 additions and 298 deletions
|
|
@ -150,7 +150,7 @@ def test_pack_unpack(self):
|
|||
self.assertNotInBytecode(code, 'UNPACK_SEQUENCE')
|
||||
self.check_lnotab(code)
|
||||
|
||||
def test_folding_of_tuples_of_constants(self):
|
||||
def test_constant_folding_tuples_of_constants(self):
|
||||
for line, elem in (
|
||||
('a = 1,2,3', (1, 2, 3)),
|
||||
('("a","b","c")', ('a', 'b', 'c')),
|
||||
|
|
@ -191,7 +191,7 @@ def crater():
|
|||
],)
|
||||
self.check_lnotab(crater)
|
||||
|
||||
def test_folding_of_lists_of_constants(self):
|
||||
def test_constant_folding_lists_of_constants(self):
|
||||
for line, elem in (
|
||||
# in/not in constants with BUILD_LIST should be folded to a tuple:
|
||||
('a in [1,2,3]', (1, 2, 3)),
|
||||
|
|
@ -205,7 +205,7 @@ def test_folding_of_lists_of_constants(self):
|
|||
self.assertNotInBytecode(code, 'BUILD_LIST')
|
||||
self.check_lnotab(code)
|
||||
|
||||
def test_folding_of_sets_of_constants(self):
|
||||
def test_constant_folding_sets_of_constants(self):
|
||||
for line, elem in (
|
||||
# in/not in constants with BUILD_SET should be folded to a frozenset:
|
||||
('a in {1,2,3}', frozenset({1, 2, 3})),
|
||||
|
|
@ -235,56 +235,175 @@ def g(a):
|
|||
self.assertTrue(g(4))
|
||||
self.check_lnotab(g)
|
||||
|
||||
|
||||
def test_folding_of_binops_on_constants(self):
|
||||
for line, elem in (
|
||||
('a = 2+3+4', 9), # chained fold
|
||||
('"@"*4', '@@@@'), # check string ops
|
||||
('a="abc" + "def"', 'abcdef'), # check string ops
|
||||
('a = 3**4', 81), # binary power
|
||||
('a = 3*4', 12), # binary multiply
|
||||
('a = 13//4', 3), # binary floor divide
|
||||
('a = 14%4', 2), # binary modulo
|
||||
('a = 2+3', 5), # binary add
|
||||
('a = 13-4', 9), # binary subtract
|
||||
('a = (12,13)[1]', 13), # binary subscr
|
||||
('a = 13 << 2', 52), # binary lshift
|
||||
('a = 13 >> 2', 3), # binary rshift
|
||||
('a = 13 & 7', 5), # binary and
|
||||
('a = 13 ^ 7', 10), # binary xor
|
||||
('a = 13 | 7', 15), # binary or
|
||||
):
|
||||
with self.subTest(line=line):
|
||||
code = compile(line, '', 'single')
|
||||
if isinstance(elem, int):
|
||||
self.assertInBytecode(code, 'LOAD_SMALL_INT', elem)
|
||||
def test_constant_folding_small_int(self):
|
||||
tests = [
|
||||
('(0, )[0]', 0),
|
||||
('(1 + 2, )[0]', 3),
|
||||
('(2 + 2 * 2, )[0]', 6),
|
||||
('(1, (1 + 2 + 3, ))[1][0]', 6),
|
||||
('1 + 2', 3),
|
||||
('2 + 2 * 2 // 2 - 2', 2),
|
||||
('(255, )[0]', 255),
|
||||
('(256, )[0]', None),
|
||||
('(1000, )[0]', None),
|
||||
('(1 - 2, )[0]', None),
|
||||
('255 + 0', 255),
|
||||
('255 + 1', None),
|
||||
('-1', None),
|
||||
('--1', 1),
|
||||
('--255', 255),
|
||||
('--256', None),
|
||||
('~1', None),
|
||||
('~~1', 1),
|
||||
('~~255', 255),
|
||||
('~~256', None),
|
||||
('++255', 255),
|
||||
('++256', None),
|
||||
]
|
||||
for expr, oparg in tests:
|
||||
with self.subTest(expr=expr, oparg=oparg):
|
||||
code = compile(expr, '', 'single')
|
||||
if oparg is not None:
|
||||
self.assertInBytecode(code, 'LOAD_SMALL_INT', oparg)
|
||||
else:
|
||||
self.assertInBytecode(code, 'LOAD_CONST', elem)
|
||||
for instr in dis.get_instructions(code):
|
||||
self.assertFalse(instr.opname.startswith('BINARY_'))
|
||||
self.assertNotInBytecode(code, 'LOAD_SMALL_INT')
|
||||
self.check_lnotab(code)
|
||||
|
||||
# Verify that unfoldables are skipped
|
||||
code = compile('a=2+"b"', '', 'single')
|
||||
self.assertInBytecode(code, 'LOAD_SMALL_INT', 2)
|
||||
self.assertInBytecode(code, 'LOAD_CONST', 'b')
|
||||
self.check_lnotab(code)
|
||||
def test_constant_folding_unaryop(self):
|
||||
intrinsic_positive = 5
|
||||
tests = [
|
||||
('-0', 'UNARY_NEGATIVE', None, True, 'LOAD_SMALL_INT', 0),
|
||||
('-0.0', 'UNARY_NEGATIVE', None, True, 'LOAD_CONST', -0.0),
|
||||
('-(1.0-1.0)', 'UNARY_NEGATIVE', None, True, 'LOAD_CONST', -0.0),
|
||||
('-0.5', 'UNARY_NEGATIVE', None, True, 'LOAD_CONST', -0.5),
|
||||
('---1', 'UNARY_NEGATIVE', None, True, 'LOAD_CONST', -1),
|
||||
('---""', 'UNARY_NEGATIVE', None, False, None, None),
|
||||
('~~~1', 'UNARY_INVERT', None, True, 'LOAD_CONST', -2),
|
||||
('~~~""', 'UNARY_INVERT', None, False, None, None),
|
||||
('not not True', 'UNARY_NOT', None, True, 'LOAD_CONST', True),
|
||||
('not not x', 'UNARY_NOT', None, True, 'LOAD_NAME', 'x'), # this should be optimized regardless of constant or not
|
||||
('+++1', 'CALL_INTRINSIC_1', intrinsic_positive, True, 'LOAD_SMALL_INT', 1),
|
||||
('---x', 'UNARY_NEGATIVE', None, False, None, None),
|
||||
('~~~x', 'UNARY_INVERT', None, False, None, None),
|
||||
('+++x', 'CALL_INTRINSIC_1', intrinsic_positive, False, None, None),
|
||||
]
|
||||
|
||||
for (
|
||||
expr,
|
||||
original_opcode,
|
||||
original_argval,
|
||||
is_optimized,
|
||||
optimized_opcode,
|
||||
optimized_argval,
|
||||
) in tests:
|
||||
with self.subTest(expr=expr, is_optimized=is_optimized):
|
||||
code = compile(expr, "", "single")
|
||||
if is_optimized:
|
||||
self.assertNotInBytecode(code, original_opcode, argval=original_argval)
|
||||
self.assertInBytecode(code, optimized_opcode, argval=optimized_argval)
|
||||
else:
|
||||
self.assertInBytecode(code, original_opcode, argval=original_argval)
|
||||
self.check_lnotab(code)
|
||||
|
||||
# Check that -0.0 works after marshaling
|
||||
def negzero():
|
||||
return -(1.0-1.0)
|
||||
|
||||
for instr in dis.get_instructions(negzero):
|
||||
self.assertFalse(instr.opname.startswith('UNARY_'))
|
||||
self.check_lnotab(negzero)
|
||||
|
||||
def test_constant_folding_binop(self):
|
||||
tests = [
|
||||
('1 + 2', 'NB_ADD', True, 'LOAD_SMALL_INT', 3),
|
||||
('1 + 2 + 3', 'NB_ADD', True, 'LOAD_SMALL_INT', 6),
|
||||
('1 + ""', 'NB_ADD', False, None, None),
|
||||
('1 - 2', 'NB_SUBTRACT', True, 'LOAD_CONST', -1),
|
||||
('1 - 2 - 3', 'NB_SUBTRACT', True, 'LOAD_CONST', -4),
|
||||
('1 - ""', 'NB_SUBTRACT', False, None, None),
|
||||
('2 * 2', 'NB_MULTIPLY', True, 'LOAD_SMALL_INT', 4),
|
||||
('2 * 2 * 2', 'NB_MULTIPLY', True, 'LOAD_SMALL_INT', 8),
|
||||
('2 / 2', 'NB_TRUE_DIVIDE', True, 'LOAD_CONST', 1.0),
|
||||
('2 / 2 / 2', 'NB_TRUE_DIVIDE', True, 'LOAD_CONST', 0.5),
|
||||
('2 / ""', 'NB_TRUE_DIVIDE', False, None, None),
|
||||
('2 // 2', 'NB_FLOOR_DIVIDE', True, 'LOAD_SMALL_INT', 1),
|
||||
('2 // 2 // 2', 'NB_FLOOR_DIVIDE', True, 'LOAD_SMALL_INT', 0),
|
||||
('2 // ""', 'NB_FLOOR_DIVIDE', False, None, None),
|
||||
('2 % 2', 'NB_REMAINDER', True, 'LOAD_SMALL_INT', 0),
|
||||
('2 % 2 % 2', 'NB_REMAINDER', True, 'LOAD_SMALL_INT', 0),
|
||||
('2 % ()', 'NB_REMAINDER', False, None, None),
|
||||
('2 ** 2', 'NB_POWER', True, 'LOAD_SMALL_INT', 4),
|
||||
('2 ** 2 ** 2', 'NB_POWER', True, 'LOAD_SMALL_INT', 16),
|
||||
('2 ** ""', 'NB_POWER', False, None, None),
|
||||
('2 << 2', 'NB_LSHIFT', True, 'LOAD_SMALL_INT', 8),
|
||||
('2 << 2 << 2', 'NB_LSHIFT', True, 'LOAD_SMALL_INT', 32),
|
||||
('2 << ""', 'NB_LSHIFT', False, None, None),
|
||||
('2 >> 2', 'NB_RSHIFT', True, 'LOAD_SMALL_INT', 0),
|
||||
('2 >> 2 >> 2', 'NB_RSHIFT', True, 'LOAD_SMALL_INT', 0),
|
||||
('2 >> ""', 'NB_RSHIFT', False, None, None),
|
||||
('2 | 2', 'NB_OR', True, 'LOAD_SMALL_INT', 2),
|
||||
('2 | 2 | 2', 'NB_OR', True, 'LOAD_SMALL_INT', 2),
|
||||
('2 | ""', 'NB_OR', False, None, None),
|
||||
('2 & 2', 'NB_AND', True, 'LOAD_SMALL_INT', 2),
|
||||
('2 & 2 & 2', 'NB_AND', True, 'LOAD_SMALL_INT', 2),
|
||||
('2 & ""', 'NB_AND', False, None, None),
|
||||
('2 ^ 2', 'NB_XOR', True, 'LOAD_SMALL_INT', 0),
|
||||
('2 ^ 2 ^ 2', 'NB_XOR', True, 'LOAD_SMALL_INT', 2),
|
||||
('2 ^ ""', 'NB_XOR', False, None, None),
|
||||
('(1, )[0]', 'NB_SUBSCR', True, 'LOAD_SMALL_INT', 1),
|
||||
('(1, )[-1]', 'NB_SUBSCR', True, 'LOAD_SMALL_INT', 1),
|
||||
('(1 + 2, )[0]', 'NB_SUBSCR', True, 'LOAD_SMALL_INT', 3),
|
||||
('(1, (1, 2))[1][1]', 'NB_SUBSCR', True, 'LOAD_SMALL_INT', 2),
|
||||
('(1, 2)[2-1]', 'NB_SUBSCR', True, 'LOAD_SMALL_INT', 2),
|
||||
('(1, (1, 2))[1][2-1]', 'NB_SUBSCR', True, 'LOAD_SMALL_INT', 2),
|
||||
('(1, (1, 2))[1:6][0][2-1]', 'NB_SUBSCR', True, 'LOAD_SMALL_INT', 2),
|
||||
('"a"[0]', 'NB_SUBSCR', True, 'LOAD_CONST', 'a'),
|
||||
('("a" + "b")[1]', 'NB_SUBSCR', True, 'LOAD_CONST', 'b'),
|
||||
('("a" + "b", )[0][1]', 'NB_SUBSCR', True, 'LOAD_CONST', 'b'),
|
||||
('("a" * 10)[9]', 'NB_SUBSCR', True, 'LOAD_CONST', 'a'),
|
||||
('(1, )[1]', 'NB_SUBSCR', False, None, None),
|
||||
('(1, )[-2]', 'NB_SUBSCR', False, None, None),
|
||||
('"a"[1]', 'NB_SUBSCR', False, None, None),
|
||||
('"a"[-2]', 'NB_SUBSCR', False, None, None),
|
||||
('("a" + "b")[2]', 'NB_SUBSCR', False, None, None),
|
||||
('("a" + "b", )[0][2]', 'NB_SUBSCR', False, None, None),
|
||||
('("a" + "b", )[1][0]', 'NB_SUBSCR', False, None, None),
|
||||
('("a" * 10)[10]', 'NB_SUBSCR', False, None, None),
|
||||
('(1, (1, 2))[2:6][0][2-1]', 'NB_SUBSCR', False, None, None),
|
||||
]
|
||||
|
||||
for (
|
||||
expr,
|
||||
nb_op,
|
||||
is_optimized,
|
||||
optimized_opcode,
|
||||
optimized_argval
|
||||
) in tests:
|
||||
with self.subTest(expr=expr, is_optimized=is_optimized):
|
||||
code = compile(expr, '', 'single')
|
||||
nb_op_val = get_binop_argval(nb_op)
|
||||
if is_optimized:
|
||||
self.assertNotInBytecode(code, 'BINARY_OP', argval=nb_op_val)
|
||||
self.assertInBytecode(code, optimized_opcode, argval=optimized_argval)
|
||||
else:
|
||||
self.assertInBytecode(code, 'BINARY_OP', argval=nb_op_val)
|
||||
self.check_lnotab(code)
|
||||
|
||||
# Verify that large sequences do not result from folding
|
||||
code = compile('a="x"*10000', '', 'single')
|
||||
code = compile('"x"*10000', '', 'single')
|
||||
self.assertInBytecode(code, 'LOAD_CONST', 10000)
|
||||
self.assertNotIn("x"*10000, code.co_consts)
|
||||
self.check_lnotab(code)
|
||||
code = compile('a=1<<1000', '', 'single')
|
||||
code = compile('1<<1000', '', 'single')
|
||||
self.assertInBytecode(code, 'LOAD_CONST', 1000)
|
||||
self.assertNotIn(1<<1000, code.co_consts)
|
||||
self.check_lnotab(code)
|
||||
code = compile('a=2**1000', '', 'single')
|
||||
code = compile('2**1000', '', 'single')
|
||||
self.assertInBytecode(code, 'LOAD_CONST', 1000)
|
||||
self.assertNotIn(2**1000, code.co_consts)
|
||||
self.check_lnotab(code)
|
||||
|
||||
def test_binary_subscr_on_unicode(self):
|
||||
# Test binary subscript on unicode
|
||||
# valid code get optimized
|
||||
code = compile('"foo"[0]', '', 'single')
|
||||
self.assertInBytecode(code, 'LOAD_CONST', 'f')
|
||||
|
|
@ -307,43 +426,83 @@ def test_binary_subscr_on_unicode(self):
|
|||
self.assertInBytecode(code, 'BINARY_OP')
|
||||
self.check_lnotab(code)
|
||||
|
||||
def test_folding_of_unaryops_on_constants(self):
|
||||
for line, elem in (
|
||||
('-0.5', -0.5), # unary negative
|
||||
('-0.0', -0.0), # -0.0
|
||||
('-(1.0-1.0)', -0.0), # -0.0 after folding
|
||||
('-0', 0), # -0
|
||||
('~-2', 1), # unary invert
|
||||
('+1', 1), # unary positive
|
||||
):
|
||||
with self.subTest(line=line):
|
||||
code = compile(line, '', 'single')
|
||||
if isinstance(elem, int):
|
||||
self.assertInBytecode(code, 'LOAD_SMALL_INT', elem)
|
||||
else:
|
||||
self.assertInBytecode(code, 'LOAD_CONST', elem)
|
||||
for instr in dis.get_instructions(code):
|
||||
self.assertFalse(instr.opname.startswith('UNARY_'))
|
||||
self.check_lnotab(code)
|
||||
|
||||
# Check that -0.0 works after marshaling
|
||||
def negzero():
|
||||
return -(1.0-1.0)
|
||||
def test_constant_folding_remove_nop_location(self):
|
||||
sources = [
|
||||
"""
|
||||
(-
|
||||
-
|
||||
-
|
||||
1)
|
||||
""",
|
||||
|
||||
for instr in dis.get_instructions(negzero):
|
||||
self.assertFalse(instr.opname.startswith('UNARY_'))
|
||||
self.check_lnotab(negzero)
|
||||
"""
|
||||
(1
|
||||
+
|
||||
2
|
||||
+
|
||||
3)
|
||||
""",
|
||||
|
||||
# Verify that unfoldables are skipped
|
||||
for line, elem, opname in (
|
||||
('-"abc"', 'abc', 'UNARY_NEGATIVE'),
|
||||
('~"abc"', 'abc', 'UNARY_INVERT'),
|
||||
):
|
||||
with self.subTest(line=line):
|
||||
code = compile(line, '', 'single')
|
||||
self.assertInBytecode(code, 'LOAD_CONST', elem)
|
||||
self.assertInBytecode(code, opname)
|
||||
self.check_lnotab(code)
|
||||
"""
|
||||
(1,
|
||||
2,
|
||||
3)[0]
|
||||
""",
|
||||
|
||||
"""
|
||||
[1,
|
||||
2,
|
||||
3]
|
||||
""",
|
||||
|
||||
"""
|
||||
{1,
|
||||
2,
|
||||
3}
|
||||
""",
|
||||
|
||||
"""
|
||||
1 in [
|
||||
1,
|
||||
2,
|
||||
3
|
||||
]
|
||||
""",
|
||||
|
||||
"""
|
||||
1 in {
|
||||
1,
|
||||
2,
|
||||
3
|
||||
}
|
||||
""",
|
||||
|
||||
"""
|
||||
for _ in [1,
|
||||
2,
|
||||
3]:
|
||||
pass
|
||||
""",
|
||||
|
||||
"""
|
||||
for _ in [1,
|
||||
2,
|
||||
x]:
|
||||
pass
|
||||
""",
|
||||
|
||||
"""
|
||||
for _ in {1,
|
||||
2,
|
||||
3}:
|
||||
pass
|
||||
"""
|
||||
]
|
||||
|
||||
for source in sources:
|
||||
code = compile(textwrap.dedent(source), '', 'single')
|
||||
self.assertNotInBytecode(code, 'NOP')
|
||||
|
||||
def test_elim_extra_return(self):
|
||||
# RETURN LOAD_CONST None RETURN --> RETURN
|
||||
|
|
@ -459,232 +618,6 @@ def g()->1+1:
|
|||
self.assertNotInBytecode(f, 'BINARY_OP')
|
||||
self.check_lnotab(f)
|
||||
|
||||
def test_constant_folding(self):
|
||||
# Issue #11244: aggressive constant folding.
|
||||
exprs = [
|
||||
'3 * -5',
|
||||
'-3 * 5',
|
||||
'2 * (3 * 4)',
|
||||
'(2 * 3) * 4',
|
||||
'(-1, 2, 3)',
|
||||
'(1, -2, 3)',
|
||||
'(1, 2, -3)',
|
||||
'(1, 2, -3) * 6',
|
||||
'lambda x: x in {(3 * -5) + (-1 - 6), (1, -2, 3) * 2, None}',
|
||||
]
|
||||
for e in exprs:
|
||||
with self.subTest(e=e):
|
||||
code = compile(e, '', 'single')
|
||||
for instr in dis.get_instructions(code):
|
||||
self.assertFalse(instr.opname.startswith('UNARY_'))
|
||||
self.assertFalse(instr.opname.startswith('BINARY_'))
|
||||
self.assertFalse(instr.opname.startswith('BUILD_'))
|
||||
self.check_lnotab(code)
|
||||
|
||||
def test_constant_folding_small_int(self):
|
||||
tests = [
|
||||
('(0, )[0]', 0),
|
||||
('(1 + 2, )[0]', 3),
|
||||
('(2 + 2 * 2, )[0]', 6),
|
||||
('(1, (1 + 2 + 3, ))[1][0]', 6),
|
||||
('1 + 2', 3),
|
||||
('2 + 2 * 2 // 2 - 2', 2),
|
||||
('(255, )[0]', 255),
|
||||
('(256, )[0]', None),
|
||||
('(1000, )[0]', None),
|
||||
('(1 - 2, )[0]', None),
|
||||
('255 + 0', 255),
|
||||
('255 + 1', None),
|
||||
('-1', None),
|
||||
('--1', 1),
|
||||
('--255', 255),
|
||||
('--256', None),
|
||||
('~1', None),
|
||||
('~~1', 1),
|
||||
('~~255', 255),
|
||||
('~~256', None),
|
||||
('++255', 255),
|
||||
('++256', None),
|
||||
]
|
||||
for expr, oparg in tests:
|
||||
with self.subTest(expr=expr, oparg=oparg):
|
||||
code = compile(expr, '', 'single')
|
||||
if oparg is not None:
|
||||
self.assertInBytecode(code, 'LOAD_SMALL_INT', oparg)
|
||||
else:
|
||||
self.assertNotInBytecode(code, 'LOAD_SMALL_INT')
|
||||
self.check_lnotab(code)
|
||||
|
||||
def test_folding_unaryop(self):
|
||||
intrinsic_positive = 5
|
||||
tests = [
|
||||
('---1', 'UNARY_NEGATIVE', None, True),
|
||||
('---""', 'UNARY_NEGATIVE', None, False),
|
||||
('~~~1', 'UNARY_INVERT', None, True),
|
||||
('~~~""', 'UNARY_INVERT', None, False),
|
||||
('not not True', 'UNARY_NOT', None, True),
|
||||
('not not x', 'UNARY_NOT', None, True), # this should be optimized regardless of constant or not
|
||||
('+++1', 'CALL_INTRINSIC_1', intrinsic_positive, True),
|
||||
('---x', 'UNARY_NEGATIVE', None, False),
|
||||
('~~~x', 'UNARY_INVERT', None, False),
|
||||
('+++x', 'CALL_INTRINSIC_1', intrinsic_positive, False),
|
||||
]
|
||||
|
||||
for expr, opcode, oparg, optimized in tests:
|
||||
with self.subTest(expr=expr, optimized=optimized):
|
||||
code = compile(expr, '', 'single')
|
||||
if optimized:
|
||||
self.assertNotInBytecode(code, opcode, argval=oparg)
|
||||
else:
|
||||
self.assertInBytecode(code, opcode, argval=oparg)
|
||||
self.check_lnotab(code)
|
||||
|
||||
def test_folding_binop(self):
|
||||
tests = [
|
||||
('1 + 2', False, 'NB_ADD'),
|
||||
('1 + 2 + 3', False, 'NB_ADD'),
|
||||
('1 + ""', True, 'NB_ADD'),
|
||||
('1 - 2', False, 'NB_SUBTRACT'),
|
||||
('1 - 2 - 3', False, 'NB_SUBTRACT'),
|
||||
('1 - ""', True, 'NB_SUBTRACT'),
|
||||
('2 * 2', False, 'NB_MULTIPLY'),
|
||||
('2 * 2 * 2', False, 'NB_MULTIPLY'),
|
||||
('2 / 2', False, 'NB_TRUE_DIVIDE'),
|
||||
('2 / 2 / 2', False, 'NB_TRUE_DIVIDE'),
|
||||
('2 / ""', True, 'NB_TRUE_DIVIDE'),
|
||||
('2 // 2', False, 'NB_FLOOR_DIVIDE'),
|
||||
('2 // 2 // 2', False, 'NB_FLOOR_DIVIDE'),
|
||||
('2 // ""', True, 'NB_FLOOR_DIVIDE'),
|
||||
('2 % 2', False, 'NB_REMAINDER'),
|
||||
('2 % 2 % 2', False, 'NB_REMAINDER'),
|
||||
('2 % ()', True, 'NB_REMAINDER'),
|
||||
('2 ** 2', False, 'NB_POWER'),
|
||||
('2 ** 2 ** 2', False, 'NB_POWER'),
|
||||
('2 ** ""', True, 'NB_POWER'),
|
||||
('2 << 2', False, 'NB_LSHIFT'),
|
||||
('2 << 2 << 2', False, 'NB_LSHIFT'),
|
||||
('2 << ""', True, 'NB_LSHIFT'),
|
||||
('2 >> 2', False, 'NB_RSHIFT'),
|
||||
('2 >> 2 >> 2', False, 'NB_RSHIFT'),
|
||||
('2 >> ""', True, 'NB_RSHIFT'),
|
||||
('2 | 2', False, 'NB_OR'),
|
||||
('2 | 2 | 2', False, 'NB_OR'),
|
||||
('2 | ""', True, 'NB_OR'),
|
||||
('2 & 2', False, 'NB_AND'),
|
||||
('2 & 2 & 2', False, 'NB_AND'),
|
||||
('2 & ""', True, 'NB_AND'),
|
||||
('2 ^ 2', False, 'NB_XOR'),
|
||||
('2 ^ 2 ^ 2', False, 'NB_XOR'),
|
||||
('2 ^ ""', True, 'NB_XOR'),
|
||||
('(1, )[0]', False, 'NB_SUBSCR'),
|
||||
('(1, )[-1]', False, 'NB_SUBSCR'),
|
||||
('(1 + 2, )[0]', False, 'NB_SUBSCR'),
|
||||
('(1, (1, 2))[1][1]', False, 'NB_SUBSCR'),
|
||||
('(1, 2)[2-1]', False, 'NB_SUBSCR'),
|
||||
('(1, (1, 2))[1][2-1]', False, 'NB_SUBSCR'),
|
||||
('(1, (1, 2))[1:6][0][2-1]', False, 'NB_SUBSCR'),
|
||||
('"a"[0]', False, 'NB_SUBSCR'),
|
||||
('("a" + "b")[1]', False, 'NB_SUBSCR'),
|
||||
('("a" + "b", )[0][1]', False, 'NB_SUBSCR'),
|
||||
('("a" * 10)[9]', False, 'NB_SUBSCR'),
|
||||
('(1, )[1]', True, 'NB_SUBSCR'),
|
||||
('(1, )[-2]', True, 'NB_SUBSCR'),
|
||||
('"a"[1]', True, 'NB_SUBSCR'),
|
||||
('"a"[-2]', True, 'NB_SUBSCR'),
|
||||
('("a" + "b")[2]', True, 'NB_SUBSCR'),
|
||||
('("a" + "b", )[0][2]', True, 'NB_SUBSCR'),
|
||||
('("a" + "b", )[1][0]', True, 'NB_SUBSCR'),
|
||||
('("a" * 10)[10]', True, 'NB_SUBSCR'),
|
||||
('(1, (1, 2))[2:6][0][2-1]', True, 'NB_SUBSCR'),
|
||||
|
||||
]
|
||||
for expr, has_error, nb_op in tests:
|
||||
with self.subTest(expr=expr, has_error=has_error):
|
||||
code = compile(expr, '', 'single')
|
||||
nb_op_val = get_binop_argval(nb_op)
|
||||
if not has_error:
|
||||
self.assertNotInBytecode(code, 'BINARY_OP', argval=nb_op_val)
|
||||
else:
|
||||
self.assertInBytecode(code, 'BINARY_OP', argval=nb_op_val)
|
||||
self.check_lnotab(code)
|
||||
|
||||
def test_constant_folding_remove_nop_location(self):
|
||||
sources = [
|
||||
"""
|
||||
(-
|
||||
-
|
||||
-
|
||||
1)
|
||||
""",
|
||||
|
||||
"""
|
||||
(1
|
||||
+
|
||||
2
|
||||
+
|
||||
3)
|
||||
""",
|
||||
|
||||
"""
|
||||
(1,
|
||||
2,
|
||||
3)[0]
|
||||
""",
|
||||
|
||||
"""
|
||||
[1,
|
||||
2,
|
||||
3]
|
||||
""",
|
||||
|
||||
"""
|
||||
{1,
|
||||
2,
|
||||
3}
|
||||
""",
|
||||
|
||||
"""
|
||||
1 in [
|
||||
1,
|
||||
2,
|
||||
3
|
||||
]
|
||||
""",
|
||||
|
||||
"""
|
||||
1 in {
|
||||
1,
|
||||
2,
|
||||
3
|
||||
}
|
||||
""",
|
||||
|
||||
"""
|
||||
for _ in [1,
|
||||
2,
|
||||
3]:
|
||||
pass
|
||||
""",
|
||||
|
||||
"""
|
||||
for _ in [1,
|
||||
2,
|
||||
x]:
|
||||
pass
|
||||
""",
|
||||
|
||||
"""
|
||||
for _ in {1,
|
||||
2,
|
||||
3}:
|
||||
pass
|
||||
"""
|
||||
]
|
||||
|
||||
for source in sources:
|
||||
code = compile(textwrap.dedent(source), '', 'single')
|
||||
self.assertNotInBytecode(code, 'NOP')
|
||||
|
||||
def test_in_literal_list(self):
|
||||
def containtest():
|
||||
return x in [a, b]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue