17db96d56Sopenharmony_ciimport dis 27db96d56Sopenharmony_cifrom itertools import combinations, product 37db96d56Sopenharmony_ciimport textwrap 47db96d56Sopenharmony_ciimport unittest 57db96d56Sopenharmony_ci 67db96d56Sopenharmony_cifrom test.support.bytecode_helper import BytecodeTestCase 77db96d56Sopenharmony_ci 87db96d56Sopenharmony_ci 97db96d56Sopenharmony_cidef compile_pattern_with_fast_locals(pattern): 107db96d56Sopenharmony_ci source = textwrap.dedent( 117db96d56Sopenharmony_ci f""" 127db96d56Sopenharmony_ci def f(x): 137db96d56Sopenharmony_ci match x: 147db96d56Sopenharmony_ci case {pattern}: 157db96d56Sopenharmony_ci pass 167db96d56Sopenharmony_ci """ 177db96d56Sopenharmony_ci ) 187db96d56Sopenharmony_ci namespace = {} 197db96d56Sopenharmony_ci exec(source, namespace) 207db96d56Sopenharmony_ci return namespace["f"].__code__ 217db96d56Sopenharmony_ci 227db96d56Sopenharmony_ci 237db96d56Sopenharmony_cidef count_instr_recursively(f, opname): 247db96d56Sopenharmony_ci count = 0 257db96d56Sopenharmony_ci for instr in dis.get_instructions(f): 267db96d56Sopenharmony_ci if instr.opname == opname: 277db96d56Sopenharmony_ci count += 1 287db96d56Sopenharmony_ci if hasattr(f, '__code__'): 297db96d56Sopenharmony_ci f = f.__code__ 307db96d56Sopenharmony_ci for c in f.co_consts: 317db96d56Sopenharmony_ci if hasattr(c, 'co_code'): 327db96d56Sopenharmony_ci count += count_instr_recursively(c, opname) 337db96d56Sopenharmony_ci return count 347db96d56Sopenharmony_ci 357db96d56Sopenharmony_ci 367db96d56Sopenharmony_ciclass TestTranforms(BytecodeTestCase): 377db96d56Sopenharmony_ci 387db96d56Sopenharmony_ci def check_jump_targets(self, code): 397db96d56Sopenharmony_ci instructions = list(dis.get_instructions(code)) 407db96d56Sopenharmony_ci targets = {instr.offset: instr for instr in instructions} 417db96d56Sopenharmony_ci for instr in instructions: 427db96d56Sopenharmony_ci if 'JUMP_' not in instr.opname: 437db96d56Sopenharmony_ci continue 447db96d56Sopenharmony_ci tgt = targets[instr.argval] 457db96d56Sopenharmony_ci # jump to unconditional jump 467db96d56Sopenharmony_ci if tgt.opname in ('JUMP_ABSOLUTE', 'JUMP_FORWARD'): 477db96d56Sopenharmony_ci self.fail(f'{instr.opname} at {instr.offset} ' 487db96d56Sopenharmony_ci f'jumps to {tgt.opname} at {tgt.offset}') 497db96d56Sopenharmony_ci # unconditional jump to RETURN_VALUE 507db96d56Sopenharmony_ci if (instr.opname in ('JUMP_ABSOLUTE', 'JUMP_FORWARD') and 517db96d56Sopenharmony_ci tgt.opname == 'RETURN_VALUE'): 527db96d56Sopenharmony_ci self.fail(f'{instr.opname} at {instr.offset} ' 537db96d56Sopenharmony_ci f'jumps to {tgt.opname} at {tgt.offset}') 547db96d56Sopenharmony_ci # JUMP_IF_*_OR_POP jump to conditional jump 557db96d56Sopenharmony_ci if '_OR_POP' in instr.opname and 'JUMP_IF_' in tgt.opname: 567db96d56Sopenharmony_ci self.fail(f'{instr.opname} at {instr.offset} ' 577db96d56Sopenharmony_ci f'jumps to {tgt.opname} at {tgt.offset}') 587db96d56Sopenharmony_ci 597db96d56Sopenharmony_ci def check_lnotab(self, code): 607db96d56Sopenharmony_ci "Check that the lnotab byte offsets are sensible." 617db96d56Sopenharmony_ci code = dis._get_code_object(code) 627db96d56Sopenharmony_ci lnotab = list(dis.findlinestarts(code)) 637db96d56Sopenharmony_ci # Don't bother checking if the line info is sensible, because 647db96d56Sopenharmony_ci # most of the line info we can get at comes from lnotab. 657db96d56Sopenharmony_ci min_bytecode = min(t[0] for t in lnotab) 667db96d56Sopenharmony_ci max_bytecode = max(t[0] for t in lnotab) 677db96d56Sopenharmony_ci self.assertGreaterEqual(min_bytecode, 0) 687db96d56Sopenharmony_ci self.assertLess(max_bytecode, len(code.co_code)) 697db96d56Sopenharmony_ci # This could conceivably test more (and probably should, as there 707db96d56Sopenharmony_ci # aren't very many tests of lnotab), if peepholer wasn't scheduled 717db96d56Sopenharmony_ci # to be replaced anyway. 727db96d56Sopenharmony_ci 737db96d56Sopenharmony_ci def test_unot(self): 747db96d56Sopenharmony_ci # UNARY_NOT POP_JUMP_IF_FALSE --> POP_JUMP_IF_TRUE' 757db96d56Sopenharmony_ci def unot(x): 767db96d56Sopenharmony_ci if not x == 2: 777db96d56Sopenharmony_ci del x 787db96d56Sopenharmony_ci self.assertNotInBytecode(unot, 'UNARY_NOT') 797db96d56Sopenharmony_ci self.assertNotInBytecode(unot, 'POP_JUMP_FORWARD_IF_FALSE') 807db96d56Sopenharmony_ci self.assertNotInBytecode(unot, 'POP_JUMP_BACKWARD_IF_FALSE') 817db96d56Sopenharmony_ci self.assertInBytecode(unot, 'POP_JUMP_FORWARD_IF_TRUE') 827db96d56Sopenharmony_ci self.check_lnotab(unot) 837db96d56Sopenharmony_ci 847db96d56Sopenharmony_ci def test_elim_inversion_of_is_or_in(self): 857db96d56Sopenharmony_ci for line, cmp_op, invert in ( 867db96d56Sopenharmony_ci ('not a is b', 'IS_OP', 1,), 877db96d56Sopenharmony_ci ('not a is not b', 'IS_OP', 0,), 887db96d56Sopenharmony_ci ('not a in b', 'CONTAINS_OP', 1,), 897db96d56Sopenharmony_ci ('not a not in b', 'CONTAINS_OP', 0,), 907db96d56Sopenharmony_ci ): 917db96d56Sopenharmony_ci with self.subTest(line=line): 927db96d56Sopenharmony_ci code = compile(line, '', 'single') 937db96d56Sopenharmony_ci self.assertInBytecode(code, cmp_op, invert) 947db96d56Sopenharmony_ci self.check_lnotab(code) 957db96d56Sopenharmony_ci 967db96d56Sopenharmony_ci def test_global_as_constant(self): 977db96d56Sopenharmony_ci # LOAD_GLOBAL None/True/False --> LOAD_CONST None/True/False 987db96d56Sopenharmony_ci def f(): 997db96d56Sopenharmony_ci x = None 1007db96d56Sopenharmony_ci x = None 1017db96d56Sopenharmony_ci return x 1027db96d56Sopenharmony_ci def g(): 1037db96d56Sopenharmony_ci x = True 1047db96d56Sopenharmony_ci return x 1057db96d56Sopenharmony_ci def h(): 1067db96d56Sopenharmony_ci x = False 1077db96d56Sopenharmony_ci return x 1087db96d56Sopenharmony_ci 1097db96d56Sopenharmony_ci for func, elem in ((f, None), (g, True), (h, False)): 1107db96d56Sopenharmony_ci with self.subTest(func=func): 1117db96d56Sopenharmony_ci self.assertNotInBytecode(func, 'LOAD_GLOBAL') 1127db96d56Sopenharmony_ci self.assertInBytecode(func, 'LOAD_CONST', elem) 1137db96d56Sopenharmony_ci self.check_lnotab(func) 1147db96d56Sopenharmony_ci 1157db96d56Sopenharmony_ci def f(): 1167db96d56Sopenharmony_ci 'Adding a docstring made this test fail in Py2.5.0' 1177db96d56Sopenharmony_ci return None 1187db96d56Sopenharmony_ci 1197db96d56Sopenharmony_ci self.assertNotInBytecode(f, 'LOAD_GLOBAL') 1207db96d56Sopenharmony_ci self.assertInBytecode(f, 'LOAD_CONST', None) 1217db96d56Sopenharmony_ci self.check_lnotab(f) 1227db96d56Sopenharmony_ci 1237db96d56Sopenharmony_ci def test_while_one(self): 1247db96d56Sopenharmony_ci # Skip over: LOAD_CONST trueconst POP_JUMP_IF_FALSE xx 1257db96d56Sopenharmony_ci def f(): 1267db96d56Sopenharmony_ci while 1: 1277db96d56Sopenharmony_ci pass 1287db96d56Sopenharmony_ci return list 1297db96d56Sopenharmony_ci for elem in ('LOAD_CONST', 'POP_JUMP_IF_FALSE'): 1307db96d56Sopenharmony_ci self.assertNotInBytecode(f, elem) 1317db96d56Sopenharmony_ci for elem in ('JUMP_BACKWARD',): 1327db96d56Sopenharmony_ci self.assertInBytecode(f, elem) 1337db96d56Sopenharmony_ci self.check_lnotab(f) 1347db96d56Sopenharmony_ci 1357db96d56Sopenharmony_ci def test_pack_unpack(self): 1367db96d56Sopenharmony_ci for line, elem in ( 1377db96d56Sopenharmony_ci ('a, = a,', 'LOAD_CONST',), 1387db96d56Sopenharmony_ci ('a, b = a, b', 'SWAP',), 1397db96d56Sopenharmony_ci ('a, b, c = a, b, c', 'SWAP',), 1407db96d56Sopenharmony_ci ): 1417db96d56Sopenharmony_ci with self.subTest(line=line): 1427db96d56Sopenharmony_ci code = compile(line,'','single') 1437db96d56Sopenharmony_ci self.assertInBytecode(code, elem) 1447db96d56Sopenharmony_ci self.assertNotInBytecode(code, 'BUILD_TUPLE') 1457db96d56Sopenharmony_ci self.assertNotInBytecode(code, 'UNPACK_SEQUENCE') 1467db96d56Sopenharmony_ci self.check_lnotab(code) 1477db96d56Sopenharmony_ci 1487db96d56Sopenharmony_ci def test_folding_of_tuples_of_constants(self): 1497db96d56Sopenharmony_ci for line, elem in ( 1507db96d56Sopenharmony_ci ('a = 1,2,3', (1, 2, 3)), 1517db96d56Sopenharmony_ci ('("a","b","c")', ('a', 'b', 'c')), 1527db96d56Sopenharmony_ci ('a,b,c = 1,2,3', (1, 2, 3)), 1537db96d56Sopenharmony_ci ('(None, 1, None)', (None, 1, None)), 1547db96d56Sopenharmony_ci ('((1, 2), 3, 4)', ((1, 2), 3, 4)), 1557db96d56Sopenharmony_ci ): 1567db96d56Sopenharmony_ci with self.subTest(line=line): 1577db96d56Sopenharmony_ci code = compile(line,'','single') 1587db96d56Sopenharmony_ci self.assertInBytecode(code, 'LOAD_CONST', elem) 1597db96d56Sopenharmony_ci self.assertNotInBytecode(code, 'BUILD_TUPLE') 1607db96d56Sopenharmony_ci self.check_lnotab(code) 1617db96d56Sopenharmony_ci 1627db96d56Sopenharmony_ci # Long tuples should be folded too. 1637db96d56Sopenharmony_ci code = compile(repr(tuple(range(10000))),'','single') 1647db96d56Sopenharmony_ci self.assertNotInBytecode(code, 'BUILD_TUPLE') 1657db96d56Sopenharmony_ci # One LOAD_CONST for the tuple, one for the None return value 1667db96d56Sopenharmony_ci load_consts = [instr for instr in dis.get_instructions(code) 1677db96d56Sopenharmony_ci if instr.opname == 'LOAD_CONST'] 1687db96d56Sopenharmony_ci self.assertEqual(len(load_consts), 2) 1697db96d56Sopenharmony_ci self.check_lnotab(code) 1707db96d56Sopenharmony_ci 1717db96d56Sopenharmony_ci # Bug 1053819: Tuple of constants misidentified when presented with: 1727db96d56Sopenharmony_ci # . . . opcode_with_arg 100 unary_opcode BUILD_TUPLE 1 . . . 1737db96d56Sopenharmony_ci # The following would segfault upon compilation 1747db96d56Sopenharmony_ci def crater(): 1757db96d56Sopenharmony_ci (~[ 1767db96d56Sopenharmony_ci 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1777db96d56Sopenharmony_ci 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1787db96d56Sopenharmony_ci 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1797db96d56Sopenharmony_ci 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1807db96d56Sopenharmony_ci 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1817db96d56Sopenharmony_ci 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1827db96d56Sopenharmony_ci 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1837db96d56Sopenharmony_ci 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1847db96d56Sopenharmony_ci 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1857db96d56Sopenharmony_ci 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1867db96d56Sopenharmony_ci ],) 1877db96d56Sopenharmony_ci self.check_lnotab(crater) 1887db96d56Sopenharmony_ci 1897db96d56Sopenharmony_ci def test_folding_of_lists_of_constants(self): 1907db96d56Sopenharmony_ci for line, elem in ( 1917db96d56Sopenharmony_ci # in/not in constants with BUILD_LIST should be folded to a tuple: 1927db96d56Sopenharmony_ci ('a in [1,2,3]', (1, 2, 3)), 1937db96d56Sopenharmony_ci ('a not in ["a","b","c"]', ('a', 'b', 'c')), 1947db96d56Sopenharmony_ci ('a in [None, 1, None]', (None, 1, None)), 1957db96d56Sopenharmony_ci ('a not in [(1, 2), 3, 4]', ((1, 2), 3, 4)), 1967db96d56Sopenharmony_ci ): 1977db96d56Sopenharmony_ci with self.subTest(line=line): 1987db96d56Sopenharmony_ci code = compile(line, '', 'single') 1997db96d56Sopenharmony_ci self.assertInBytecode(code, 'LOAD_CONST', elem) 2007db96d56Sopenharmony_ci self.assertNotInBytecode(code, 'BUILD_LIST') 2017db96d56Sopenharmony_ci self.check_lnotab(code) 2027db96d56Sopenharmony_ci 2037db96d56Sopenharmony_ci def test_folding_of_sets_of_constants(self): 2047db96d56Sopenharmony_ci for line, elem in ( 2057db96d56Sopenharmony_ci # in/not in constants with BUILD_SET should be folded to a frozenset: 2067db96d56Sopenharmony_ci ('a in {1,2,3}', frozenset({1, 2, 3})), 2077db96d56Sopenharmony_ci ('a not in {"a","b","c"}', frozenset({'a', 'c', 'b'})), 2087db96d56Sopenharmony_ci ('a in {None, 1, None}', frozenset({1, None})), 2097db96d56Sopenharmony_ci ('a not in {(1, 2), 3, 4}', frozenset({(1, 2), 3, 4})), 2107db96d56Sopenharmony_ci ('a in {1, 2, 3, 3, 2, 1}', frozenset({1, 2, 3})), 2117db96d56Sopenharmony_ci ): 2127db96d56Sopenharmony_ci with self.subTest(line=line): 2137db96d56Sopenharmony_ci code = compile(line, '', 'single') 2147db96d56Sopenharmony_ci self.assertNotInBytecode(code, 'BUILD_SET') 2157db96d56Sopenharmony_ci self.assertInBytecode(code, 'LOAD_CONST', elem) 2167db96d56Sopenharmony_ci self.check_lnotab(code) 2177db96d56Sopenharmony_ci 2187db96d56Sopenharmony_ci # Ensure that the resulting code actually works: 2197db96d56Sopenharmony_ci def f(a): 2207db96d56Sopenharmony_ci return a in {1, 2, 3} 2217db96d56Sopenharmony_ci 2227db96d56Sopenharmony_ci def g(a): 2237db96d56Sopenharmony_ci return a not in {1, 2, 3} 2247db96d56Sopenharmony_ci 2257db96d56Sopenharmony_ci self.assertTrue(f(3)) 2267db96d56Sopenharmony_ci self.assertTrue(not f(4)) 2277db96d56Sopenharmony_ci self.check_lnotab(f) 2287db96d56Sopenharmony_ci 2297db96d56Sopenharmony_ci self.assertTrue(not g(3)) 2307db96d56Sopenharmony_ci self.assertTrue(g(4)) 2317db96d56Sopenharmony_ci self.check_lnotab(g) 2327db96d56Sopenharmony_ci 2337db96d56Sopenharmony_ci 2347db96d56Sopenharmony_ci def test_folding_of_binops_on_constants(self): 2357db96d56Sopenharmony_ci for line, elem in ( 2367db96d56Sopenharmony_ci ('a = 2+3+4', 9), # chained fold 2377db96d56Sopenharmony_ci ('"@"*4', '@@@@'), # check string ops 2387db96d56Sopenharmony_ci ('a="abc" + "def"', 'abcdef'), # check string ops 2397db96d56Sopenharmony_ci ('a = 3**4', 81), # binary power 2407db96d56Sopenharmony_ci ('a = 3*4', 12), # binary multiply 2417db96d56Sopenharmony_ci ('a = 13//4', 3), # binary floor divide 2427db96d56Sopenharmony_ci ('a = 14%4', 2), # binary modulo 2437db96d56Sopenharmony_ci ('a = 2+3', 5), # binary add 2447db96d56Sopenharmony_ci ('a = 13-4', 9), # binary subtract 2457db96d56Sopenharmony_ci ('a = (12,13)[1]', 13), # binary subscr 2467db96d56Sopenharmony_ci ('a = 13 << 2', 52), # binary lshift 2477db96d56Sopenharmony_ci ('a = 13 >> 2', 3), # binary rshift 2487db96d56Sopenharmony_ci ('a = 13 & 7', 5), # binary and 2497db96d56Sopenharmony_ci ('a = 13 ^ 7', 10), # binary xor 2507db96d56Sopenharmony_ci ('a = 13 | 7', 15), # binary or 2517db96d56Sopenharmony_ci ): 2527db96d56Sopenharmony_ci with self.subTest(line=line): 2537db96d56Sopenharmony_ci code = compile(line, '', 'single') 2547db96d56Sopenharmony_ci self.assertInBytecode(code, 'LOAD_CONST', elem) 2557db96d56Sopenharmony_ci for instr in dis.get_instructions(code): 2567db96d56Sopenharmony_ci self.assertFalse(instr.opname.startswith('BINARY_')) 2577db96d56Sopenharmony_ci self.check_lnotab(code) 2587db96d56Sopenharmony_ci 2597db96d56Sopenharmony_ci # Verify that unfoldables are skipped 2607db96d56Sopenharmony_ci code = compile('a=2+"b"', '', 'single') 2617db96d56Sopenharmony_ci self.assertInBytecode(code, 'LOAD_CONST', 2) 2627db96d56Sopenharmony_ci self.assertInBytecode(code, 'LOAD_CONST', 'b') 2637db96d56Sopenharmony_ci self.check_lnotab(code) 2647db96d56Sopenharmony_ci 2657db96d56Sopenharmony_ci # Verify that large sequences do not result from folding 2667db96d56Sopenharmony_ci code = compile('a="x"*10000', '', 'single') 2677db96d56Sopenharmony_ci self.assertInBytecode(code, 'LOAD_CONST', 10000) 2687db96d56Sopenharmony_ci self.assertNotIn("x"*10000, code.co_consts) 2697db96d56Sopenharmony_ci self.check_lnotab(code) 2707db96d56Sopenharmony_ci code = compile('a=1<<1000', '', 'single') 2717db96d56Sopenharmony_ci self.assertInBytecode(code, 'LOAD_CONST', 1000) 2727db96d56Sopenharmony_ci self.assertNotIn(1<<1000, code.co_consts) 2737db96d56Sopenharmony_ci self.check_lnotab(code) 2747db96d56Sopenharmony_ci code = compile('a=2**1000', '', 'single') 2757db96d56Sopenharmony_ci self.assertInBytecode(code, 'LOAD_CONST', 1000) 2767db96d56Sopenharmony_ci self.assertNotIn(2**1000, code.co_consts) 2777db96d56Sopenharmony_ci self.check_lnotab(code) 2787db96d56Sopenharmony_ci 2797db96d56Sopenharmony_ci def test_binary_subscr_on_unicode(self): 2807db96d56Sopenharmony_ci # valid code get optimized 2817db96d56Sopenharmony_ci code = compile('"foo"[0]', '', 'single') 2827db96d56Sopenharmony_ci self.assertInBytecode(code, 'LOAD_CONST', 'f') 2837db96d56Sopenharmony_ci self.assertNotInBytecode(code, 'BINARY_SUBSCR') 2847db96d56Sopenharmony_ci self.check_lnotab(code) 2857db96d56Sopenharmony_ci code = compile('"\u0061\uffff"[1]', '', 'single') 2867db96d56Sopenharmony_ci self.assertInBytecode(code, 'LOAD_CONST', '\uffff') 2877db96d56Sopenharmony_ci self.assertNotInBytecode(code,'BINARY_SUBSCR') 2887db96d56Sopenharmony_ci self.check_lnotab(code) 2897db96d56Sopenharmony_ci 2907db96d56Sopenharmony_ci # With PEP 393, non-BMP char get optimized 2917db96d56Sopenharmony_ci code = compile('"\U00012345"[0]', '', 'single') 2927db96d56Sopenharmony_ci self.assertInBytecode(code, 'LOAD_CONST', '\U00012345') 2937db96d56Sopenharmony_ci self.assertNotInBytecode(code, 'BINARY_SUBSCR') 2947db96d56Sopenharmony_ci self.check_lnotab(code) 2957db96d56Sopenharmony_ci 2967db96d56Sopenharmony_ci # invalid code doesn't get optimized 2977db96d56Sopenharmony_ci # out of range 2987db96d56Sopenharmony_ci code = compile('"fuu"[10]', '', 'single') 2997db96d56Sopenharmony_ci self.assertInBytecode(code, 'BINARY_SUBSCR') 3007db96d56Sopenharmony_ci self.check_lnotab(code) 3017db96d56Sopenharmony_ci 3027db96d56Sopenharmony_ci def test_folding_of_unaryops_on_constants(self): 3037db96d56Sopenharmony_ci for line, elem in ( 3047db96d56Sopenharmony_ci ('-0.5', -0.5), # unary negative 3057db96d56Sopenharmony_ci ('-0.0', -0.0), # -0.0 3067db96d56Sopenharmony_ci ('-(1.0-1.0)', -0.0), # -0.0 after folding 3077db96d56Sopenharmony_ci ('-0', 0), # -0 3087db96d56Sopenharmony_ci ('~-2', 1), # unary invert 3097db96d56Sopenharmony_ci ('+1', 1), # unary positive 3107db96d56Sopenharmony_ci ): 3117db96d56Sopenharmony_ci with self.subTest(line=line): 3127db96d56Sopenharmony_ci code = compile(line, '', 'single') 3137db96d56Sopenharmony_ci self.assertInBytecode(code, 'LOAD_CONST', elem) 3147db96d56Sopenharmony_ci for instr in dis.get_instructions(code): 3157db96d56Sopenharmony_ci self.assertFalse(instr.opname.startswith('UNARY_')) 3167db96d56Sopenharmony_ci self.check_lnotab(code) 3177db96d56Sopenharmony_ci 3187db96d56Sopenharmony_ci # Check that -0.0 works after marshaling 3197db96d56Sopenharmony_ci def negzero(): 3207db96d56Sopenharmony_ci return -(1.0-1.0) 3217db96d56Sopenharmony_ci 3227db96d56Sopenharmony_ci for instr in dis.get_instructions(negzero): 3237db96d56Sopenharmony_ci self.assertFalse(instr.opname.startswith('UNARY_')) 3247db96d56Sopenharmony_ci self.check_lnotab(negzero) 3257db96d56Sopenharmony_ci 3267db96d56Sopenharmony_ci # Verify that unfoldables are skipped 3277db96d56Sopenharmony_ci for line, elem, opname in ( 3287db96d56Sopenharmony_ci ('-"abc"', 'abc', 'UNARY_NEGATIVE'), 3297db96d56Sopenharmony_ci ('~"abc"', 'abc', 'UNARY_INVERT'), 3307db96d56Sopenharmony_ci ): 3317db96d56Sopenharmony_ci with self.subTest(line=line): 3327db96d56Sopenharmony_ci code = compile(line, '', 'single') 3337db96d56Sopenharmony_ci self.assertInBytecode(code, 'LOAD_CONST', elem) 3347db96d56Sopenharmony_ci self.assertInBytecode(code, opname) 3357db96d56Sopenharmony_ci self.check_lnotab(code) 3367db96d56Sopenharmony_ci 3377db96d56Sopenharmony_ci def test_elim_extra_return(self): 3387db96d56Sopenharmony_ci # RETURN LOAD_CONST None RETURN --> RETURN 3397db96d56Sopenharmony_ci def f(x): 3407db96d56Sopenharmony_ci return x 3417db96d56Sopenharmony_ci self.assertNotInBytecode(f, 'LOAD_CONST', None) 3427db96d56Sopenharmony_ci returns = [instr for instr in dis.get_instructions(f) 3437db96d56Sopenharmony_ci if instr.opname == 'RETURN_VALUE'] 3447db96d56Sopenharmony_ci self.assertEqual(len(returns), 1) 3457db96d56Sopenharmony_ci self.check_lnotab(f) 3467db96d56Sopenharmony_ci 3477db96d56Sopenharmony_ci @unittest.skip("Following gh-92228 the return has two predecessors " 3487db96d56Sopenharmony_ci "and that prevents jump elimination.") 3497db96d56Sopenharmony_ci def test_elim_jump_to_return(self): 3507db96d56Sopenharmony_ci # JUMP_FORWARD to RETURN --> RETURN 3517db96d56Sopenharmony_ci def f(cond, true_value, false_value): 3527db96d56Sopenharmony_ci # Intentionally use two-line expression to test issue37213. 3537db96d56Sopenharmony_ci return (true_value if cond 3547db96d56Sopenharmony_ci else false_value) 3557db96d56Sopenharmony_ci self.check_jump_targets(f) 3567db96d56Sopenharmony_ci self.assertNotInBytecode(f, 'JUMP_FORWARD') 3577db96d56Sopenharmony_ci self.assertNotInBytecode(f, 'JUMP_ABSOLUTE') 3587db96d56Sopenharmony_ci returns = [instr for instr in dis.get_instructions(f) 3597db96d56Sopenharmony_ci if instr.opname == 'RETURN_VALUE'] 3607db96d56Sopenharmony_ci self.assertEqual(len(returns), 2) 3617db96d56Sopenharmony_ci self.check_lnotab(f) 3627db96d56Sopenharmony_ci 3637db96d56Sopenharmony_ci def test_elim_jump_to_uncond_jump(self): 3647db96d56Sopenharmony_ci # POP_JUMP_IF_FALSE to JUMP_FORWARD --> POP_JUMP_IF_FALSE to non-jump 3657db96d56Sopenharmony_ci def f(): 3667db96d56Sopenharmony_ci if a: 3677db96d56Sopenharmony_ci # Intentionally use two-line expression to test issue37213. 3687db96d56Sopenharmony_ci if (c 3697db96d56Sopenharmony_ci or d): 3707db96d56Sopenharmony_ci foo() 3717db96d56Sopenharmony_ci else: 3727db96d56Sopenharmony_ci baz() 3737db96d56Sopenharmony_ci self.check_jump_targets(f) 3747db96d56Sopenharmony_ci self.check_lnotab(f) 3757db96d56Sopenharmony_ci 3767db96d56Sopenharmony_ci def test_elim_jump_to_uncond_jump2(self): 3777db96d56Sopenharmony_ci # POP_JUMP_IF_FALSE to JUMP_ABSOLUTE --> POP_JUMP_IF_FALSE to non-jump 3787db96d56Sopenharmony_ci def f(): 3797db96d56Sopenharmony_ci while a: 3807db96d56Sopenharmony_ci # Intentionally use two-line expression to test issue37213. 3817db96d56Sopenharmony_ci if (c 3827db96d56Sopenharmony_ci or d): 3837db96d56Sopenharmony_ci a = foo() 3847db96d56Sopenharmony_ci self.check_jump_targets(f) 3857db96d56Sopenharmony_ci self.check_lnotab(f) 3867db96d56Sopenharmony_ci 3877db96d56Sopenharmony_ci def test_elim_jump_to_uncond_jump3(self): 3887db96d56Sopenharmony_ci # Intentionally use two-line expressions to test issue37213. 3897db96d56Sopenharmony_ci # JUMP_IF_FALSE_OR_POP to JUMP_IF_FALSE_OR_POP --> JUMP_IF_FALSE_OR_POP to non-jump 3907db96d56Sopenharmony_ci def f(a, b, c): 3917db96d56Sopenharmony_ci return ((a and b) 3927db96d56Sopenharmony_ci and c) 3937db96d56Sopenharmony_ci self.check_jump_targets(f) 3947db96d56Sopenharmony_ci self.check_lnotab(f) 3957db96d56Sopenharmony_ci self.assertEqual(count_instr_recursively(f, 'JUMP_IF_FALSE_OR_POP'), 2) 3967db96d56Sopenharmony_ci # JUMP_IF_TRUE_OR_POP to JUMP_IF_TRUE_OR_POP --> JUMP_IF_TRUE_OR_POP to non-jump 3977db96d56Sopenharmony_ci def f(a, b, c): 3987db96d56Sopenharmony_ci return ((a or b) 3997db96d56Sopenharmony_ci or c) 4007db96d56Sopenharmony_ci self.check_jump_targets(f) 4017db96d56Sopenharmony_ci self.check_lnotab(f) 4027db96d56Sopenharmony_ci self.assertEqual(count_instr_recursively(f, 'JUMP_IF_TRUE_OR_POP'), 2) 4037db96d56Sopenharmony_ci # JUMP_IF_FALSE_OR_POP to JUMP_IF_TRUE_OR_POP --> POP_JUMP_IF_FALSE to non-jump 4047db96d56Sopenharmony_ci def f(a, b, c): 4057db96d56Sopenharmony_ci return ((a and b) 4067db96d56Sopenharmony_ci or c) 4077db96d56Sopenharmony_ci self.check_jump_targets(f) 4087db96d56Sopenharmony_ci self.check_lnotab(f) 4097db96d56Sopenharmony_ci self.assertNotInBytecode(f, 'JUMP_IF_FALSE_OR_POP') 4107db96d56Sopenharmony_ci self.assertInBytecode(f, 'JUMP_IF_TRUE_OR_POP') 4117db96d56Sopenharmony_ci self.assertInBytecode(f, 'POP_JUMP_FORWARD_IF_FALSE') 4127db96d56Sopenharmony_ci # JUMP_IF_TRUE_OR_POP to JUMP_IF_FALSE_OR_POP --> POP_JUMP_IF_TRUE to non-jump 4137db96d56Sopenharmony_ci def f(a, b, c): 4147db96d56Sopenharmony_ci return ((a or b) 4157db96d56Sopenharmony_ci and c) 4167db96d56Sopenharmony_ci self.check_jump_targets(f) 4177db96d56Sopenharmony_ci self.check_lnotab(f) 4187db96d56Sopenharmony_ci self.assertNotInBytecode(f, 'JUMP_IF_TRUE_OR_POP') 4197db96d56Sopenharmony_ci self.assertInBytecode(f, 'JUMP_IF_FALSE_OR_POP') 4207db96d56Sopenharmony_ci self.assertInBytecode(f, 'POP_JUMP_FORWARD_IF_TRUE') 4217db96d56Sopenharmony_ci 4227db96d56Sopenharmony_ci def test_elim_jump_after_return1(self): 4237db96d56Sopenharmony_ci # Eliminate dead code: jumps immediately after returns can't be reached 4247db96d56Sopenharmony_ci def f(cond1, cond2): 4257db96d56Sopenharmony_ci if cond1: return 1 4267db96d56Sopenharmony_ci if cond2: return 2 4277db96d56Sopenharmony_ci while 1: 4287db96d56Sopenharmony_ci return 3 4297db96d56Sopenharmony_ci while 1: 4307db96d56Sopenharmony_ci if cond1: return 4 4317db96d56Sopenharmony_ci return 5 4327db96d56Sopenharmony_ci return 6 4337db96d56Sopenharmony_ci self.assertNotInBytecode(f, 'JUMP_FORWARD') 4347db96d56Sopenharmony_ci self.assertNotInBytecode(f, 'JUMP_ABSOLUTE') 4357db96d56Sopenharmony_ci returns = [instr for instr in dis.get_instructions(f) 4367db96d56Sopenharmony_ci if instr.opname == 'RETURN_VALUE'] 4377db96d56Sopenharmony_ci self.assertLessEqual(len(returns), 6) 4387db96d56Sopenharmony_ci self.check_lnotab(f) 4397db96d56Sopenharmony_ci 4407db96d56Sopenharmony_ci def test_make_function_doesnt_bail(self): 4417db96d56Sopenharmony_ci def f(): 4427db96d56Sopenharmony_ci def g()->1+1: 4437db96d56Sopenharmony_ci pass 4447db96d56Sopenharmony_ci return g 4457db96d56Sopenharmony_ci self.assertNotInBytecode(f, 'BINARY_OP') 4467db96d56Sopenharmony_ci self.check_lnotab(f) 4477db96d56Sopenharmony_ci 4487db96d56Sopenharmony_ci def test_constant_folding(self): 4497db96d56Sopenharmony_ci # Issue #11244: aggressive constant folding. 4507db96d56Sopenharmony_ci exprs = [ 4517db96d56Sopenharmony_ci '3 * -5', 4527db96d56Sopenharmony_ci '-3 * 5', 4537db96d56Sopenharmony_ci '2 * (3 * 4)', 4547db96d56Sopenharmony_ci '(2 * 3) * 4', 4557db96d56Sopenharmony_ci '(-1, 2, 3)', 4567db96d56Sopenharmony_ci '(1, -2, 3)', 4577db96d56Sopenharmony_ci '(1, 2, -3)', 4587db96d56Sopenharmony_ci '(1, 2, -3) * 6', 4597db96d56Sopenharmony_ci 'lambda x: x in {(3 * -5) + (-1 - 6), (1, -2, 3) * 2, None}', 4607db96d56Sopenharmony_ci ] 4617db96d56Sopenharmony_ci for e in exprs: 4627db96d56Sopenharmony_ci with self.subTest(e=e): 4637db96d56Sopenharmony_ci code = compile(e, '', 'single') 4647db96d56Sopenharmony_ci for instr in dis.get_instructions(code): 4657db96d56Sopenharmony_ci self.assertFalse(instr.opname.startswith('UNARY_')) 4667db96d56Sopenharmony_ci self.assertFalse(instr.opname.startswith('BINARY_')) 4677db96d56Sopenharmony_ci self.assertFalse(instr.opname.startswith('BUILD_')) 4687db96d56Sopenharmony_ci self.check_lnotab(code) 4697db96d56Sopenharmony_ci 4707db96d56Sopenharmony_ci def test_in_literal_list(self): 4717db96d56Sopenharmony_ci def containtest(): 4727db96d56Sopenharmony_ci return x in [a, b] 4737db96d56Sopenharmony_ci self.assertEqual(count_instr_recursively(containtest, 'BUILD_LIST'), 0) 4747db96d56Sopenharmony_ci self.check_lnotab(containtest) 4757db96d56Sopenharmony_ci 4767db96d56Sopenharmony_ci def test_iterate_literal_list(self): 4777db96d56Sopenharmony_ci def forloop(): 4787db96d56Sopenharmony_ci for x in [a, b]: 4797db96d56Sopenharmony_ci pass 4807db96d56Sopenharmony_ci self.assertEqual(count_instr_recursively(forloop, 'BUILD_LIST'), 0) 4817db96d56Sopenharmony_ci self.check_lnotab(forloop) 4827db96d56Sopenharmony_ci 4837db96d56Sopenharmony_ci def test_condition_with_binop_with_bools(self): 4847db96d56Sopenharmony_ci def f(): 4857db96d56Sopenharmony_ci if True or False: 4867db96d56Sopenharmony_ci return 1 4877db96d56Sopenharmony_ci return 0 4887db96d56Sopenharmony_ci self.assertEqual(f(), 1) 4897db96d56Sopenharmony_ci self.check_lnotab(f) 4907db96d56Sopenharmony_ci 4917db96d56Sopenharmony_ci def test_if_with_if_expression(self): 4927db96d56Sopenharmony_ci # Check bpo-37289 4937db96d56Sopenharmony_ci def f(x): 4947db96d56Sopenharmony_ci if (True if x else False): 4957db96d56Sopenharmony_ci return True 4967db96d56Sopenharmony_ci return False 4977db96d56Sopenharmony_ci self.assertTrue(f(True)) 4987db96d56Sopenharmony_ci self.check_lnotab(f) 4997db96d56Sopenharmony_ci 5007db96d56Sopenharmony_ci def test_trailing_nops(self): 5017db96d56Sopenharmony_ci # Check the lnotab of a function that even after trivial 5027db96d56Sopenharmony_ci # optimization has trailing nops, which the lnotab adjustment has to 5037db96d56Sopenharmony_ci # handle properly (bpo-38115). 5047db96d56Sopenharmony_ci def f(x): 5057db96d56Sopenharmony_ci while 1: 5067db96d56Sopenharmony_ci return 3 5077db96d56Sopenharmony_ci while 1: 5087db96d56Sopenharmony_ci return 5 5097db96d56Sopenharmony_ci return 6 5107db96d56Sopenharmony_ci self.check_lnotab(f) 5117db96d56Sopenharmony_ci 5127db96d56Sopenharmony_ci def test_assignment_idiom_in_comprehensions(self): 5137db96d56Sopenharmony_ci def listcomp(): 5147db96d56Sopenharmony_ci return [y for x in a for y in [f(x)]] 5157db96d56Sopenharmony_ci self.assertEqual(count_instr_recursively(listcomp, 'FOR_ITER'), 1) 5167db96d56Sopenharmony_ci def setcomp(): 5177db96d56Sopenharmony_ci return {y for x in a for y in [f(x)]} 5187db96d56Sopenharmony_ci self.assertEqual(count_instr_recursively(setcomp, 'FOR_ITER'), 1) 5197db96d56Sopenharmony_ci def dictcomp(): 5207db96d56Sopenharmony_ci return {y: y for x in a for y in [f(x)]} 5217db96d56Sopenharmony_ci self.assertEqual(count_instr_recursively(dictcomp, 'FOR_ITER'), 1) 5227db96d56Sopenharmony_ci def genexpr(): 5237db96d56Sopenharmony_ci return (y for x in a for y in [f(x)]) 5247db96d56Sopenharmony_ci self.assertEqual(count_instr_recursively(genexpr, 'FOR_ITER'), 1) 5257db96d56Sopenharmony_ci 5267db96d56Sopenharmony_ci def test_format_combinations(self): 5277db96d56Sopenharmony_ci flags = '-+ #0' 5287db96d56Sopenharmony_ci testcases = [ 5297db96d56Sopenharmony_ci *product(('', '1234', 'абвг'), 'sra'), 5307db96d56Sopenharmony_ci *product((1234, -1234), 'duioxX'), 5317db96d56Sopenharmony_ci *product((1234.5678901, -1234.5678901), 'duifegFEG'), 5327db96d56Sopenharmony_ci *product((float('inf'), -float('inf')), 'fegFEG'), 5337db96d56Sopenharmony_ci ] 5347db96d56Sopenharmony_ci width_precs = [ 5357db96d56Sopenharmony_ci *product(('', '1', '30'), ('', '.', '.0', '.2')), 5367db96d56Sopenharmony_ci ('', '.40'), 5377db96d56Sopenharmony_ci ('30', '.40'), 5387db96d56Sopenharmony_ci ] 5397db96d56Sopenharmony_ci for value, suffix in testcases: 5407db96d56Sopenharmony_ci for width, prec in width_precs: 5417db96d56Sopenharmony_ci for r in range(len(flags) + 1): 5427db96d56Sopenharmony_ci for spec in combinations(flags, r): 5437db96d56Sopenharmony_ci fmt = '%' + ''.join(spec) + width + prec + suffix 5447db96d56Sopenharmony_ci with self.subTest(fmt=fmt, value=value): 5457db96d56Sopenharmony_ci s1 = fmt % value 5467db96d56Sopenharmony_ci s2 = eval(f'{fmt!r} % (x,)', {'x': value}) 5477db96d56Sopenharmony_ci self.assertEqual(s2, s1, f'{fmt = }') 5487db96d56Sopenharmony_ci 5497db96d56Sopenharmony_ci def test_format_misc(self): 5507db96d56Sopenharmony_ci def format(fmt, *values): 5517db96d56Sopenharmony_ci vars = [f'x{i+1}' for i in range(len(values))] 5527db96d56Sopenharmony_ci if len(vars) == 1: 5537db96d56Sopenharmony_ci args = '(' + vars[0] + ',)' 5547db96d56Sopenharmony_ci else: 5557db96d56Sopenharmony_ci args = '(' + ', '.join(vars) + ')' 5567db96d56Sopenharmony_ci return eval(f'{fmt!r} % {args}', dict(zip(vars, values))) 5577db96d56Sopenharmony_ci 5587db96d56Sopenharmony_ci self.assertEqual(format('string'), 'string') 5597db96d56Sopenharmony_ci self.assertEqual(format('x = %s!', 1234), 'x = 1234!') 5607db96d56Sopenharmony_ci self.assertEqual(format('x = %d!', 1234), 'x = 1234!') 5617db96d56Sopenharmony_ci self.assertEqual(format('x = %x!', 1234), 'x = 4d2!') 5627db96d56Sopenharmony_ci self.assertEqual(format('x = %f!', 1234), 'x = 1234.000000!') 5637db96d56Sopenharmony_ci self.assertEqual(format('x = %s!', 1234.5678901), 'x = 1234.5678901!') 5647db96d56Sopenharmony_ci self.assertEqual(format('x = %f!', 1234.5678901), 'x = 1234.567890!') 5657db96d56Sopenharmony_ci self.assertEqual(format('x = %d!', 1234.5678901), 'x = 1234!') 5667db96d56Sopenharmony_ci self.assertEqual(format('x = %s%% %%%%', 1234), 'x = 1234% %%') 5677db96d56Sopenharmony_ci self.assertEqual(format('x = %s!', '%% %s'), 'x = %% %s!') 5687db96d56Sopenharmony_ci self.assertEqual(format('x = %s, y = %d', 12, 34), 'x = 12, y = 34') 5697db96d56Sopenharmony_ci 5707db96d56Sopenharmony_ci def test_format_errors(self): 5717db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, 5727db96d56Sopenharmony_ci 'not enough arguments for format string'): 5737db96d56Sopenharmony_ci eval("'%s' % ()") 5747db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, 5757db96d56Sopenharmony_ci 'not all arguments converted during string formatting'): 5767db96d56Sopenharmony_ci eval("'%s' % (x, y)", {'x': 1, 'y': 2}) 5777db96d56Sopenharmony_ci with self.assertRaisesRegex(ValueError, 'incomplete format'): 5787db96d56Sopenharmony_ci eval("'%s%' % (x,)", {'x': 1234}) 5797db96d56Sopenharmony_ci with self.assertRaisesRegex(ValueError, 'incomplete format'): 5807db96d56Sopenharmony_ci eval("'%s%%%' % (x,)", {'x': 1234}) 5817db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, 5827db96d56Sopenharmony_ci 'not enough arguments for format string'): 5837db96d56Sopenharmony_ci eval("'%s%z' % (x,)", {'x': 1234}) 5847db96d56Sopenharmony_ci with self.assertRaisesRegex(ValueError, 'unsupported format character'): 5857db96d56Sopenharmony_ci eval("'%s%z' % (x, 5)", {'x': 1234}) 5867db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, 'a real number is required, not str'): 5877db96d56Sopenharmony_ci eval("'%d' % (x,)", {'x': '1234'}) 5887db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, 'an integer is required, not float'): 5897db96d56Sopenharmony_ci eval("'%x' % (x,)", {'x': 1234.56}) 5907db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, 'an integer is required, not str'): 5917db96d56Sopenharmony_ci eval("'%x' % (x,)", {'x': '1234'}) 5927db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, 'must be real number, not str'): 5937db96d56Sopenharmony_ci eval("'%f' % (x,)", {'x': '1234'}) 5947db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, 5957db96d56Sopenharmony_ci 'not enough arguments for format string'): 5967db96d56Sopenharmony_ci eval("'%s, %s' % (x, *y)", {'x': 1, 'y': []}) 5977db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, 5987db96d56Sopenharmony_ci 'not all arguments converted during string formatting'): 5997db96d56Sopenharmony_ci eval("'%s, %s' % (x, *y)", {'x': 1, 'y': [2, 3]}) 6007db96d56Sopenharmony_ci 6017db96d56Sopenharmony_ci def test_static_swaps_unpack_two(self): 6027db96d56Sopenharmony_ci def f(a, b): 6037db96d56Sopenharmony_ci a, b = a, b 6047db96d56Sopenharmony_ci b, a = a, b 6057db96d56Sopenharmony_ci self.assertNotInBytecode(f, "SWAP") 6067db96d56Sopenharmony_ci 6077db96d56Sopenharmony_ci def test_static_swaps_unpack_three(self): 6087db96d56Sopenharmony_ci def f(a, b, c): 6097db96d56Sopenharmony_ci a, b, c = a, b, c 6107db96d56Sopenharmony_ci a, c, b = a, b, c 6117db96d56Sopenharmony_ci b, a, c = a, b, c 6127db96d56Sopenharmony_ci b, c, a = a, b, c 6137db96d56Sopenharmony_ci c, a, b = a, b, c 6147db96d56Sopenharmony_ci c, b, a = a, b, c 6157db96d56Sopenharmony_ci self.assertNotInBytecode(f, "SWAP") 6167db96d56Sopenharmony_ci 6177db96d56Sopenharmony_ci def test_static_swaps_match_mapping(self): 6187db96d56Sopenharmony_ci for a, b, c in product("_a", "_b", "_c"): 6197db96d56Sopenharmony_ci pattern = f"{{'a': {a}, 'b': {b}, 'c': {c}}}" 6207db96d56Sopenharmony_ci with self.subTest(pattern): 6217db96d56Sopenharmony_ci code = compile_pattern_with_fast_locals(pattern) 6227db96d56Sopenharmony_ci self.assertNotInBytecode(code, "SWAP") 6237db96d56Sopenharmony_ci 6247db96d56Sopenharmony_ci def test_static_swaps_match_class(self): 6257db96d56Sopenharmony_ci forms = [ 6267db96d56Sopenharmony_ci "C({}, {}, {})", 6277db96d56Sopenharmony_ci "C({}, {}, c={})", 6287db96d56Sopenharmony_ci "C({}, b={}, c={})", 6297db96d56Sopenharmony_ci "C(a={}, b={}, c={})" 6307db96d56Sopenharmony_ci ] 6317db96d56Sopenharmony_ci for a, b, c in product("_a", "_b", "_c"): 6327db96d56Sopenharmony_ci for form in forms: 6337db96d56Sopenharmony_ci pattern = form.format(a, b, c) 6347db96d56Sopenharmony_ci with self.subTest(pattern): 6357db96d56Sopenharmony_ci code = compile_pattern_with_fast_locals(pattern) 6367db96d56Sopenharmony_ci self.assertNotInBytecode(code, "SWAP") 6377db96d56Sopenharmony_ci 6387db96d56Sopenharmony_ci def test_static_swaps_match_sequence(self): 6397db96d56Sopenharmony_ci swaps = {"*_, b, c", "a, *_, c", "a, b, *_"} 6407db96d56Sopenharmony_ci forms = ["{}, {}, {}", "{}, {}, *{}", "{}, *{}, {}", "*{}, {}, {}"] 6417db96d56Sopenharmony_ci for a, b, c in product("_a", "_b", "_c"): 6427db96d56Sopenharmony_ci for form in forms: 6437db96d56Sopenharmony_ci pattern = form.format(a, b, c) 6447db96d56Sopenharmony_ci with self.subTest(pattern): 6457db96d56Sopenharmony_ci code = compile_pattern_with_fast_locals(pattern) 6467db96d56Sopenharmony_ci if pattern in swaps: 6477db96d56Sopenharmony_ci # If this fails... great! Remove this pattern from swaps 6487db96d56Sopenharmony_ci # to prevent regressing on any improvement: 6497db96d56Sopenharmony_ci self.assertInBytecode(code, "SWAP") 6507db96d56Sopenharmony_ci else: 6517db96d56Sopenharmony_ci self.assertNotInBytecode(code, "SWAP") 6527db96d56Sopenharmony_ci 6537db96d56Sopenharmony_ci 6547db96d56Sopenharmony_ciclass TestBuglets(unittest.TestCase): 6557db96d56Sopenharmony_ci 6567db96d56Sopenharmony_ci def test_bug_11510(self): 6577db96d56Sopenharmony_ci # folded constant set optimization was commingled with the tuple 6587db96d56Sopenharmony_ci # unpacking optimization which would fail if the set had duplicate 6597db96d56Sopenharmony_ci # elements so that the set length was unexpected 6607db96d56Sopenharmony_ci def f(): 6617db96d56Sopenharmony_ci x, y = {1, 1} 6627db96d56Sopenharmony_ci return x, y 6637db96d56Sopenharmony_ci with self.assertRaises(ValueError): 6647db96d56Sopenharmony_ci f() 6657db96d56Sopenharmony_ci 6667db96d56Sopenharmony_ci def test_bpo_42057(self): 6677db96d56Sopenharmony_ci for i in range(10): 6687db96d56Sopenharmony_ci try: 6697db96d56Sopenharmony_ci raise Exception 6707db96d56Sopenharmony_ci except Exception or Exception: 6717db96d56Sopenharmony_ci pass 6727db96d56Sopenharmony_ci 6737db96d56Sopenharmony_ci def test_bpo_45773_pop_jump_if_true(self): 6747db96d56Sopenharmony_ci compile("while True or spam: pass", "<test>", "exec") 6757db96d56Sopenharmony_ci 6767db96d56Sopenharmony_ci def test_bpo_45773_pop_jump_if_false(self): 6777db96d56Sopenharmony_ci compile("while True or not spam: pass", "<test>", "exec") 6787db96d56Sopenharmony_ci 6797db96d56Sopenharmony_ci 6807db96d56Sopenharmony_ciif __name__ == "__main__": 6817db96d56Sopenharmony_ci unittest.main() 682