blob: 5d00240e2595a8c8088ad187f1b15c2ac5181d21 [file] [log] [blame]
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +00001import dis
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +00002import unittest
Pablo Galindo3498c642019-06-13 19:16:22 +01003import types
4import textwrap
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +00005
Nick Coghland6245172013-05-07 00:03:00 +10006from test.bytecode_helper import BytecodeTestCase
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +00007
Serhiy Storchaka3f7e9aa2018-03-11 10:54:47 +02008def count_instr_recursively(f, opname):
9 count = 0
10 for instr in dis.get_instructions(f):
11 if instr.opname == opname:
12 count += 1
13 if hasattr(f, '__code__'):
14 f = f.__code__
15 for c in f.co_consts:
16 if hasattr(c, 'co_code'):
17 count += count_instr_recursively(c, opname)
18 return count
19
20
Nick Coghland6245172013-05-07 00:03:00 +100021class TestTranforms(BytecodeTestCase):
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +000022
Pablo Galindo3498c642019-06-13 19:16:22 +010023 def check_jump_targets(self, code):
24 instructions = list(dis.get_instructions(code))
25 targets = {instr.offset: instr for instr in instructions}
26 for instr in instructions:
27 if 'JUMP_' not in instr.opname:
28 continue
29 tgt = targets[instr.argval]
30 # jump to unconditional jump
31 if tgt.opname in ('JUMP_ABSOLUTE', 'JUMP_FORWARD'):
32 self.fail(f'{instr.opname} at {instr.offset} '
33 f'jumps to {tgt.opname} at {tgt.offset}')
34 # unconditional jump to RETURN_VALUE
35 if (instr.opname in ('JUMP_ABSOLUTE', 'JUMP_FORWARD') and
36 tgt.opname == 'RETURN_VALUE'):
37 self.fail(f'{instr.opname} at {instr.offset} '
38 f'jumps to {tgt.opname} at {tgt.offset}')
39 # JUMP_IF_*_OR_POP jump to conditional jump
40 if '_OR_POP' in instr.opname and 'JUMP_IF_' in tgt.opname:
41 self.fail(f'{instr.opname} at {instr.offset} '
42 f'jumps to {tgt.opname} at {tgt.offset}')
43
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +000044 def test_unot(self):
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +000045 # UNARY_NOT POP_JUMP_IF_FALSE --> POP_JUMP_IF_TRUE'
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +000046 def unot(x):
47 if not x == 2:
48 del x
Nick Coghland6245172013-05-07 00:03:00 +100049 self.assertNotInBytecode(unot, 'UNARY_NOT')
50 self.assertNotInBytecode(unot, 'POP_JUMP_IF_FALSE')
51 self.assertInBytecode(unot, 'POP_JUMP_IF_TRUE')
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +000052
53 def test_elim_inversion_of_is_or_in(self):
Nick Coghland6245172013-05-07 00:03:00 +100054 for line, cmp_op in (
55 ('not a is b', 'is not',),
56 ('not a in b', 'not in',),
57 ('not a is not b', 'is',),
58 ('not a not in b', 'in',),
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +000059 ):
Nick Coghland6245172013-05-07 00:03:00 +100060 code = compile(line, '', 'single')
61 self.assertInBytecode(code, 'COMPARE_OP', cmp_op)
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +000062
Guido van Rossumcd16bf62007-06-13 18:07:49 +000063 def test_global_as_constant(self):
64 # LOAD_GLOBAL None/True/False --> LOAD_CONST None/True/False
Victor Stinner51d8c522016-02-08 17:57:02 +010065 def f():
66 x = None
67 x = None
Tim Peters66cb0182004-08-26 05:23:19 +000068 return x
Victor Stinner51d8c522016-02-08 17:57:02 +010069 def g():
70 x = True
Guido van Rossumcd16bf62007-06-13 18:07:49 +000071 return x
Victor Stinner51d8c522016-02-08 17:57:02 +010072 def h():
73 x = False
Guido van Rossumcd16bf62007-06-13 18:07:49 +000074 return x
Victor Stinner51d8c522016-02-08 17:57:02 +010075
Nick Coghland6245172013-05-07 00:03:00 +100076 for func, elem in ((f, None), (g, True), (h, False)):
77 self.assertNotInBytecode(func, 'LOAD_GLOBAL')
78 self.assertInBytecode(func, 'LOAD_CONST', elem)
Victor Stinner51d8c522016-02-08 17:57:02 +010079
Guido van Rossumd8faa362007-04-27 19:54:29 +000080 def f():
81 'Adding a docstring made this test fail in Py2.5.0'
82 return None
Victor Stinner51d8c522016-02-08 17:57:02 +010083
Nick Coghland6245172013-05-07 00:03:00 +100084 self.assertNotInBytecode(f, 'LOAD_GLOBAL')
85 self.assertInBytecode(f, 'LOAD_CONST', None)
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +000086
87 def test_while_one(self):
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +000088 # Skip over: LOAD_CONST trueconst POP_JUMP_IF_FALSE xx
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +000089 def f():
Tim Peters66cb0182004-08-26 05:23:19 +000090 while 1:
91 pass
92 return list
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +000093 for elem in ('LOAD_CONST', 'POP_JUMP_IF_FALSE'):
Nick Coghland6245172013-05-07 00:03:00 +100094 self.assertNotInBytecode(f, elem)
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +000095 for elem in ('JUMP_ABSOLUTE',):
Nick Coghland6245172013-05-07 00:03:00 +100096 self.assertInBytecode(f, elem)
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +000097
98 def test_pack_unpack(self):
99 for line, elem in (
Raymond Hettinger2c31a052004-09-22 18:44:21 +0000100 ('a, = a,', 'LOAD_CONST',),
101 ('a, b = a, b', 'ROT_TWO',),
102 ('a, b, c = a, b, c', 'ROT_THREE',),
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +0000103 ):
Nick Coghland6245172013-05-07 00:03:00 +1000104 code = compile(line,'','single')
105 self.assertInBytecode(code, elem)
106 self.assertNotInBytecode(code, 'BUILD_TUPLE')
107 self.assertNotInBytecode(code, 'UNPACK_TUPLE')
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +0000108
Raymond Hettinger2c31a052004-09-22 18:44:21 +0000109 def test_folding_of_tuples_of_constants(self):
110 for line, elem in (
Nick Coghland6245172013-05-07 00:03:00 +1000111 ('a = 1,2,3', (1, 2, 3)),
112 ('("a","b","c")', ('a', 'b', 'c')),
113 ('a,b,c = 1,2,3', (1, 2, 3)),
114 ('(None, 1, None)', (None, 1, None)),
115 ('((1, 2), 3, 4)', ((1, 2), 3, 4)),
Raymond Hettinger2c31a052004-09-22 18:44:21 +0000116 ):
Nick Coghland6245172013-05-07 00:03:00 +1000117 code = compile(line,'','single')
118 self.assertInBytecode(code, 'LOAD_CONST', elem)
119 self.assertNotInBytecode(code, 'BUILD_TUPLE')
Raymond Hettinger2c31a052004-09-22 18:44:21 +0000120
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100121 # Long tuples should be folded too.
Nick Coghland6245172013-05-07 00:03:00 +1000122 code = compile(repr(tuple(range(10000))),'','single')
123 self.assertNotInBytecode(code, 'BUILD_TUPLE')
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100124 # One LOAD_CONST for the tuple, one for the None return value
Nick Coghland6245172013-05-07 00:03:00 +1000125 load_consts = [instr for instr in dis.get_instructions(code)
126 if instr.opname == 'LOAD_CONST']
127 self.assertEqual(len(load_consts), 2)
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100128
Raymond Hettinger23109ef2004-10-26 08:59:14 +0000129 # Bug 1053819: Tuple of constants misidentified when presented with:
130 # . . . opcode_with_arg 100 unary_opcode BUILD_TUPLE 1 . . .
131 # The following would segfault upon compilation
132 def crater():
133 (~[
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 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
144 ],)
145
Antoine Pitroub7fbcd32010-01-16 18:37:38 +0000146 def test_folding_of_lists_of_constants(self):
147 for line, elem in (
148 # in/not in constants with BUILD_LIST should be folded to a tuple:
Nick Coghland6245172013-05-07 00:03:00 +1000149 ('a in [1,2,3]', (1, 2, 3)),
150 ('a not in ["a","b","c"]', ('a', 'b', 'c')),
151 ('a in [None, 1, None]', (None, 1, None)),
152 ('a not in [(1, 2), 3, 4]', ((1, 2), 3, 4)),
Antoine Pitroub7fbcd32010-01-16 18:37:38 +0000153 ):
Nick Coghland6245172013-05-07 00:03:00 +1000154 code = compile(line, '', 'single')
155 self.assertInBytecode(code, 'LOAD_CONST', elem)
156 self.assertNotInBytecode(code, 'BUILD_LIST')
Antoine Pitroub7fbcd32010-01-16 18:37:38 +0000157
158 def test_folding_of_sets_of_constants(self):
159 for line, elem in (
160 # in/not in constants with BUILD_SET should be folded to a frozenset:
161 ('a in {1,2,3}', frozenset({1, 2, 3})),
162 ('a not in {"a","b","c"}', frozenset({'a', 'c', 'b'})),
163 ('a in {None, 1, None}', frozenset({1, None})),
164 ('a not in {(1, 2), 3, 4}', frozenset({(1, 2), 3, 4})),
165 ('a in {1, 2, 3, 3, 2, 1}', frozenset({1, 2, 3})),
166 ):
Nick Coghland6245172013-05-07 00:03:00 +1000167 code = compile(line, '', 'single')
168 self.assertNotInBytecode(code, 'BUILD_SET')
169 self.assertInBytecode(code, 'LOAD_CONST', elem)
Antoine Pitroub7fbcd32010-01-16 18:37:38 +0000170
171 # Ensure that the resulting code actually works:
172 def f(a):
173 return a in {1, 2, 3}
174
175 def g(a):
176 return a not in {1, 2, 3}
177
178 self.assertTrue(f(3))
179 self.assertTrue(not f(4))
180
181 self.assertTrue(not g(3))
182 self.assertTrue(g(4))
183
184
Raymond Hettingerc34f8672005-01-02 06:17:33 +0000185 def test_folding_of_binops_on_constants(self):
186 for line, elem in (
Nick Coghland6245172013-05-07 00:03:00 +1000187 ('a = 2+3+4', 9), # chained fold
188 ('"@"*4', '@@@@'), # check string ops
189 ('a="abc" + "def"', 'abcdef'), # check string ops
190 ('a = 3**4', 81), # binary power
191 ('a = 3*4', 12), # binary multiply
192 ('a = 13//4', 3), # binary floor divide
193 ('a = 14%4', 2), # binary modulo
194 ('a = 2+3', 5), # binary add
195 ('a = 13-4', 9), # binary subtract
196 ('a = (12,13)[1]', 13), # binary subscr
197 ('a = 13 << 2', 52), # binary lshift
198 ('a = 13 >> 2', 3), # binary rshift
199 ('a = 13 & 7', 5), # binary and
200 ('a = 13 ^ 7', 10), # binary xor
201 ('a = 13 | 7', 15), # binary or
Raymond Hettingerc34f8672005-01-02 06:17:33 +0000202 ):
Nick Coghland6245172013-05-07 00:03:00 +1000203 code = compile(line, '', 'single')
204 self.assertInBytecode(code, 'LOAD_CONST', elem)
205 for instr in dis.get_instructions(code):
206 self.assertFalse(instr.opname.startswith('BINARY_'))
Raymond Hettingerc34f8672005-01-02 06:17:33 +0000207
208 # Verify that unfoldables are skipped
Nick Coghland6245172013-05-07 00:03:00 +1000209 code = compile('a=2+"b"', '', 'single')
210 self.assertInBytecode(code, 'LOAD_CONST', 2)
211 self.assertInBytecode(code, 'LOAD_CONST', 'b')
Raymond Hettingerc34f8672005-01-02 06:17:33 +0000212
Raymond Hettinger9feb2672005-01-26 12:50:05 +0000213 # Verify that large sequences do not result from folding
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200214 code = compile('a="x"*10000', '', 'single')
215 self.assertInBytecode(code, 'LOAD_CONST', 10000)
216 self.assertNotIn("x"*10000, code.co_consts)
217 code = compile('a=1<<1000', '', 'single')
Nick Coghland6245172013-05-07 00:03:00 +1000218 self.assertInBytecode(code, 'LOAD_CONST', 1000)
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200219 self.assertNotIn(1<<1000, code.co_consts)
220 code = compile('a=2**1000', '', 'single')
221 self.assertInBytecode(code, 'LOAD_CONST', 1000)
222 self.assertNotIn(2**1000, code.co_consts)
Raymond Hettinger9feb2672005-01-26 12:50:05 +0000223
Ezio Melotti2df6a932011-04-15 16:38:34 +0300224 def test_binary_subscr_on_unicode(self):
225 # valid code get optimized
Nick Coghland6245172013-05-07 00:03:00 +1000226 code = compile('"foo"[0]', '', 'single')
227 self.assertInBytecode(code, 'LOAD_CONST', 'f')
228 self.assertNotInBytecode(code, 'BINARY_SUBSCR')
229 code = compile('"\u0061\uffff"[1]', '', 'single')
230 self.assertInBytecode(code, 'LOAD_CONST', '\uffff')
231 self.assertNotInBytecode(code,'BINARY_SUBSCR')
232
233 # With PEP 393, non-BMP char get optimized
234 code = compile('"\U00012345"[0]', '', 'single')
235 self.assertInBytecode(code, 'LOAD_CONST', '\U00012345')
236 self.assertNotInBytecode(code, 'BINARY_SUBSCR')
Ezio Melotti2df6a932011-04-15 16:38:34 +0300237
238 # invalid code doesn't get optimized
239 # out of range
Nick Coghland6245172013-05-07 00:03:00 +1000240 code = compile('"fuu"[10]', '', 'single')
241 self.assertInBytecode(code, 'BINARY_SUBSCR')
Ezio Melotti2df6a932011-04-15 16:38:34 +0300242
Raymond Hettingerafd842f2005-02-20 12:46:54 +0000243 def test_folding_of_unaryops_on_constants(self):
244 for line, elem in (
Nick Coghland6245172013-05-07 00:03:00 +1000245 ('-0.5', -0.5), # unary negative
246 ('-0.0', -0.0), # -0.0
247 ('-(1.0-1.0)', -0.0), # -0.0 after folding
248 ('-0', 0), # -0
249 ('~-2', 1), # unary invert
250 ('+1', 1), # unary positive
Raymond Hettingerafd842f2005-02-20 12:46:54 +0000251 ):
Nick Coghland6245172013-05-07 00:03:00 +1000252 code = compile(line, '', 'single')
253 self.assertInBytecode(code, 'LOAD_CONST', elem)
254 for instr in dis.get_instructions(code):
255 self.assertFalse(instr.opname.startswith('UNARY_'))
Raymond Hettingerafd842f2005-02-20 12:46:54 +0000256
Mark Dickinson7c9e8032011-03-23 17:59:37 +0000257 # Check that -0.0 works after marshaling
258 def negzero():
259 return -(1.0-1.0)
260
Nick Coghland6245172013-05-07 00:03:00 +1000261 for instr in dis.get_instructions(code):
262 self.assertFalse(instr.opname.startswith('UNARY_'))
Mark Dickinson7c9e8032011-03-23 17:59:37 +0000263
Raymond Hettingerafd842f2005-02-20 12:46:54 +0000264 # Verify that unfoldables are skipped
Nick Coghland6245172013-05-07 00:03:00 +1000265 for line, elem, opname in (
266 ('-"abc"', 'abc', 'UNARY_NEGATIVE'),
267 ('~"abc"', 'abc', 'UNARY_INVERT'),
Raymond Hettingerafd842f2005-02-20 12:46:54 +0000268 ):
Nick Coghland6245172013-05-07 00:03:00 +1000269 code = compile(line, '', 'single')
270 self.assertInBytecode(code, 'LOAD_CONST', elem)
271 self.assertInBytecode(code, opname)
Raymond Hettingerafd842f2005-02-20 12:46:54 +0000272
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +0000273 def test_elim_extra_return(self):
274 # RETURN LOAD_CONST None RETURN --> RETURN
275 def f(x):
276 return x
Nick Coghland6245172013-05-07 00:03:00 +1000277 self.assertNotInBytecode(f, 'LOAD_CONST', None)
278 returns = [instr for instr in dis.get_instructions(f)
279 if instr.opname == 'RETURN_VALUE']
280 self.assertEqual(len(returns), 1)
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +0000281
Thomas Wouters89f507f2006-12-13 04:49:30 +0000282 def test_elim_jump_to_return(self):
283 # JUMP_FORWARD to RETURN --> RETURN
284 def f(cond, true_value, false_value):
Pablo Galindo3498c642019-06-13 19:16:22 +0100285 # Intentionally use two-line expression to test issue37213.
286 return (true_value if cond
287 else false_value)
288 self.check_jump_targets(f)
Nick Coghland6245172013-05-07 00:03:00 +1000289 self.assertNotInBytecode(f, 'JUMP_FORWARD')
290 self.assertNotInBytecode(f, 'JUMP_ABSOLUTE')
291 returns = [instr for instr in dis.get_instructions(f)
292 if instr.opname == 'RETURN_VALUE']
293 self.assertEqual(len(returns), 2)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000294
Pablo Galindo3498c642019-06-13 19:16:22 +0100295 def test_elim_jump_to_uncond_jump(self):
296 # POP_JUMP_IF_FALSE to JUMP_FORWARD --> POP_JUMP_IF_FALSE to non-jump
297 def f():
298 if a:
299 # Intentionally use two-line expression to test issue37213.
300 if (c
301 or d):
302 foo()
303 else:
304 baz()
305 self.check_jump_targets(f)
306
307 def test_elim_jump_to_uncond_jump2(self):
308 # POP_JUMP_IF_FALSE to JUMP_ABSOLUTE --> POP_JUMP_IF_FALSE to non-jump
309 def f():
310 while a:
311 # Intentionally use two-line expression to test issue37213.
312 if (c
313 or d):
314 a = foo()
315 self.check_jump_targets(f)
316
317 def test_elim_jump_to_uncond_jump3(self):
318 # Intentionally use two-line expressions to test issue37213.
319 # JUMP_IF_FALSE_OR_POP to JUMP_IF_FALSE_OR_POP --> JUMP_IF_FALSE_OR_POP to non-jump
320 def f(a, b, c):
321 return ((a and b)
322 and c)
323 self.check_jump_targets(f)
324 self.assertEqual(count_instr_recursively(f, 'JUMP_IF_FALSE_OR_POP'), 2)
325 # JUMP_IF_TRUE_OR_POP to JUMP_IF_TRUE_OR_POP --> JUMP_IF_TRUE_OR_POP to non-jump
326 def f(a, b, c):
327 return ((a or b)
328 or c)
329 self.check_jump_targets(f)
330 self.assertEqual(count_instr_recursively(f, 'JUMP_IF_TRUE_OR_POP'), 2)
331 # JUMP_IF_FALSE_OR_POP to JUMP_IF_TRUE_OR_POP --> POP_JUMP_IF_FALSE to non-jump
332 def f(a, b, c):
333 return ((a and b)
334 or c)
335 self.check_jump_targets(f)
336 self.assertNotInBytecode(f, 'JUMP_IF_FALSE_OR_POP')
337 self.assertInBytecode(f, 'JUMP_IF_TRUE_OR_POP')
338 self.assertInBytecode(f, 'POP_JUMP_IF_FALSE')
339 # JUMP_IF_TRUE_OR_POP to JUMP_IF_FALSE_OR_POP --> POP_JUMP_IF_TRUE to non-jump
340 def f(a, b, c):
341 return ((a or b)
342 and c)
343 self.check_jump_targets(f)
344 self.assertNotInBytecode(f, 'JUMP_IF_TRUE_OR_POP')
345 self.assertInBytecode(f, 'JUMP_IF_FALSE_OR_POP')
346 self.assertInBytecode(f, 'POP_JUMP_IF_TRUE')
347
Thomas Wouters89f507f2006-12-13 04:49:30 +0000348 def test_elim_jump_after_return1(self):
349 # Eliminate dead code: jumps immediately after returns can't be reached
350 def f(cond1, cond2):
351 if cond1: return 1
352 if cond2: return 2
353 while 1:
354 return 3
355 while 1:
356 if cond1: return 4
357 return 5
358 return 6
Nick Coghland6245172013-05-07 00:03:00 +1000359 self.assertNotInBytecode(f, 'JUMP_FORWARD')
360 self.assertNotInBytecode(f, 'JUMP_ABSOLUTE')
361 returns = [instr for instr in dis.get_instructions(f)
362 if instr.opname == 'RETURN_VALUE']
Serhiy Storchaka520b7ae2018-02-22 23:33:30 +0200363 self.assertLessEqual(len(returns), 6)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000364
365 def test_elim_jump_after_return2(self):
366 # Eliminate dead code: jumps immediately after returns can't be reached
367 def f(cond1, cond2):
368 while 1:
369 if cond1: return 4
Nick Coghland6245172013-05-07 00:03:00 +1000370 self.assertNotInBytecode(f, 'JUMP_FORWARD')
Thomas Wouters89f507f2006-12-13 04:49:30 +0000371 # There should be one jump for the while loop.
Nick Coghland6245172013-05-07 00:03:00 +1000372 returns = [instr for instr in dis.get_instructions(f)
373 if instr.opname == 'JUMP_ABSOLUTE']
374 self.assertEqual(len(returns), 1)
375 returns = [instr for instr in dis.get_instructions(f)
376 if instr.opname == 'RETURN_VALUE']
Serhiy Storchaka520b7ae2018-02-22 23:33:30 +0200377 self.assertLessEqual(len(returns), 2)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000378
Guido van Rossum0240b922007-02-26 21:23:50 +0000379 def test_make_function_doesnt_bail(self):
380 def f():
Guido van Rossumd8faa362007-04-27 19:54:29 +0000381 def g()->1+1:
Guido van Rossum0240b922007-02-26 21:23:50 +0000382 pass
383 return g
Nick Coghland6245172013-05-07 00:03:00 +1000384 self.assertNotInBytecode(f, 'BINARY_ADD')
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +0000385
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100386 def test_constant_folding(self):
387 # Issue #11244: aggressive constant folding.
388 exprs = [
Nick Coghland6245172013-05-07 00:03:00 +1000389 '3 * -5',
390 '-3 * 5',
391 '2 * (3 * 4)',
392 '(2 * 3) * 4',
393 '(-1, 2, 3)',
394 '(1, -2, 3)',
395 '(1, 2, -3)',
396 '(1, 2, -3) * 6',
397 'lambda x: x in {(3 * -5) + (-1 - 6), (1, -2, 3) * 2, None}',
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100398 ]
399 for e in exprs:
Nick Coghland6245172013-05-07 00:03:00 +1000400 code = compile(e, '', 'single')
401 for instr in dis.get_instructions(code):
402 self.assertFalse(instr.opname.startswith('UNARY_'))
403 self.assertFalse(instr.opname.startswith('BINARY_'))
404 self.assertFalse(instr.opname.startswith('BUILD_'))
405
Serhiy Storchaka3f7e9aa2018-03-11 10:54:47 +0200406 def test_in_literal_list(self):
407 def containtest():
408 return x in [a, b]
409 self.assertEqual(count_instr_recursively(containtest, 'BUILD_LIST'), 0)
410
411 def test_iterate_literal_list(self):
412 def forloop():
413 for x in [a, b]:
414 pass
415 self.assertEqual(count_instr_recursively(forloop, 'BUILD_LIST'), 0)
416
Pablo Galindo05f83182019-06-14 06:54:53 +0100417 def test_condition_with_binop_with_bools(self):
418 def f():
419 if True or False:
420 return 1
421 return 0
422 self.assertEqual(f(), 1)
423
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100424
Raymond Hettinger0661e912011-03-15 15:03:36 -0700425class TestBuglets(unittest.TestCase):
426
Raymond Hettinger5bd75b82011-03-15 15:07:38 -0700427 def test_bug_11510(self):
428 # folded constant set optimization was commingled with the tuple
429 # unpacking optimization which would fail if the set had duplicate
430 # elements so that the set length was unexpected
431 def f():
432 x, y = {1, 1}
433 return x, y
434 with self.assertRaises(ValueError):
435 f()
Raymond Hettinger0661e912011-03-15 15:03:36 -0700436
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +0000437
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +0000438if __name__ == "__main__":
Zachary Ware38c707e2015-04-13 15:00:43 -0500439 unittest.main()