blob: 42224244ef205a36ade45cc427726dc135ef08d0 [file] [log] [blame]
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +00001import dis
2import sys
3from cStringIO import StringIO
4import unittest
5
6def disassemble(func):
7 f = StringIO()
8 tmp = sys.stdout
9 sys.stdout = f
10 dis.dis(func)
11 sys.stdout = tmp
12 result = f.getvalue()
13 f.close()
14 return result
15
16def dis_single(line):
17 return disassemble(compile(line, '', 'single'))
18
19class TestTranforms(unittest.TestCase):
20
21 def test_unot(self):
22 # UNARY_NOT JUMP_IF_FALSE POP_TOP --> JUMP_IF_TRUE POP_TOP'
23 def unot(x):
24 if not x == 2:
25 del x
26 asm = disassemble(unot)
27 for elem in ('UNARY_NOT', 'JUMP_IF_FALSE'):
28 self.assert_(elem not in asm)
29 for elem in ('JUMP_IF_TRUE', 'POP_TOP'):
30 self.assert_(elem in asm)
31
32 def test_elim_inversion_of_is_or_in(self):
33 for line, elem in (
34 ('not a is b', '(is not)',),
35 ('not a in b', '(not in)',),
36 ('not a is not b', '(is)',),
37 ('not a not in b', '(in)',),
38 ):
39 asm = dis_single(line)
40 self.assert_(elem in asm)
41
42 def test_none_as_constant(self):
43 # LOAD_GLOBAL None --> LOAD_CONST None
44 def f(x):
Tim Peters66cb0182004-08-26 05:23:19 +000045 None
46 return x
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +000047 asm = disassemble(f)
48 for elem in ('LOAD_GLOBAL',):
49 self.assert_(elem not in asm)
50 for elem in ('LOAD_CONST', '(None)'):
51 self.assert_(elem in asm)
52
53 def test_while_one(self):
54 # Skip over: LOAD_CONST trueconst JUMP_IF_FALSE xx POP_TOP
55 def f():
Tim Peters66cb0182004-08-26 05:23:19 +000056 while 1:
57 pass
58 return list
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +000059 asm = disassemble(f)
60 for elem in ('LOAD_CONST', 'JUMP_IF_FALSE'):
61 self.assert_(elem not in asm)
62 for elem in ('JUMP_ABSOLUTE',):
63 self.assert_(elem in asm)
64
65 def test_pack_unpack(self):
66 for line, elem in (
Raymond Hettinger2c31a052004-09-22 18:44:21 +000067 ('a, = a,', 'LOAD_CONST',),
68 ('a, b = a, b', 'ROT_TWO',),
69 ('a, b, c = a, b, c', 'ROT_THREE',),
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +000070 ):
71 asm = dis_single(line)
72 self.assert_(elem in asm)
73 self.assert_('BUILD_TUPLE' not in asm)
74 self.assert_('UNPACK_TUPLE' not in asm)
75
Raymond Hettinger2c31a052004-09-22 18:44:21 +000076 def test_folding_of_tuples_of_constants(self):
77 for line, elem in (
Raymond Hettinger5dec0962004-11-02 04:20:10 +000078 ('a = 1,2,3', '((1, 2, 3))'),
79 ('("a","b","c")', "(('a', 'b', 'c'))"),
80 ('a,b,c = 1,2,3', '((1, 2, 3))'),
81 ('(None, 1, None)', '((None, 1, None))'),
82 ('((1, 2), 3, 4)', '(((1, 2), 3, 4))'),
Raymond Hettinger2c31a052004-09-22 18:44:21 +000083 ):
84 asm = dis_single(line)
85 self.assert_(elem in asm)
86 self.assert_('BUILD_TUPLE' not in asm)
87
Raymond Hettinger23109ef2004-10-26 08:59:14 +000088 # Bug 1053819: Tuple of constants misidentified when presented with:
89 # . . . opcode_with_arg 100 unary_opcode BUILD_TUPLE 1 . . .
90 # The following would segfault upon compilation
91 def crater():
92 (~[
93 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
94 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
95 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
96 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
97 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
98 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
99 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
100 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
101 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
102 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
103 ],)
104
Raymond Hettingerc34f8672005-01-02 06:17:33 +0000105 def test_folding_of_binops_on_constants(self):
106 for line, elem in (
107 ('a = 2+3+4', '(9)'), # chained fold
108 ('"@"*4', "('@@@@')"), # check string ops
109 ('a="abc" + "def"', "('abcdef')"), # check string ops
110 ('a = 3**4', '(81)'), # binary power
111 ('a = 3*4', '(12)'), # binary multiply
Raymond Hettingerc34f8672005-01-02 06:17:33 +0000112 ('a = 13//4', '(3)'), # binary floor divide
113 ('a = 14%4', '(2)'), # binary modulo
114 ('a = 2+3', '(5)'), # binary add
115 ('a = 13-4', '(9)'), # binary subtract
116 ('a = (12,13)[1]', '(13)'), # binary subscr
117 ('a = 13 << 2', '(52)'), # binary lshift
118 ('a = 13 >> 2', '(3)'), # binary rshift
119 ('a = 13 & 7', '(5)'), # binary and
120 ('a = 13 ^ 7', '(10)'), # binary xor
121 ('a = 13 | 7', '(15)'), # binary or
122 ):
123 asm = dis_single(line)
124 self.assert_(elem in asm, asm)
125 self.assert_('BINARY_' not in asm)
126
127 # Verify that unfoldables are skipped
128 asm = dis_single('a=2+"b"')
129 self.assert_('(2)' in asm)
130 self.assert_("('b')" in asm)
131
Raymond Hettingerfd2d1f72004-08-23 23:37:48 +0000132 def test_elim_extra_return(self):
133 # RETURN LOAD_CONST None RETURN --> RETURN
134 def f(x):
135 return x
136 asm = disassemble(f)
137 self.assert_('LOAD_CONST' not in asm)
138 self.assert_('(None)' not in asm)
139 self.assertEqual(asm.split().count('RETURN_VALUE'), 1)
140
141
142
143def test_main(verbose=None):
144 import sys
145 from test import test_support
146 test_classes = (TestTranforms,)
147 test_support.run_unittest(*test_classes)
148
149 # verify reference counting
150 if verbose and hasattr(sys, "gettotalrefcount"):
151 import gc
152 counts = [None] * 5
153 for i in xrange(len(counts)):
154 test_support.run_unittest(*test_classes)
155 gc.collect()
156 counts[i] = sys.gettotalrefcount()
157 print counts
158
159if __name__ == "__main__":
160 test_main(verbose=True)