You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-03 00:45:53 +08:00
Fix "for ... if" bug introduced since 3.6.2...
However we've isolated and documented the 3.x grammar a little bit better
This commit is contained in:
Binary file not shown.
BIN
test/bytecode_3.2_run/10_for_if_loopback.pyc
Normal file
BIN
test/bytecode_3.2_run/10_for_if_loopback.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.7_run/10_for_if_loopback.pyc
Normal file
BIN
test/bytecode_3.7_run/10_for_if_loopback.pyc
Normal file
Binary file not shown.
@@ -11,6 +11,7 @@
|
|||||||
# 101_0 COME_FROM '50' statement: if name == ...to fictional "end if"
|
# 101_0 COME_FROM '50' statement: if name == ...to fictional "end if"
|
||||||
# 101 JUMP_BACK '16' jump as before to loop head
|
# 101 JUMP_BACK '16' jump as before to loop head
|
||||||
|
|
||||||
|
# RUNNABLE!
|
||||||
def _slotnames(cls):
|
def _slotnames(cls):
|
||||||
names = []
|
names = []
|
||||||
for c in cls.__mro__:
|
for c in cls.__mro__:
|
||||||
@@ -21,3 +22,18 @@ def _slotnames(cls):
|
|||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
names.append(name) # 3.2 bug here jumping to outer for
|
names.append(name) # 3.2 bug here jumping to outer for
|
||||||
|
|
||||||
|
# From 3.2.6 pdb.py
|
||||||
|
# There is no "come_from" after the "if" since the
|
||||||
|
# if jumps back to the loop. For this we use
|
||||||
|
# grammar rule "ifstmtl"
|
||||||
|
def lasti2lineno(linestarts, a):
|
||||||
|
for i in linestarts:
|
||||||
|
if a:
|
||||||
|
return a
|
||||||
|
return -1
|
||||||
|
|
||||||
|
assert lasti2lineno([], True) == -1
|
||||||
|
assert lasti2lineno([], False) == -1
|
||||||
|
assert lasti2lineno([1], False) == -1
|
||||||
|
assert lasti2lineno([1], True) == 1
|
||||||
|
@@ -141,18 +141,20 @@ class Python3Parser(PythonParser):
|
|||||||
assert_expr_or ::= assert_expr jmp_true expr
|
assert_expr_or ::= assert_expr jmp_true expr
|
||||||
assert_expr_and ::= assert_expr jmp_false expr
|
assert_expr_and ::= assert_expr jmp_false expr
|
||||||
|
|
||||||
ifstmt ::= testexpr _ifstmts_jump
|
ifstmt ::= testexpr _ifstmts_jump
|
||||||
|
|
||||||
testexpr ::= testfalse
|
testexpr ::= testfalse
|
||||||
testexpr ::= testtrue
|
testexpr ::= testtrue
|
||||||
testfalse ::= expr jmp_false
|
testfalse ::= expr jmp_false
|
||||||
testtrue ::= expr jmp_true
|
testtrue ::= expr jmp_true
|
||||||
|
|
||||||
_ifstmts_jump ::= return_if_stmts
|
_ifstmts_jump ::= return_if_stmts
|
||||||
_ifstmts_jump ::= c_stmts_opt come_froms
|
_ifstmts_jump ::= c_stmts_opt come_froms
|
||||||
|
_ifstmts_jumpl ::= return_if_stmts
|
||||||
|
|
||||||
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 _ifstmts_jumpl
|
||||||
|
|
||||||
# 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
|
||||||
@@ -330,6 +332,10 @@ class Python3Parser(PythonParser):
|
|||||||
def p_stmt3(self, args):
|
def p_stmt3(self, args):
|
||||||
"""
|
"""
|
||||||
stmt ::= if_expr_lambda
|
stmt ::= if_expr_lambda
|
||||||
|
|
||||||
|
# If statement inside a loop:
|
||||||
|
lastl_stmt ::= ifstmtl
|
||||||
|
|
||||||
stmt ::= conditional_not_lambda
|
stmt ::= conditional_not_lambda
|
||||||
if_expr_lambda ::= expr jmp_false expr return_if_lambda
|
if_expr_lambda ::= expr jmp_false expr return_if_lambda
|
||||||
return_stmt_lambda LAMBDA_MARKER
|
return_stmt_lambda LAMBDA_MARKER
|
||||||
|
@@ -952,6 +952,8 @@ class Python37Parser(Python37BaseParser):
|
|||||||
"""
|
"""
|
||||||
stmt ::= if_expr_lambda
|
stmt ::= if_expr_lambda
|
||||||
stmt ::= conditional_not_lambda
|
stmt ::= conditional_not_lambda
|
||||||
|
|
||||||
|
# If statement inside a loop:
|
||||||
stmt ::= ifstmtl
|
stmt ::= ifstmtl
|
||||||
|
|
||||||
if_expr_lambda ::= expr jmp_false expr return_if_lambda
|
if_expr_lambda ::= expr jmp_false expr return_if_lambda
|
||||||
|
@@ -371,14 +371,13 @@ TABLE_DIRECT = {
|
|||||||
# 'return': ( '%|return %c\n', 0),
|
# 'return': ( '%|return %c\n', 0),
|
||||||
'return_if_stmt': ( 'return %c\n', 0),
|
'return_if_stmt': ( 'return %c\n', 0),
|
||||||
|
|
||||||
'ifstmt': ( '%|if %c:\n%+%c%-',
|
"ifstmt": ( "%|if %c:\n%+%c%-",
|
||||||
0, # "testexpr" or "testexpr_then"
|
0, # "testexpr" or "testexpr_then"
|
||||||
1, # "_ifstmts_jump" or "return_stmts"
|
1, # "_ifstmts_jump" or "return_stmts"
|
||||||
),
|
),
|
||||||
|
'iflaststmt': ( "%|if %c:\n%+%c%-", 0, 1 ),
|
||||||
'iflaststmt': ( '%|if %c:\n%+%c%-', 0, 1 ),
|
'iflaststmtl': ( "%|if %c:\n%+%c%-", 0, 1 ),
|
||||||
'iflaststmtl': ( '%|if %c:\n%+%c%-', 0, 1 ),
|
'testtrue': ( "not %p",
|
||||||
'testtrue': ( 'not %p',
|
|
||||||
(0, PRECEDENCE['unary_not']) ),
|
(0, PRECEDENCE['unary_not']) ),
|
||||||
|
|
||||||
# Generally the args here are 0: (some sort of) "testexpr",
|
# Generally the args here are 0: (some sort of) "testexpr",
|
||||||
|
Reference in New Issue
Block a user