X Tutup
Skip to content

Commit a65a8bb

Browse files
committed
Fix 3.2 for/if loopback bug
problem was handling in Python 3.2 for ... if ... else: .... jump for come from if jump for In later Python 3's a "come from" is removed. Also, start to DRY parser{,2,3} grammar rules.
1 parent 4a79082 commit a65a8bb

File tree

6 files changed

+60
-40
lines changed

6 files changed

+60
-40
lines changed
513 Bytes
Binary file not shown.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# In Python 3.2 JUMP_ABSOLUTE's (which can
2+
# turn into COME_FROM's) are not optimized as
3+
# they are in later Python's.
4+
#
5+
# So an if statement can jump to the end of a for loop
6+
# which in turn jump's back to the beginning of that loop.
7+
#
8+
# Should handle in Python 3.2
9+
#
10+
# 98 JUMP_BACK '16' statement after: names.append(name) to loop head
11+
# 101_0 COME_FROM '50' statement: if name == ...to fictional "end if"
12+
# 101 JUMP_BACK '16' jump as before to loop head
13+
14+
def _slotnames(cls):
15+
names = []
16+
for c in cls.__mro__:
17+
if "__slots__" in c.__dict__:
18+
slots = c.__dict__['__slots__']
19+
for name in slots:
20+
if name == "__dict__":
21+
continue
22+
else:
23+
names.append(name) # 3.2 bug here jumping to outer for

uncompyle6/parser.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,27 @@ def p_assign(self, args):
161161
assign3 ::= expr expr expr ROT_THREE ROT_TWO designator designator designator
162162
'''
163163

164+
def p_forstmt(self, args):
165+
"""
166+
_for ::= GET_ITER FOR_ITER
167+
_for ::= LOAD_CONST FOR_LOOP
168+
169+
for_block ::= l_stmts_opt JUMP_BACK
170+
for_block ::= return_stmts _come_from
171+
172+
forstmt ::= SETUP_LOOP expr _for designator
173+
for_block POP_BLOCK _come_from
174+
175+
forelsestmt ::= SETUP_LOOP expr _for designator
176+
for_block POP_BLOCK else_suite COME_FROM
177+
178+
forelselaststmt ::= SETUP_LOOP expr _for designator
179+
for_block POP_BLOCK else_suitec COME_FROM
180+
181+
forelselaststmtl ::= SETUP_LOOP expr _for designator
182+
for_block POP_BLOCK else_suitel COME_FROM
183+
"""
184+
164185
def p_import20(self, args):
165186
'''
166187
stmt ::= importstmt

uncompyle6/parsers/parse2.py

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -344,25 +344,6 @@ def p_grammar(self, args):
344344
l_stmts_opt JUMP_BACK
345345
POP_BLOCK
346346
else_suitec COME_FROM
347-
348-
_for ::= GET_ITER FOR_ITER
349-
_for ::= LOAD_CONST FOR_LOOP
350-
351-
for_block ::= l_stmts_opt JUMP_BACK
352-
for_block ::= return_stmts _come_from
353-
354-
forstmt ::= SETUP_LOOP expr _for designator
355-
for_block POP_BLOCK COME_FROM
356-
357-
forelsestmt ::= SETUP_LOOP expr _for designator
358-
for_block POP_BLOCK else_suite COME_FROM
359-
360-
forelselaststmt ::= SETUP_LOOP expr _for designator
361-
for_block POP_BLOCK else_suitec COME_FROM
362-
363-
forelselaststmtl ::= SETUP_LOOP expr _for designator
364-
for_block POP_BLOCK else_suitel COME_FROM
365-
366347
'''
367348

368349
def p_expr2(self, args):

uncompyle6/parsers/parse3.py

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -350,26 +350,21 @@ def p_grammar(self, args):
350350
l_stmts_opt JUMP_BACK
351351
POP_BLOCK
352352
else_suitec COME_FROM
353-
354-
_for ::= GET_ITER FOR_ITER
355-
_for ::= LOAD_CONST FOR_LOOP
356-
357-
for_block ::= l_stmts_opt JUMP_BACK
358-
for_block ::= return_stmts _come_from
359-
360-
forstmt ::= SETUP_LOOP expr _for designator
361-
for_block POP_BLOCK _come_from
362-
363-
forelsestmt ::= SETUP_LOOP expr _for designator
364-
for_block POP_BLOCK else_suite COME_FROM
365-
366-
forelselaststmt ::= SETUP_LOOP expr _for designator
367-
for_block POP_BLOCK else_suitec COME_FROM
368-
369-
forelselaststmtl ::= SETUP_LOOP expr _for designator
370-
for_block POP_BLOCK else_suitel COME_FROM
371353
'''
372354

355+
def p_for3(self, args):
356+
"""
357+
# In Python 3.2 JUMP_ABSOLUTE's (which can
358+
# turn into COME_FROM's) are not optimized as
359+
# they are in later Python's.
360+
#
361+
# So an if statement can jump to the end of a for loop
362+
# which in turn jump's back to the beginning of that loop.
363+
#
364+
# Therefore we allow COME_FROM JUMP_BACK below.
365+
for_block ::= l_stmts_opt COME_FROM JUMP_BACK
366+
"""
367+
373368
def p_genexpr3(self, args):
374369
'''
375370
load_genexpr ::= LOAD_GENEXPR

uncompyle6/scanners/scanner32.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
"""
33
Python 3.2 bytecode scanner/deparser
44
5-
This overlaps Python's 3.2's dis module, but it can be run from
6-
Python 2 and other versions of Python. Also, we save token information
7-
for later use in deparsing.
5+
This overlaps various Python3.2's dis module, but it can be run from
6+
Python versions other than the version running this code. Notably,
7+
run from Python version 2. See doc comments in scanner3.py for more information.
88
"""
99

1010
from __future__ import print_function

0 commit comments

Comments
 (0)
X Tutup