blob: 9c206d1d09c0b519fd12134ebb8423be61318b74 [file] [log] [blame]
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +00001import dis
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +00002import unittest
3
Nick Coghland6245172013-05-07 00:03:00 +10004from test.bytecode_helper import BytecodeTestCase
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +00005
Victor Stinner466e18e2019-07-01 19:01:52 +02006
Serhiy Storchaka3f7e9aa2018-03-11 10:54:47 +02007def count_instr_recursively(f, opname):
8 count = 0
9 for instr in dis.get_instructions(f):
10 if instr.opname == opname:
11 count += 1
12 if hasattr(f, '__code__'):
13 f = f.__code__
14 for c in f.co_consts:
15 if hasattr(c, 'co_code'):
16 count += count_instr_recursively(c, opname)
17 return count
18
19
Nick Coghland6245172013-05-07 00:03:00 +100020class TestTranforms(BytecodeTestCase):
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +000021
Miss Islington (bot)5282b3b2019-06-13 11:35:40 -070022 def check_jump_targets(self, code):
23 instructions = list(dis.get_instructions(code))
24 targets = {instr.offset: instr for instr in instructions}
25 for instr in instructions:
26 if 'JUMP_' not in instr.opname:
27 continue
28 tgt = targets[instr.argval]
29 # jump to unconditional jump
30 if tgt.opname in ('JUMP_ABSOLUTE', 'JUMP_FORWARD'):
31 self.fail(f'{instr.opname} at {instr.offset} '
32 f'jumps to {tgt.opname} at {tgt.offset}')
33 # unconditional jump to RETURN_VALUE
34 if (instr.opname in ('JUMP_ABSOLUTE', 'JUMP_FORWARD') and
35 tgt.opname == 'RETURN_VALUE'):
36 self.fail(f'{instr.opname} at {instr.offset} '
37 f'jumps to {tgt.opname} at {tgt.offset}')
38 # JUMP_IF_*_OR_POP jump to conditional jump
39 if '_OR_POP' in instr.opname and 'JUMP_IF_' in tgt.opname:
40 self.fail(f'{instr.opname} at {instr.offset} '
41 f'jumps to {tgt.opname} at {tgt.offset}')
42
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +000043 def test_unot(self):
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +000044 # UNARY_NOT POP_JUMP_IF_FALSE --> POP_JUMP_IF_TRUE'
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +000045 def unot(x):
46 if not x == 2:
47 del x
Nick Coghland6245172013-05-07 00:03:00 +100048 self.assertNotInBytecode(unot, 'UNARY_NOT')
49 self.assertNotInBytecode(unot, 'POP_JUMP_IF_FALSE')
50 self.assertInBytecode(unot, 'POP_JUMP_IF_TRUE')
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +000051
52 def test_elim_inversion_of_is_or_in(self):
Nick Coghland6245172013-05-07 00:03:00 +100053 for line, cmp_op in (
54 ('not a is b', 'is not',),
55 ('not a in b', 'not in',),
56 ('not a is not b', 'is',),
57 ('not a not in b', 'in',),
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +000058 ):
Nick Coghland6245172013-05-07 00:03:00 +100059 code = compile(line, '', 'single')
60 self.assertInBytecode(code, 'COMPARE_OP', cmp_op)
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +000061
Guido van Rossumcd16bf62007-06-13 18:07:49 +000062 def test_global_as_constant(self):
63 # LOAD_GLOBAL None/True/False --> LOAD_CONST None/True/False
Victor Stinner51d8c522016-02-08 17:57:02 +010064 def f():
65 x = None
66 x = None
Tim Peters66cb0182004-08-26 05:23:19 +000067 return x
Victor Stinner51d8c522016-02-08 17:57:02 +010068 def g():
69 x = True
Guido van Rossumcd16bf62007-06-13 18:07:49 +000070 return x
Victor Stinner51d8c522016-02-08 17:57:02 +010071 def h():
72 x = False
Guido van Rossumcd16bf62007-06-13 18:07:49 +000073 return x
Victor Stinner51d8c522016-02-08 17:57:02 +010074
Nick Coghland6245172013-05-07 00:03:00 +100075 for func, elem in ((f, None), (g, True), (h, False)):
76 self.assertNotInBytecode(func, 'LOAD_GLOBAL')
77 self.assertInBytecode(func, 'LOAD_CONST', elem)
Victor Stinner51d8c522016-02-08 17:57:02 +010078
Guido van Rossumd8faa362007-04-27 19:54:29 +000079 def f():
80 'Adding a docstring made this test fail in Py2.5.0'
81 return None
Victor Stinner51d8c522016-02-08 17:57:02 +010082
Nick Coghland6245172013-05-07 00:03:00 +100083 self.assertNotInBytecode(f, 'LOAD_GLOBAL')
84 self.assertInBytecode(f, 'LOAD_CONST', None)
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +000085
86 def test_while_one(self):
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +000087 # Skip over: LOAD_CONST trueconst POP_JUMP_IF_FALSE xx
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +000088 def f():
Tim Peters66cb0182004-08-26 05:23:19 +000089 while 1:
90 pass
91 return list
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +000092 for elem in ('LOAD_CONST', 'POP_JUMP_IF_FALSE'):
Nick Coghland6245172013-05-07 00:03:00 +100093 self.assertNotInBytecode(f, elem)
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +000094 for elem in ('JUMP_ABSOLUTE',):
Nick Coghland6245172013-05-07 00:03:00 +100095 self.assertInBytecode(f, elem)
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +000096
97 def test_pack_unpack(self):
98 for line, elem in (
Raymond Hettinger2c31a052004-09-22 18:44:21 +000099 ('a, = a,', 'LOAD_CONST',),
100 ('a, b = a, b', 'ROT_TWO',),
101 ('a, b, c = a, b, c', 'ROT_THREE',),
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +0000102 ):
Nick Coghland6245172013-05-07 00:03:00 +1000103 code = compile(line,'','single')
104 self.assertInBytecode(code, elem)
105 self.assertNotInBytecode(code, 'BUILD_TUPLE')
106 self.assertNotInBytecode(code, 'UNPACK_TUPLE')
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +0000107
Raymond Hettinger2c31a052004-09-22 18:44:21 +0000108 def test_folding_of_tuples_of_constants(self):
109 for line, elem in (
Nick Coghland6245172013-05-07 00:03:00 +1000110 ('a = 1,2,3', (1, 2, 3)),
111 ('("a","b","c")', ('a', 'b', 'c')),
112 ('a,b,c = 1,2,3', (1, 2, 3)),
113 ('(None, 1, None)', (None, 1, None)),
114 ('((1, 2), 3, 4)', ((1, 2), 3, 4)),
Raymond Hettinger2c31a052004-09-22 18:44:21 +0000115 ):
Nick Coghland6245172013-05-07 00:03:00 +1000116 code = compile(line,'','single')
117 self.assertInBytecode(code, 'LOAD_CONST', elem)
118 self.assertNotInBytecode(code, 'BUILD_TUPLE')
Raymond Hettinger2c31a052004-09-22 18:44:21 +0000119
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100120 # Long tuples should be folded too.
Nick Coghland6245172013-05-07 00:03:00 +1000121 code = compile(repr(tuple(range(10000))),'','single')
122 self.assertNotInBytecode(code, 'BUILD_TUPLE')
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100123 # One LOAD_CONST for the tuple, one for the None return value
Nick Coghland6245172013-05-07 00:03:00 +1000124 load_consts = [instr for instr in dis.get_instructions(code)
125 if instr.opname == 'LOAD_CONST']
126 self.assertEqual(len(load_consts), 2)
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100127
Raymond Hettinger23109ef2004-10-26 08:59:14 +0000128 # Bug 1053819: Tuple of constants misidentified when presented with:
129 # . . . opcode_with_arg 100 unary_opcode BUILD_TUPLE 1 . . .
130 # The following would segfault upon compilation
131 def crater():
132 (~[
133 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
134 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
135 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
136 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
137 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
138 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
139 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
140 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
141 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
142 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
143 ],)
144
Antoine Pitroub7fbcd32010-01-16 18:37:38 +0000145 def test_folding_of_lists_of_constants(self):
146 for line, elem in (
147 # in/not in constants with BUILD_LIST should be folded to a tuple:
Nick Coghland6245172013-05-07 00:03:00 +1000148 ('a in [1,2,3]', (1, 2, 3)),
149 ('a not in ["a","b","c"]', ('a', 'b', 'c')),
150 ('a in [None, 1, None]', (None, 1, None)),
151 ('a not in [(1, 2), 3, 4]', ((1, 2), 3, 4)),
Antoine Pitroub7fbcd32010-01-16 18:37:38 +0000152 ):
Nick Coghland6245172013-05-07 00:03:00 +1000153 code = compile(line, '', 'single')
154 self.assertInBytecode(code, 'LOAD_CONST', elem)
155 self.assertNotInBytecode(code, 'BUILD_LIST')
Antoine Pitroub7fbcd32010-01-16 18:37:38 +0000156
157 def test_folding_of_sets_of_constants(self):
158 for line, elem in (
159 # in/not in constants with BUILD_SET should be folded to a frozenset:
160 ('a in {1,2,3}', frozenset({1, 2, 3})),
161 ('a not in {"a","b","c"}', frozenset({'a', 'c', 'b'})),
162 ('a in {None, 1, None}', frozenset({1, None})),
163 ('a not in {(1, 2), 3, 4}', frozenset({(1, 2), 3, 4})),
164 ('a in {1, 2, 3, 3, 2, 1}', frozenset({1, 2, 3})),
165 ):
Nick Coghland6245172013-05-07 00:03:00 +1000166 code = compile(line, '', 'single')
167 self.assertNotInBytecode(code, 'BUILD_SET')
168 self.assertInBytecode(code, 'LOAD_CONST', elem)
Antoine Pitroub7fbcd32010-01-16 18:37:38 +0000169
170 # Ensure that the resulting code actually works:
171 def f(a):
172 return a in {1, 2, 3}
173
174 def g(a):
175 return a not in {1, 2, 3}
176
177 self.assertTrue(f(3))
178 self.assertTrue(not f(4))
179
180 self.assertTrue(not g(3))
181 self.assertTrue(g(4))
182
183
Raymond Hettingerc34f8672005-01-02 06:17:33 +0000184 def test_folding_of_binops_on_constants(self):
185 for line, elem in (
Nick Coghland6245172013-05-07 00:03:00 +1000186 ('a = 2+3+4', 9), # chained fold
187 ('"@"*4', '@@@@'), # check string ops
188 ('a="abc" + "def"', 'abcdef'), # check string ops
189 ('a = 3**4', 81), # binary power
190 ('a = 3*4', 12), # binary multiply
191 ('a = 13//4', 3), # binary floor divide
192 ('a = 14%4', 2), # binary modulo
193 ('a = 2+3', 5), # binary add
194 ('a = 13-4', 9), # binary subtract
195 ('a = (12,13)[1]', 13), # binary subscr
196 ('a = 13 << 2', 52), # binary lshift
197 ('a = 13 >> 2', 3), # binary rshift
198 ('a = 13 & 7', 5), # binary and
199 ('a = 13 ^ 7', 10), # binary xor
200 ('a = 13 | 7', 15), # binary or
Raymond Hettingerc34f8672005-01-02 06:17:33 +0000201 ):
Nick Coghland6245172013-05-07 00:03:00 +1000202 code = compile(line, '', 'single')
203 self.assertInBytecode(code, 'LOAD_CONST', elem)
204 for instr in dis.get_instructions(code):
205 self.assertFalse(instr.opname.startswith('BINARY_'))
Raymond Hettingerc34f8672005-01-02 06:17:33 +0000206
207 # Verify that unfoldables are skipped
Nick Coghland6245172013-05-07 00:03:00 +1000208 code = compile('a=2+"b"', '', 'single')
209 self.assertInBytecode(code, 'LOAD_CONST', 2)
210 self.assertInBytecode(code, 'LOAD_CONST', 'b')
Raymond Hettingerc34f8672005-01-02 06:17:33 +0000211
Raymond Hettinger9feb2672005-01-26 12:50:05 +0000212 # Verify that large sequences do not result from folding
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200213 code = compile('a="x"*10000', '', 'single')
214 self.assertInBytecode(code, 'LOAD_CONST', 10000)
215 self.assertNotIn("x"*10000, code.co_consts)
216 code = compile('a=1<<1000', '', 'single')
Nick Coghland6245172013-05-07 00:03:00 +1000217 self.assertInBytecode(code, 'LOAD_CONST', 1000)
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200218 self.assertNotIn(1<<1000, code.co_consts)
219 code = compile('a=2**1000', '', 'single')
220 self.assertInBytecode(code, 'LOAD_CONST', 1000)
221 self.assertNotIn(2**1000, code.co_consts)
Raymond Hettinger9feb2672005-01-26 12:50:05 +0000222
Ezio Melotti2df6a932011-04-15 16:38:34 +0300223 def test_binary_subscr_on_unicode(self):
224 # valid code get optimized
Nick Coghland6245172013-05-07 00:03:00 +1000225 code = compile('"foo"[0]', '', 'single')
226 self.assertInBytecode(code, 'LOAD_CONST', 'f')
227 self.assertNotInBytecode(code, 'BINARY_SUBSCR')
228 code = compile('"\u0061\uffff"[1]', '', 'single')
229 self.assertInBytecode(code, 'LOAD_CONST', '\uffff')
230 self.assertNotInBytecode(code,'BINARY_SUBSCR')
231
232 # With PEP 393, non-BMP char get optimized
233 code = compile('"\U00012345"[0]', '', 'single')
234 self.assertInBytecode(code, 'LOAD_CONST', '\U00012345')
235 self.assertNotInBytecode(code, 'BINARY_SUBSCR')
Ezio Melotti2df6a932011-04-15 16:38:34 +0300236
237 # invalid code doesn't get optimized
238 # out of range
Nick Coghland6245172013-05-07 00:03:00 +1000239 code = compile('"fuu"[10]', '', 'single')
240 self.assertInBytecode(code, 'BINARY_SUBSCR')
Ezio Melotti2df6a932011-04-15 16:38:34 +0300241
Raymond Hettingerafd842f2005-02-20 12:46:54 +0000242 def test_folding_of_unaryops_on_constants(self):
243 for line, elem in (
Nick Coghland6245172013-05-07 00:03:00 +1000244 ('-0.5', -0.5), # unary negative
245 ('-0.0', -0.0), # -0.0
246 ('-(1.0-1.0)', -0.0), # -0.0 after folding
247 ('-0', 0), # -0
248 ('~-2', 1), # unary invert
249 ('+1', 1), # unary positive
Raymond Hettingerafd842f2005-02-20 12:46:54 +0000250 ):
Nick Coghland6245172013-05-07 00:03:00 +1000251 code = compile(line, '', 'single')
252 self.assertInBytecode(code, 'LOAD_CONST', elem)
253 for instr in dis.get_instructions(code):
254 self.assertFalse(instr.opname.startswith('UNARY_'))
Raymond Hettingerafd842f2005-02-20 12:46:54 +0000255
Mark Dickinson7c9e8032011-03-23 17:59:37 +0000256 # Check that -0.0 works after marshaling
257 def negzero():
258 return -(1.0-1.0)
259
Nick Coghland6245172013-05-07 00:03:00 +1000260 for instr in dis.get_instructions(code):
261 self.assertFalse(instr.opname.startswith('UNARY_'))
Mark Dickinson7c9e8032011-03-23 17:59:37 +0000262
Raymond Hettingerafd842f2005-02-20 12:46:54 +0000263 # Verify that unfoldables are skipped
Nick Coghland6245172013-05-07 00:03:00 +1000264 for line, elem, opname in (
265 ('-"abc"', 'abc', 'UNARY_NEGATIVE'),
266 ('~"abc"', 'abc', 'UNARY_INVERT'),
Raymond Hettingerafd842f2005-02-20 12:46:54 +0000267 ):
Nick Coghland6245172013-05-07 00:03:00 +1000268 code = compile(line, '', 'single')
269 self.assertInBytecode(code, 'LOAD_CONST', elem)
270 self.assertInBytecode(code, opname)
Raymond Hettingerafd842f2005-02-20 12:46:54 +0000271
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +0000272 def test_elim_extra_return(self):
273 # RETURN LOAD_CONST None RETURN --> RETURN
274 def f(x):
275 return x
Nick Coghland6245172013-05-07 00:03:00 +1000276 self.assertNotInBytecode(f, 'LOAD_CONST', None)
277 returns = [instr for instr in dis.get_instructions(f)
278 if instr.opname == 'RETURN_VALUE']
279 self.assertEqual(len(returns), 1)
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +0000280
Thomas Wouters89f507f2006-12-13 04:49:30 +0000281 def test_elim_jump_to_return(self):
282 # JUMP_FORWARD to RETURN --> RETURN
283 def f(cond, true_value, false_value):
Miss Islington (bot)5282b3b2019-06-13 11:35:40 -0700284 # Intentionally use two-line expression to test issue37213.
285 return (true_value if cond
286 else false_value)
287 self.check_jump_targets(f)
Nick Coghland6245172013-05-07 00:03:00 +1000288 self.assertNotInBytecode(f, 'JUMP_FORWARD')
289 self.assertNotInBytecode(f, 'JUMP_ABSOLUTE')
290 returns = [instr for instr in dis.get_instructions(f)
291 if instr.opname == 'RETURN_VALUE']
292 self.assertEqual(len(returns), 2)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000293
Miss Islington (bot)5282b3b2019-06-13 11:35:40 -0700294 def test_elim_jump_to_uncond_jump(self):
295 # POP_JUMP_IF_FALSE to JUMP_FORWARD --> POP_JUMP_IF_FALSE to non-jump
296 def f():
297 if a:
298 # Intentionally use two-line expression to test issue37213.
299 if (c
300 or d):
301 foo()
302 else:
303 baz()
304 self.check_jump_targets(f)
305
306 def test_elim_jump_to_uncond_jump2(self):
307 # POP_JUMP_IF_FALSE to JUMP_ABSOLUTE --> POP_JUMP_IF_FALSE to non-jump
308 def f():
309 while a:
310 # Intentionally use two-line expression to test issue37213.
311 if (c
312 or d):
313 a = foo()
314 self.check_jump_targets(f)
315
316 def test_elim_jump_to_uncond_jump3(self):
317 # Intentionally use two-line expressions to test issue37213.
318 # JUMP_IF_FALSE_OR_POP to JUMP_IF_FALSE_OR_POP --> JUMP_IF_FALSE_OR_POP to non-jump
319 def f(a, b, c):
320 return ((a and b)
321 and c)
322 self.check_jump_targets(f)
323 self.assertEqual(count_instr_recursively(f, 'JUMP_IF_FALSE_OR_POP'), 2)
324 # JUMP_IF_TRUE_OR_POP to JUMP_IF_TRUE_OR_POP --> JUMP_IF_TRUE_OR_POP to non-jump
325 def f(a, b, c):
326 return ((a or b)
327 or c)
328 self.check_jump_targets(f)
329 self.assertEqual(count_instr_recursively(f, 'JUMP_IF_TRUE_OR_POP'), 2)
330 # JUMP_IF_FALSE_OR_POP to JUMP_IF_TRUE_OR_POP --> POP_JUMP_IF_FALSE to non-jump
331 def f(a, b, c):
332 return ((a and b)
333 or c)
334 self.check_jump_targets(f)
335 self.assertNotInBytecode(f, 'JUMP_IF_FALSE_OR_POP')
336 self.assertInBytecode(f, 'JUMP_IF_TRUE_OR_POP')
337 self.assertInBytecode(f, 'POP_JUMP_IF_FALSE')
338 # JUMP_IF_TRUE_OR_POP to JUMP_IF_FALSE_OR_POP --> POP_JUMP_IF_TRUE to non-jump
339 def f(a, b, c):
340 return ((a or b)
341 and c)
342 self.check_jump_targets(f)
343 self.assertNotInBytecode(f, 'JUMP_IF_TRUE_OR_POP')
344 self.assertInBytecode(f, 'JUMP_IF_FALSE_OR_POP')
345 self.assertInBytecode(f, 'POP_JUMP_IF_TRUE')
346
Thomas Wouters89f507f2006-12-13 04:49:30 +0000347 def test_elim_jump_after_return1(self):
348 # Eliminate dead code: jumps immediately after returns can't be reached
349 def f(cond1, cond2):
350 if cond1: return 1
351 if cond2: return 2
352 while 1:
353 return 3
354 while 1:
355 if cond1: return 4
356 return 5
357 return 6
Nick Coghland6245172013-05-07 00:03:00 +1000358 self.assertNotInBytecode(f, 'JUMP_FORWARD')
359 self.assertNotInBytecode(f, 'JUMP_ABSOLUTE')
360 returns = [instr for instr in dis.get_instructions(f)
361 if instr.opname == 'RETURN_VALUE']
Serhiy Storchaka520b7ae2018-02-22 23:33:30 +0200362 self.assertLessEqual(len(returns), 6)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000363
364 def test_elim_jump_after_return2(self):
365 # Eliminate dead code: jumps immediately after returns can't be reached
366 def f(cond1, cond2):
367 while 1:
368 if cond1: return 4
Nick Coghland6245172013-05-07 00:03:00 +1000369 self.assertNotInBytecode(f, 'JUMP_FORWARD')
Thomas Wouters89f507f2006-12-13 04:49:30 +0000370 # There should be one jump for the while loop.
Nick Coghland6245172013-05-07 00:03:00 +1000371 returns = [instr for instr in dis.get_instructions(f)
372 if instr.opname == 'JUMP_ABSOLUTE']
373 self.assertEqual(len(returns), 1)
374 returns = [instr for instr in dis.get_instructions(f)
375 if instr.opname == 'RETURN_VALUE']
Serhiy Storchaka520b7ae2018-02-22 23:33:30 +0200376 self.assertLessEqual(len(returns), 2)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000377
Guido van Rossum0240b922007-02-26 21:23:50 +0000378 def test_make_function_doesnt_bail(self):
379 def f():
Guido van Rossumd8faa362007-04-27 19:54:29 +0000380 def g()->1+1:
Guido van Rossum0240b922007-02-26 21:23:50 +0000381 pass
382 return g
Nick Coghland6245172013-05-07 00:03:00 +1000383 self.assertNotInBytecode(f, 'BINARY_ADD')
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +0000384
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100385 def test_constant_folding(self):
386 # Issue #11244: aggressive constant folding.
387 exprs = [
Nick Coghland6245172013-05-07 00:03:00 +1000388 '3 * -5',
389 '-3 * 5',
390 '2 * (3 * 4)',
391 '(2 * 3) * 4',
392 '(-1, 2, 3)',
393 '(1, -2, 3)',
394 '(1, 2, -3)',
395 '(1, 2, -3) * 6',
396 'lambda x: x in {(3 * -5) + (-1 - 6), (1, -2, 3) * 2, None}',
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100397 ]
398 for e in exprs:
Nick Coghland6245172013-05-07 00:03:00 +1000399 code = compile(e, '', 'single')
400 for instr in dis.get_instructions(code):
401 self.assertFalse(instr.opname.startswith('UNARY_'))
402 self.assertFalse(instr.opname.startswith('BINARY_'))
403 self.assertFalse(instr.opname.startswith('BUILD_'))
404
Serhiy Storchaka3f7e9aa2018-03-11 10:54:47 +0200405 def test_in_literal_list(self):
406 def containtest():
407 return x in [a, b]
408 self.assertEqual(count_instr_recursively(containtest, 'BUILD_LIST'), 0)
409
410 def test_iterate_literal_list(self):
411 def forloop():
412 for x in [a, b]:
413 pass
414 self.assertEqual(count_instr_recursively(forloop, 'BUILD_LIST'), 0)
415
Miss Islington (bot)7cd581a2019-06-13 23:13:24 -0700416 def test_condition_with_binop_with_bools(self):
417 def f():
418 if True or False:
419 return 1
420 return 0
421 self.assertEqual(f(), 1)
422
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100423
Raymond Hettinger0661e912011-03-15 15:03:36 -0700424class TestBuglets(unittest.TestCase):
425
Raymond Hettinger5bd75b82011-03-15 15:07:38 -0700426 def test_bug_11510(self):
427 # folded constant set optimization was commingled with the tuple
428 # unpacking optimization which would fail if the set had duplicate
429 # elements so that the set length was unexpected
430 def f():
431 x, y = {1, 1}
432 return x, y
433 with self.assertRaises(ValueError):
434 f()
Raymond Hettinger0661e912011-03-15 15:03:36 -0700435
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +0000436
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +0000437if __name__ == "__main__":
Zachary Ware38c707e2015-04-13 15:00:43 -0500438 unittest.main()