You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-04 01:09:52 +08:00
34
test/simple_source/bug34/08_while_if.py
Normal file
34
test/simple_source/bug34/08_while_if.py
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# Testing "while 1" versus "while" handling with if/elif/else's
|
||||||
|
|
||||||
|
def while_test(a, b, c):
|
||||||
|
while a != 2:
|
||||||
|
if b:
|
||||||
|
a += 1
|
||||||
|
elif c:
|
||||||
|
c = 0
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
return a, b, c
|
||||||
|
|
||||||
|
|
||||||
|
def while1_test(a, b, c):
|
||||||
|
while 1:
|
||||||
|
if a != 2:
|
||||||
|
if b:
|
||||||
|
a = 3
|
||||||
|
b = 0
|
||||||
|
elif c:
|
||||||
|
c = 0
|
||||||
|
else:
|
||||||
|
a += b + c
|
||||||
|
break
|
||||||
|
return a, b, c
|
||||||
|
|
||||||
|
|
||||||
|
assert while_test(2, 0, 0) == (2, 0, 0), "no while loops"
|
||||||
|
assert while_test(0, 1, 0) == (2, 1, 0), "two while loops of b branch"
|
||||||
|
assert while_test(0, 0, 0) == (0, 0, 0), "0 while loops, else branch"
|
||||||
|
|
||||||
|
# FIXME: put this in a timer, and try with a=2
|
||||||
|
assert while1_test(4, 1, 1) == (3, 0, 0), "three while1 loops"
|
||||||
|
assert while1_test(4, 0, 0) == (4, 0, 0), " one while1 loop"
|
@@ -153,10 +153,7 @@ class Python3Parser(PythonParser):
|
|||||||
_ifstmts_jump ::= c_stmts_opt COME_FROM
|
_ifstmts_jump ::= c_stmts_opt COME_FROM
|
||||||
|
|
||||||
iflaststmt ::= testexpr c_stmts_opt JUMP_ABSOLUTE
|
iflaststmt ::= testexpr c_stmts_opt JUMP_ABSOLUTE
|
||||||
|
|
||||||
iflaststmtl ::= testexpr c_stmts_opt JUMP_BACK
|
iflaststmtl ::= testexpr c_stmts_opt JUMP_BACK
|
||||||
iflaststmtl ::= testexpr c_stmts_opt JUMP_BACK COME_FROM_LOOP
|
|
||||||
iflaststmtl ::= testexpr c_stmts_opt JUMP_BACK POP_BLOCK
|
|
||||||
|
|
||||||
# These are used to keep parse tree indices the same
|
# These are used to keep parse tree indices the same
|
||||||
jump_forward_else ::= JUMP_FORWARD ELSE
|
jump_forward_else ::= JUMP_FORWARD ELSE
|
||||||
@@ -182,6 +179,8 @@ class Python3Parser(PythonParser):
|
|||||||
|
|
||||||
ifelsestmtl ::= testexpr c_stmts_opt JUMP_BACK else_suitel
|
ifelsestmtl ::= testexpr c_stmts_opt JUMP_BACK else_suitel
|
||||||
ifelsestmtl ::= testexpr c_stmts_opt cf_jump_back else_suitel
|
ifelsestmtl ::= testexpr c_stmts_opt cf_jump_back else_suitel
|
||||||
|
ifelsestmtl ::= testexpr c_stmts_opt continue else_suitel
|
||||||
|
|
||||||
|
|
||||||
cf_jump_back ::= COME_FROM JUMP_BACK
|
cf_jump_back ::= COME_FROM JUMP_BACK
|
||||||
|
|
||||||
@@ -348,6 +347,8 @@ class Python3Parser(PythonParser):
|
|||||||
|
|
||||||
def p_loop_stmt3(self, args):
|
def p_loop_stmt3(self, args):
|
||||||
"""
|
"""
|
||||||
|
stmt ::= whileelsestmt2
|
||||||
|
|
||||||
for ::= SETUP_LOOP expr for_iter store for_block POP_BLOCK
|
for ::= SETUP_LOOP expr for_iter store for_block POP_BLOCK
|
||||||
COME_FROM_LOOP
|
COME_FROM_LOOP
|
||||||
|
|
||||||
@@ -363,6 +364,8 @@ class Python3Parser(PythonParser):
|
|||||||
whilestmt ::= SETUP_LOOP testexpr l_stmts_opt COME_FROM JUMP_BACK POP_BLOCK
|
whilestmt ::= SETUP_LOOP testexpr l_stmts_opt COME_FROM JUMP_BACK POP_BLOCK
|
||||||
COME_FROM_LOOP
|
COME_FROM_LOOP
|
||||||
|
|
||||||
|
whilestmt ::= SETUP_LOOP testexpr l_stmts_opt JUMP_BACK POP_BLOCK JUMP_BACK
|
||||||
|
COME_FROM_LOOP
|
||||||
whilestmt ::= SETUP_LOOP testexpr l_stmts_opt JUMP_BACK POP_BLOCK
|
whilestmt ::= SETUP_LOOP testexpr l_stmts_opt JUMP_BACK POP_BLOCK
|
||||||
COME_FROM_LOOP
|
COME_FROM_LOOP
|
||||||
|
|
||||||
@@ -375,6 +378,9 @@ class Python3Parser(PythonParser):
|
|||||||
whileelsestmt ::= SETUP_LOOP testexpr l_stmts_opt JUMP_BACK POP_BLOCK
|
whileelsestmt ::= SETUP_LOOP testexpr l_stmts_opt JUMP_BACK POP_BLOCK
|
||||||
else_suitel COME_FROM_LOOP
|
else_suitel COME_FROM_LOOP
|
||||||
|
|
||||||
|
whileelsestmt2 ::= SETUP_LOOP testexpr l_stmts_opt JUMP_BACK POP_BLOCK
|
||||||
|
else_suitel JUMP_BACK COME_FROM_LOOP
|
||||||
|
|
||||||
whileTruestmt ::= SETUP_LOOP l_stmts_opt JUMP_BACK POP_BLOCK
|
whileTruestmt ::= SETUP_LOOP l_stmts_opt JUMP_BACK POP_BLOCK
|
||||||
COME_FROM_LOOP
|
COME_FROM_LOOP
|
||||||
|
|
||||||
|
@@ -377,6 +377,7 @@ TABLE_DIRECT = {
|
|||||||
'while1stmt': ( '%|while 1:\n%+%c%-\n\n', 1 ),
|
'while1stmt': ( '%|while 1:\n%+%c%-\n\n', 1 ),
|
||||||
'while1elsestmt': ( '%|while 1:\n%+%c%-%|else:\n%+%c%-\n\n', 1, -2 ),
|
'while1elsestmt': ( '%|while 1:\n%+%c%-%|else:\n%+%c%-\n\n', 1, -2 ),
|
||||||
'whileelsestmt': ( '%|while %c:\n%+%c%-%|else:\n%+%c%-\n\n', 1, 2, -2 ),
|
'whileelsestmt': ( '%|while %c:\n%+%c%-%|else:\n%+%c%-\n\n', 1, 2, -2 ),
|
||||||
|
'whileelsestmt2': ( '%|while %c:\n%+%c%-%|else:\n%+%c%-\n\n', 1, 2, -3 ),
|
||||||
'whileelselaststmt': ( '%|while %c:\n%+%c%-%|else:\n%+%c%-', 1, 2, -2 ),
|
'whileelselaststmt': ( '%|while %c:\n%+%c%-%|else:\n%+%c%-', 1, 2, -2 ),
|
||||||
|
|
||||||
# Note: Python 3.8+ changes this
|
# Note: Python 3.8+ changes this
|
||||||
|
@@ -661,21 +661,33 @@ class SourceWalker(GenericASTTraversal, object):
|
|||||||
if ..
|
if ..
|
||||||
elif ...
|
elif ...
|
||||||
|
|
||||||
|
[else ...]
|
||||||
|
|
||||||
where appropriate
|
where appropriate
|
||||||
"""
|
"""
|
||||||
else_suite = node[3]
|
else_suite = node[3]
|
||||||
|
|
||||||
n = else_suite[0]
|
n = else_suite[0]
|
||||||
|
old_stmts = None
|
||||||
|
|
||||||
if len(n) == 1 == len(n[0]) and n[0] == 'stmt':
|
if len(n) == 1 == len(n[0]) and n[0] == 'stmt':
|
||||||
n = n[0][0]
|
n = n[0][0]
|
||||||
elif n[0].kind in ('lastc_stmt', 'lastl_stmt'):
|
elif n[0].kind in ('lastc_stmt', 'lastl_stmt'):
|
||||||
n = n[0]
|
n = n[0]
|
||||||
if n[0].kind in ('ifstmt', 'iflaststmt', 'ifelsestmtl'):
|
if n[0].kind in ('ifstmt', 'iflaststmt', 'iflaststmtl', 'ifelsestmtl', 'ifelsestmtc'):
|
||||||
# This seems needed for Python 2.5-2.7
|
# This seems needed for Python 2.5-2.7
|
||||||
n = n[0]
|
n = n[0]
|
||||||
pass
|
pass
|
||||||
pass
|
pass
|
||||||
|
elif ( len(n) > 1 and 1 == len(n[0]) and n[0] == 'stmt'
|
||||||
|
and n[1].kind == "stmt" ):
|
||||||
|
else_suite_stmts = n[0]
|
||||||
|
if else_suite_stmts[0].kind not in ('ifstmt', 'iflaststmt', 'ifelsestmtl'):
|
||||||
|
if not preprocess:
|
||||||
|
self.default(node)
|
||||||
|
return
|
||||||
|
old_stmts = n
|
||||||
|
n = else_suite_stmts[0]
|
||||||
else:
|
else:
|
||||||
if not preprocess:
|
if not preprocess:
|
||||||
self.default(node)
|
self.default(node)
|
||||||
@@ -695,6 +707,18 @@ class SourceWalker(GenericASTTraversal, object):
|
|||||||
elif n.kind in ('ifelsestmt', 'ifelsestmtc', 'ifelsestmtl'):
|
elif n.kind in ('ifelsestmt', 'ifelsestmtc', 'ifelsestmtl'):
|
||||||
n.kind = 'elifelsestmt'
|
n.kind = 'elifelsestmt'
|
||||||
if not preprocess:
|
if not preprocess:
|
||||||
|
if old_stmts:
|
||||||
|
if n.kind == "elifstmt":
|
||||||
|
trailing_else = SyntaxTree("stmts", old_stmts[1:])
|
||||||
|
# We use elifelsestmtr because it has 3 nodes
|
||||||
|
elifelse_stmt = SyntaxTree(
|
||||||
|
'elifelsestmtr', [n[0], n[1], trailing_else])
|
||||||
|
node[3] = elifelse_stmt
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
# Other cases for n.kind may happen here
|
||||||
|
return
|
||||||
|
pass
|
||||||
self.default(node)
|
self.default(node)
|
||||||
|
|
||||||
n_ifelsestmtc = n_ifelsestmtl = n_ifelsestmt
|
n_ifelsestmtc = n_ifelsestmtl = n_ifelsestmt
|
||||||
|
Reference in New Issue
Block a user