You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-04 01:09:52 +08:00
Merge branch 'master' into python-2.4
This commit is contained in:
BIN
test/bytecode_2.6/01_triple_compare.pyc
Normal file
BIN
test/bytecode_2.6/01_triple_compare.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.6/02_ifelse_lambda.pyc
Normal file
BIN
test/bytecode_2.6/02_ifelse_lambda.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -3,8 +3,6 @@
|
|||||||
|
|
||||||
f = lambda x: 1 if x<2 else 3
|
f = lambda x: 1 if x<2 else 3
|
||||||
f(5)
|
f(5)
|
||||||
<<<<<<< HEAD
|
|
||||||
=======
|
|
||||||
|
|
||||||
# If that wasn't enough ...
|
# If that wasn't enough ...
|
||||||
# Python will create dead code
|
# Python will create dead code
|
||||||
@@ -16,4 +14,6 @@ g()
|
|||||||
|
|
||||||
h = lambda: 1 if False else 3
|
h = lambda: 1 if False else 3
|
||||||
h()
|
h()
|
||||||
>>>>>>> master
|
|
||||||
|
# From 2.7 test_builtin
|
||||||
|
lambda c: 'a' <= c <= 'z', 'Hello World'
|
||||||
|
@@ -1,5 +1,13 @@
|
|||||||
# In Python 3.3+ this uses grammar rule
|
# In Python 3.3+ this uses grammar rule
|
||||||
# compare_chained2 ::= expr COMPARE_OP RETURN_VALUE
|
# compare_chained2 ::= expr COMPARE_OP RETURN_VALUE
|
||||||
|
|
||||||
def _is_valid_netmask(self, netmask):
|
# Seen in Python 3.3 ipaddress.py
|
||||||
return 0 <= netmask <= self._max_prefixlen
|
|
||||||
|
def _is_valid_netmask(netmask):
|
||||||
|
return 0 <= netmask <= 10
|
||||||
|
|
||||||
|
# There were also bugs in 2.6- involving the use of "or" twice in its "or"
|
||||||
|
# detections
|
||||||
|
|
||||||
|
# See in 2.6.9 quopri.py ishex():
|
||||||
|
'0' <= __file__ <= '9' or 'a' <= __file__ <= 'f' or 'A' <= __file__ <= 'F'
|
||||||
|
@@ -61,17 +61,48 @@ case $PYVERSION in
|
|||||||
[test_ftplib.py]=1 # Control flow?
|
[test_ftplib.py]=1 # Control flow?
|
||||||
[test_funcattrs.py]=1 # Control flow?
|
[test_funcattrs.py]=1 # Control flow?
|
||||||
[test_grp.py]=1 # Long test - might work Control flow?
|
[test_grp.py]=1 # Long test - might work Control flow?
|
||||||
|
[test_imp.py]=1
|
||||||
|
[test_int.py]=1
|
||||||
|
[test_long.py]=1
|
||||||
|
[test_pty.py]=1
|
||||||
[test_pwd.py]=1 # Long test - might work? Control flow?
|
[test_pwd.py]=1 # Long test - might work? Control flow?
|
||||||
[test_queue.py]=1 # Control flow?
|
[test_queue.py]=1 # Control flow?
|
||||||
|
[test_re.py]=1 # Probably Control flow?
|
||||||
|
[test_strftime.py]=1
|
||||||
|
[test_trace.py]=1 # Line numbers are expected to be different
|
||||||
|
# .pyenv/versions/2.6.9/lib/python2.6/lib2to3/refactor.pyc
|
||||||
|
# .pyenv/versions/2.6.9/lib/python2.6/mailbox.pyc
|
||||||
|
# .pyenv/versions/2.6.9/lib/python2.6/markupbase.pyc
|
||||||
|
# .pyenv/versions/2.6.9/lib/python2.6/pstats.pyc
|
||||||
|
# .pyenv/versions/2.6.9/lib/python2.6/pyclbr.pyc
|
||||||
|
# .pyenv/versions/2.6.9/lib/python2.6/quopri.pyc -- look at ishex, is short
|
||||||
|
# .pyenv/versions/2.6.9/lib/python2.6/random.pyc
|
||||||
|
# .pyenv/versions/2.6.9/lib/python2.6/smtpd.pyc
|
||||||
|
# .pyenv/versions/2.6.9/lib/python2.6/sre_parse.pyc
|
||||||
|
# .pyenv/versions/2.6.9/lib/python2.6/tabnanny.pyc
|
||||||
|
# .pyenv/versions/2.6.9/lib/python2.6/tarfile.pyc
|
||||||
)
|
)
|
||||||
;;
|
;;
|
||||||
2.7)
|
2.7)
|
||||||
SKIP_TESTS=(
|
SKIP_TESTS=(
|
||||||
[test_builtin.py]=1 # Syntax error, look at
|
|
||||||
[test_dis.py]=1 # We change line numbers - duh!
|
[test_dis.py]=1 # We change line numbers - duh!
|
||||||
[test_grammar.py]=1 # Too many stmts. Handle large stmts
|
[test_grammar.py]=1 # Too many stmts. Handle large stmts
|
||||||
|
[test_io.py]=1 # Test takes too long to run
|
||||||
[test_ioctl.py]=1 # Test takes too long to run
|
[test_ioctl.py]=1 # Test takes too long to run
|
||||||
[test_itertools.py]=1 # Syntax error - look at!
|
[test_itertools.py]=1 # Syntax error - look at!
|
||||||
|
[test_memoryio.py]=1 # ?
|
||||||
|
[test_multiprocessing.py]=1 # ?
|
||||||
|
[test_pep352.py]=1 # ?
|
||||||
|
[test_re.py]=1 # ?
|
||||||
|
[test_sys_settrace.py]=1 # Line numbers are expected to be different
|
||||||
|
[test_strtod.py]=1
|
||||||
|
[test_traceback.py]=1
|
||||||
|
[test_unicode.py]=1
|
||||||
|
# Syntax errors:
|
||||||
|
# .pyenv/versions/2.7.14/lib/python2.7/mimify.pyc
|
||||||
|
# .pyenv/versions/2.7.14/lib/python2.7/netrc.pyc
|
||||||
|
# .pyenv/versions/2.7.14/lib/python2.7/pyclbr.pyc
|
||||||
|
# .pyenv/versions/2.7.14/lib/python2.7/sre_compile.pyc
|
||||||
)
|
)
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
@@ -101,13 +132,22 @@ if [[ -n $1 ]] ; then
|
|||||||
files=$1
|
files=$1
|
||||||
SKIP_TESTS=()
|
SKIP_TESTS=()
|
||||||
else
|
else
|
||||||
files=test_[m]*.py
|
files=test_*.py
|
||||||
fi
|
fi
|
||||||
for file in $files; do
|
for file in $files; do
|
||||||
[[ -v SKIP_TESTS[$file] ]] && continue
|
[[ -v SKIP_TESTS[$file] ]] && continue
|
||||||
|
|
||||||
# If the fails *before* decompiling, skip it!
|
# If the fails *before* decompiling, skip it!
|
||||||
|
typeset -i STARTTIME=$(date +%s)
|
||||||
if ! python $file >/dev/null 2>&1 ; then
|
if ! python $file >/dev/null 2>&1 ; then
|
||||||
|
echo "Skipping test $file -- it fails on its own"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
typeset -i ENDTIME=$(date +%s)
|
||||||
|
typeset -i time_diff
|
||||||
|
(( time_diff = ENDTIME - STARTTIME))
|
||||||
|
if (( time_diff > 10 )) ; then
|
||||||
|
echo "Skipping test $file -- test takes too long to run: $time_diff seconds"
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -117,10 +157,11 @@ for file in $files; do
|
|||||||
decompiled_file=$short_name-${PYVERSION}.pyc
|
decompiled_file=$short_name-${PYVERSION}.pyc
|
||||||
$fulldir/compile-file.py $file && \
|
$fulldir/compile-file.py $file && \
|
||||||
mv $file{,.orig} && \
|
mv $file{,.orig} && \
|
||||||
|
echo ========== $(date +%X) Decompiling $file ===========
|
||||||
$fulldir/../../bin/uncompyle6 $decompiled_file > $file
|
$fulldir/../../bin/uncompyle6 $decompiled_file > $file
|
||||||
rc=$?
|
rc=$?
|
||||||
if (( rc == 0 )) ; then
|
if (( rc == 0 )) ; then
|
||||||
echo ========== Running $file ===========
|
echo ========== $(date +%X) Running $file ===========
|
||||||
python $file
|
python $file
|
||||||
rc=$?
|
rc=$?
|
||||||
else
|
else
|
||||||
|
@@ -101,6 +101,9 @@ def do_tests(src_dir, patterns, target_dir, start_with=None, do_verify=False):
|
|||||||
files = [file for file in files if not 'site-packages' in file]
|
files = [file for file in files if not 'site-packages' in file]
|
||||||
files = [file for file in files if not 'test' in file]
|
files = [file for file in files if not 'test' in file]
|
||||||
if len(files) > 200:
|
if len(files) > 200:
|
||||||
|
# print("Numer of files %d - truncating to last 200" % len(files))
|
||||||
|
# files = files[-200:]
|
||||||
|
print("Numer of files %d - truncating to first 200" % len(files))
|
||||||
files = files[:200]
|
files = files[:200]
|
||||||
|
|
||||||
print(time.ctime())
|
print(time.ctime())
|
||||||
|
@@ -266,7 +266,7 @@ class PythonParser(GenericASTBuilder):
|
|||||||
stmt ::= while1stmt
|
stmt ::= while1stmt
|
||||||
stmt ::= whileelsestmt
|
stmt ::= whileelsestmt
|
||||||
stmt ::= while1elsestmt
|
stmt ::= while1elsestmt
|
||||||
stmt ::= forstmt
|
stmt ::= for
|
||||||
stmt ::= forelsestmt
|
stmt ::= forelsestmt
|
||||||
stmt ::= try_except
|
stmt ::= try_except
|
||||||
stmt ::= tryelsestmt
|
stmt ::= tryelsestmt
|
||||||
@@ -374,20 +374,20 @@ class PythonParser(GenericASTBuilder):
|
|||||||
|
|
||||||
def p_forstmt(self, args):
|
def p_forstmt(self, args):
|
||||||
"""
|
"""
|
||||||
_for ::= GET_ITER FOR_ITER
|
for_iter ::= GET_ITER FOR_ITER
|
||||||
|
|
||||||
for_block ::= l_stmts_opt _come_froms JUMP_BACK
|
for_block ::= l_stmts_opt _come_froms JUMP_BACK
|
||||||
|
|
||||||
forstmt ::= SETUP_LOOP expr _for store
|
for ::= SETUP_LOOP expr for_iter store
|
||||||
for_block POP_BLOCK _come_froms
|
for_block POP_BLOCK _come_froms
|
||||||
|
|
||||||
forelsestmt ::= SETUP_LOOP expr _for store
|
forelsestmt ::= SETUP_LOOP expr for_iter store
|
||||||
for_block POP_BLOCK else_suite _come_froms
|
for_block POP_BLOCK else_suite _come_froms
|
||||||
|
|
||||||
forelselaststmt ::= SETUP_LOOP expr _for store
|
forelselaststmt ::= SETUP_LOOP expr for_iter store
|
||||||
for_block POP_BLOCK else_suitec _come_froms
|
for_block POP_BLOCK else_suitec _come_froms
|
||||||
|
|
||||||
forelselaststmtl ::= SETUP_LOOP expr _for store
|
forelselaststmtl ::= SETUP_LOOP expr for_iter store
|
||||||
for_block POP_BLOCK else_suitel _come_froms
|
for_block POP_BLOCK else_suitel _come_froms
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@@ -244,7 +244,7 @@ class Python2Parser(PythonParser):
|
|||||||
stmt ::= assign2_pypy
|
stmt ::= assign2_pypy
|
||||||
assign3_pypy ::= expr expr expr store store store
|
assign3_pypy ::= expr expr expr store store store
|
||||||
assign2_pypy ::= expr expr store store
|
assign2_pypy ::= expr expr store store
|
||||||
list_comp ::= expr BUILD_LIST_FROM_ARG _for store list_iter
|
list_comp ::= expr BUILD_LIST_FROM_ARG for_iter store list_iter
|
||||||
JUMP_BACK
|
JUMP_BACK
|
||||||
""", nop_func)
|
""", nop_func)
|
||||||
|
|
||||||
|
@@ -13,11 +13,11 @@ class Python21Parser(Python22Parser):
|
|||||||
|
|
||||||
def p_forstmt21(self, args):
|
def p_forstmt21(self, args):
|
||||||
"""
|
"""
|
||||||
_for ::= LOAD_CONST FOR_LOOP
|
for_iter ::= LOAD_CONST FOR_LOOP
|
||||||
forstmt ::= SETUP_LOOP expr _for store
|
for ::= SETUP_LOOP expr for_iter store
|
||||||
return_stmts
|
return_stmts
|
||||||
POP_BLOCK COME_FROM
|
POP_BLOCK COME_FROM
|
||||||
forstmt ::= SETUP_LOOP expr _for store
|
for ::= SETUP_LOOP expr for_iter store
|
||||||
l_stmts_opt _jump_back
|
l_stmts_opt _jump_back
|
||||||
POP_BLOCK COME_FROM
|
POP_BLOCK COME_FROM
|
||||||
|
|
||||||
|
@@ -13,10 +13,10 @@ class Python22Parser(Python23Parser):
|
|||||||
|
|
||||||
def p_misc22(self, args):
|
def p_misc22(self, args):
|
||||||
'''
|
'''
|
||||||
_for ::= LOAD_CONST FOR_LOOP
|
for_iter ::= LOAD_CONST FOR_LOOP
|
||||||
list_iter ::= list_if JUMP_FORWARD
|
list_iter ::= list_if JUMP_FORWARD
|
||||||
COME_FROM POP_TOP COME_FROM
|
COME_FROM POP_TOP COME_FROM
|
||||||
list_for ::= expr _for store list_iter CONTINUE JUMP_FORWARD
|
list_for ::= expr for_iter store list_iter CONTINUE JUMP_FORWARD
|
||||||
COME_FROM POP_TOP COME_FROM
|
COME_FROM POP_TOP COME_FROM
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
@@ -36,7 +36,7 @@ class Python23Parser(Python24Parser):
|
|||||||
COME_FROM POP_TOP POP_BLOCK COME_FROM
|
COME_FROM POP_TOP POP_BLOCK COME_FROM
|
||||||
|
|
||||||
list_comp ::= BUILD_LIST_0 DUP_TOP LOAD_ATTR store list_iter del_stmt
|
list_comp ::= BUILD_LIST_0 DUP_TOP LOAD_ATTR store list_iter del_stmt
|
||||||
list_for ::= expr _for store list_iter JUMP_BACK come_froms POP_TOP JUMP_BACK
|
list_for ::= expr for_iter store list_iter JUMP_BACK come_froms POP_TOP JUMP_BACK
|
||||||
|
|
||||||
lc_body ::= LOAD_NAME expr CALL_FUNCTION_1 POP_TOP
|
lc_body ::= LOAD_NAME expr CALL_FUNCTION_1 POP_TOP
|
||||||
lc_body ::= LOAD_FAST expr CALL_FUNCTION_1 POP_TOP
|
lc_body ::= LOAD_FAST expr CALL_FUNCTION_1 POP_TOP
|
||||||
|
@@ -180,23 +180,23 @@ class Python26Parser(Python2Parser):
|
|||||||
|
|
||||||
def p_comp26(self, args):
|
def p_comp26(self, args):
|
||||||
'''
|
'''
|
||||||
list_for ::= expr _for store list_iter JUMP_BACK come_froms POP_TOP
|
list_for ::= expr for_iter store list_iter JUMP_BACK come_froms POP_TOP
|
||||||
|
|
||||||
# The JUMP FORWARD below jumps to the JUMP BACK. It seems to happen
|
# The JUMP FORWARD below jumps to the JUMP BACK. It seems to happen
|
||||||
# in rare cases that may have to with length of code
|
# in rare cases that may have to with length of code
|
||||||
# FIXME: we can add a reduction check for this
|
# FIXME: we can add a reduction check for this
|
||||||
|
|
||||||
list_for ::= expr _for store list_iter JUMP_FORWARD come_froms POP_TOP
|
list_for ::= expr for_iter store list_iter JUMP_FORWARD come_froms POP_TOP
|
||||||
COME_FROM JUMP_BACK
|
COME_FROM JUMP_BACK
|
||||||
|
|
||||||
list_for ::= expr _for store list_iter jb_cont
|
list_for ::= expr for_iter store list_iter jb_cont
|
||||||
|
|
||||||
# This is for a really funky:
|
# This is for a really funky:
|
||||||
# [ x for x in range(10) if x % 2 if x % 3 ]
|
# [ x for x in range(10) if x % 2 if x % 3 ]
|
||||||
# the JUMP_ABSOLUTE is to the instruction after the last POP_TOP
|
# the JUMP_ABSOLUTE is to the instruction after the last POP_TOP
|
||||||
# we have a reduction check for this
|
# we have a reduction check for this
|
||||||
|
|
||||||
list_for ::= expr _for store list_iter JUMP_ABSOLUTE come_froms
|
list_for ::= expr for_iter store list_iter JUMP_ABSOLUTE come_froms
|
||||||
POP_TOP jb_pop
|
POP_TOP jb_pop
|
||||||
|
|
||||||
list_iter ::= list_if JUMP_BACK
|
list_iter ::= list_if JUMP_BACK
|
||||||
@@ -208,7 +208,7 @@ class Python26Parser(Python2Parser):
|
|||||||
lc_body ::= LOAD_NAME expr LIST_APPEND
|
lc_body ::= LOAD_NAME expr LIST_APPEND
|
||||||
lc_body ::= LOAD_FAST expr LIST_APPEND
|
lc_body ::= LOAD_FAST expr LIST_APPEND
|
||||||
|
|
||||||
comp_for ::= SETUP_LOOP expr _for store comp_iter jb_pb_come_from
|
comp_for ::= SETUP_LOOP expr for_iter store comp_iter jb_pb_come_from
|
||||||
|
|
||||||
comp_body ::= gen_comp_body
|
comp_body ::= gen_comp_body
|
||||||
|
|
||||||
@@ -259,10 +259,24 @@ class Python26Parser(Python2Parser):
|
|||||||
|
|
||||||
# compare_chained is like x <= y <= z
|
# compare_chained is like x <= y <= z
|
||||||
compare_chained ::= expr compare_chained1 ROT_TWO COME_FROM POP_TOP _come_froms
|
compare_chained ::= expr compare_chained1 ROT_TWO COME_FROM POP_TOP _come_froms
|
||||||
|
compare_chained1 ::= expr DUP_TOP ROT_THREE COMPARE_OP
|
||||||
|
jmp_false_then compare_chained1 _come_froms
|
||||||
|
compare_chained1 ::= expr DUP_TOP ROT_THREE COMPARE_OP
|
||||||
|
jmp_false_then compare_chained2 _come_froms
|
||||||
compare_chained1 ::= expr DUP_TOP ROT_THREE COMPARE_OP
|
compare_chained1 ::= expr DUP_TOP ROT_THREE COMPARE_OP
|
||||||
jmp_false compare_chained1 _come_froms
|
jmp_false compare_chained1 _come_froms
|
||||||
compare_chained1 ::= expr DUP_TOP ROT_THREE COMPARE_OP
|
compare_chained1 ::= expr DUP_TOP ROT_THREE COMPARE_OP
|
||||||
jmp_false compare_chained2 _come_froms
|
jmp_false compare_chained2 _come_froms
|
||||||
|
compare_chained1 ::= expr DUP_TOP ROT_THREE COMPARE_OP
|
||||||
|
jmp_false_then compare_chained2 _come_froms
|
||||||
|
|
||||||
|
return_lambda ::= RETURN_VALUE
|
||||||
|
return_lambda ::= RETURN_END_IF
|
||||||
|
return_lambda ::= RETURN_END_IF_LAMBDA
|
||||||
|
return_lambda ::= RETURN_VALUE_LAMBDA
|
||||||
|
|
||||||
|
compare_chained2 ::= expr COMPARE_OP return_lambda
|
||||||
|
|
||||||
return_if_lambda ::= RETURN_END_IF_LAMBDA POP_TOP
|
return_if_lambda ::= RETURN_END_IF_LAMBDA POP_TOP
|
||||||
stmt ::= conditional_lambda
|
stmt ::= conditional_lambda
|
||||||
conditional_lambda ::= expr jmp_false_then expr return_if_lambda
|
conditional_lambda ::= expr jmp_false_then expr return_if_lambda
|
||||||
@@ -314,7 +328,7 @@ class Python26Parser(Python2Parser):
|
|||||||
tokens[last].pattr == jmp_false.pattr)
|
tokens[last].pattr == jmp_false.pattr)
|
||||||
elif rule == (
|
elif rule == (
|
||||||
'list_for',
|
'list_for',
|
||||||
('expr', '_for', 'store', 'list_iter',
|
('expr', 'for_iter', 'store', 'list_iter',
|
||||||
'JUMP_ABSOLUTE', 'come_froms', 'POP_TOP', 'jb_pop')):
|
'JUMP_ABSOLUTE', 'come_froms', 'POP_TOP', 'jb_pop')):
|
||||||
# The JUMP_ABSOLUTE has to be to the last POP_TOP or this is invalid
|
# The JUMP_ABSOLUTE has to be to the last POP_TOP or this is invalid
|
||||||
ja_attr = ast[4].attr
|
ja_attr = ast[4].attr
|
||||||
|
@@ -14,7 +14,7 @@ class Python27Parser(Python2Parser):
|
|||||||
|
|
||||||
def p_comprehension27(self, args):
|
def p_comprehension27(self, args):
|
||||||
"""
|
"""
|
||||||
list_for ::= expr _for store list_iter JUMP_BACK
|
list_for ::= expr for_iter store list_iter JUMP_BACK
|
||||||
list_comp ::= BUILD_LIST_0 list_iter
|
list_comp ::= BUILD_LIST_0 list_iter
|
||||||
lc_body ::= expr LIST_APPEND
|
lc_body ::= expr LIST_APPEND
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ class Python27Parser(Python2Parser):
|
|||||||
|
|
||||||
comp_body ::= dict_comp_body
|
comp_body ::= dict_comp_body
|
||||||
comp_body ::= set_comp_body
|
comp_body ::= set_comp_body
|
||||||
comp_for ::= expr _for store comp_iter JUMP_BACK
|
comp_for ::= expr for_iter store comp_iter JUMP_BACK
|
||||||
|
|
||||||
dict_comp_body ::= expr expr MAP_ADD
|
dict_comp_body ::= expr expr MAP_ADD
|
||||||
set_comp_body ::= expr SET_ADD
|
set_comp_body ::= expr SET_ADD
|
||||||
@@ -82,7 +82,12 @@ class Python27Parser(Python2Parser):
|
|||||||
compare_chained1 COME_FROM
|
compare_chained1 COME_FROM
|
||||||
compare_chained1 ::= expr DUP_TOP ROT_THREE COMPARE_OP JUMP_IF_FALSE_OR_POP
|
compare_chained1 ::= expr DUP_TOP ROT_THREE COMPARE_OP JUMP_IF_FALSE_OR_POP
|
||||||
compare_chained2 COME_FROM
|
compare_chained2 COME_FROM
|
||||||
compare_chained2 ::= expr COMPARE_OP RETURN_VALUE
|
|
||||||
|
return_lambda ::= RETURN_VALUE
|
||||||
|
return_lambda ::= RETURN_VALUE_LAMBDA
|
||||||
|
|
||||||
|
compare_chained2 ::= expr COMPARE_OP return_lambda
|
||||||
|
compare_chained2 ::= expr COMPARE_OP return_lambda
|
||||||
|
|
||||||
# conditional_true are for conditions which always evaluate true
|
# conditional_true are for conditions which always evaluate true
|
||||||
# There is dead or non-optional remnants of the condition code though,
|
# There is dead or non-optional remnants of the condition code though,
|
||||||
|
@@ -36,8 +36,8 @@ class Python3Parser(PythonParser):
|
|||||||
# one may be a continue - sometimes classifies a JUMP_BACK
|
# one may be a continue - sometimes classifies a JUMP_BACK
|
||||||
# as a CONTINUE. The two are kind of the same in a comprehension.
|
# as a CONTINUE. The two are kind of the same in a comprehension.
|
||||||
|
|
||||||
comp_for ::= expr _for store comp_iter CONTINUE
|
comp_for ::= expr for_iter store comp_iter CONTINUE
|
||||||
comp_for ::= expr _for store comp_iter JUMP_BACK
|
comp_for ::= expr for_iter store comp_iter JUMP_BACK
|
||||||
|
|
||||||
list_comp ::= BUILD_LIST_0 list_iter
|
list_comp ::= BUILD_LIST_0 list_iter
|
||||||
lc_body ::= expr LIST_APPEND
|
lc_body ::= expr LIST_APPEND
|
||||||
@@ -326,16 +326,16 @@ class Python3Parser(PythonParser):
|
|||||||
|
|
||||||
def p_loop_stmt3(self, args):
|
def p_loop_stmt3(self, args):
|
||||||
"""
|
"""
|
||||||
forstmt ::= SETUP_LOOP expr _for store for_block POP_BLOCK
|
for ::= SETUP_LOOP expr for_iter store for_block POP_BLOCK
|
||||||
COME_FROM_LOOP
|
COME_FROM_LOOP
|
||||||
|
|
||||||
forelsestmt ::= SETUP_LOOP expr _for store for_block POP_BLOCK else_suite
|
forelsestmt ::= SETUP_LOOP expr for_iter store for_block POP_BLOCK else_suite
|
||||||
COME_FROM_LOOP
|
COME_FROM_LOOP
|
||||||
|
|
||||||
forelselaststmt ::= SETUP_LOOP expr _for store for_block POP_BLOCK else_suitec
|
forelselaststmt ::= SETUP_LOOP expr for_iter store for_block POP_BLOCK else_suitec
|
||||||
COME_FROM_LOOP
|
COME_FROM_LOOP
|
||||||
|
|
||||||
forelselaststmtl ::= SETUP_LOOP expr _for store for_block POP_BLOCK else_suitel
|
forelselaststmtl ::= SETUP_LOOP expr for_iter store for_block POP_BLOCK else_suitel
|
||||||
COME_FROM_LOOP
|
COME_FROM_LOOP
|
||||||
|
|
||||||
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
|
||||||
@@ -370,7 +370,7 @@ class Python3Parser(PythonParser):
|
|||||||
COME_FROM_LOOP
|
COME_FROM_LOOP
|
||||||
whileTruestmt ::= SETUP_LOOP l_stmts_opt JUMP_BACK POP_BLOCK NOP
|
whileTruestmt ::= SETUP_LOOP l_stmts_opt JUMP_BACK POP_BLOCK NOP
|
||||||
COME_FROM_LOOP
|
COME_FROM_LOOP
|
||||||
forstmt ::= SETUP_LOOP expr _for store for_block POP_BLOCK NOP
|
for ::= SETUP_LOOP expr for_iter store for_block POP_BLOCK NOP
|
||||||
COME_FROM_LOOP
|
COME_FROM_LOOP
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@@ -715,18 +715,22 @@ class Scanner2(Scanner):
|
|||||||
# rocky: if we have a conditional jump to the next instruction, then
|
# rocky: if we have a conditional jump to the next instruction, then
|
||||||
# possibly I am "skipping over" a "pass" or null statement.
|
# possibly I am "skipping over" a "pass" or null statement.
|
||||||
|
|
||||||
|
test_target = target
|
||||||
if self.version < 2.7:
|
if self.version < 2.7:
|
||||||
op_testset = set([self.opc.POP_TOP,
|
# Before 2.6 we have to deal with the fact that there is an extra
|
||||||
self.opc.JUMP_IF_TRUE, self.opc.JUMP_IF_FALSE])
|
# POP_TOP that is logically associated with the JUMP_IF's (even though
|
||||||
|
# the instance set is called "self.pop_jump_if")
|
||||||
|
if code[pre[test_target]] == self.opc.POP_TOP:
|
||||||
|
test_target = pre[test_target]
|
||||||
|
test_set = self.pop_jump_if
|
||||||
else:
|
else:
|
||||||
op_testset = self.pop_jump_if_or_pop | self.pop_jump_if
|
test_set = self.pop_jump_if_or_pop | self.pop_jump_if
|
||||||
|
|
||||||
if ( code[pre[target]] in op_testset
|
if ( code[pre[test_target]] in test_set and target > offset ):
|
||||||
and (target > offset) ):
|
|
||||||
self.fixed_jumps[offset] = pre[target]
|
self.fixed_jumps[offset] = pre[target]
|
||||||
self.structs.append({'type': 'and/or',
|
self.structs.append({'type': 'and/or',
|
||||||
'start': start,
|
'start': start,
|
||||||
'end': pre[target]})
|
'end': pre[target]})
|
||||||
return
|
return
|
||||||
|
|
||||||
# The op offset just before the target jump offset is important
|
# The op offset just before the target jump offset is important
|
||||||
|
@@ -196,8 +196,12 @@ class Scanner3(Scanner):
|
|||||||
# 'LOAD_ASSERT' is used in assert statements.
|
# 'LOAD_ASSERT' is used in assert statements.
|
||||||
self.load_asserts = set()
|
self.load_asserts = set()
|
||||||
self.insts = list(bytecode)
|
self.insts = list(bytecode)
|
||||||
|
self.offset2inst_index = {}
|
||||||
n = len(self.insts)
|
n = len(self.insts)
|
||||||
for i, inst in enumerate(self.insts):
|
for i, inst in enumerate(self.insts):
|
||||||
|
|
||||||
|
self.offset2inst_index[inst.offset] = i
|
||||||
|
|
||||||
# We need to detect the difference between:
|
# We need to detect the difference between:
|
||||||
# raise AssertionError
|
# raise AssertionError
|
||||||
# and
|
# and
|
||||||
@@ -953,8 +957,18 @@ class Scanner3(Scanner):
|
|||||||
self.fixed_jumps[offset] = rtarget
|
self.fixed_jumps[offset] = rtarget
|
||||||
self.not_continue.add(pre_rtarget)
|
self.not_continue.add(pre_rtarget)
|
||||||
else:
|
else:
|
||||||
# For now, we'll only tag forward jump.
|
|
||||||
if self.version >= 3.6:
|
# FIXME: this is very convoluted and based on rather hacky
|
||||||
|
# empirical evidence. It should go a way when
|
||||||
|
# we have better control-flow analysis
|
||||||
|
normal_jump = self.version >= 3.6
|
||||||
|
if self.version == 3.5:
|
||||||
|
j = self.offset2inst_index[target]
|
||||||
|
if j+2 < len(self.insts) and self.insts[j+2].is_jump_target:
|
||||||
|
normal_jump = self.insts[j+1].opname == 'POP_BLOCK'
|
||||||
|
|
||||||
|
if normal_jump:
|
||||||
|
# For now, we'll only tag forward jump.
|
||||||
if target > offset:
|
if target > offset:
|
||||||
self.fixed_jumps[offset] = target
|
self.fixed_jumps[offset] = target
|
||||||
pass
|
pass
|
||||||
|
@@ -258,7 +258,7 @@ TABLE_DIRECT = {
|
|||||||
'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 ),
|
||||||
'whileelselaststmt': ( '%|while %c:\n%+%c%-%|else:\n%+%c%-', 1, 2, -2 ),
|
'whileelselaststmt': ( '%|while %c:\n%+%c%-%|else:\n%+%c%-', 1, 2, -2 ),
|
||||||
'forstmt': ( '%|for %c in %c:\n%+%c%-\n\n', 3, 1, 4 ),
|
'for': ( '%|for %c in %c:\n%+%c%-\n\n', 3, 1, 4 ),
|
||||||
'forelsestmt': (
|
'forelsestmt': (
|
||||||
'%|for %c in %c:\n%+%c%-%|else:\n%+%c%-\n\n', 3, 1, 4, -2 ),
|
'%|for %c in %c:\n%+%c%-%|else:\n%+%c%-\n\n', 3, 1, 4, -2 ),
|
||||||
'forelselaststmt': (
|
'forelselaststmt': (
|
||||||
|
@@ -105,7 +105,7 @@ TABLE_DIRECT_FRAGMENT = {
|
|||||||
'whilestmt': ( '%|while%b %c:\n%+%c%-\n\n', 0, 1, 2 ),
|
'whilestmt': ( '%|while%b %c:\n%+%c%-\n\n', 0, 1, 2 ),
|
||||||
'whileelsestmt': ( '%|while%b %c:\n%+%c%-%|else:\n%+%c%-\n\n', 0, 1, 2, -2 ),
|
'whileelsestmt': ( '%|while%b %c:\n%+%c%-%|else:\n%+%c%-\n\n', 0, 1, 2, -2 ),
|
||||||
'whileelselaststmt': ( '%|while%b %c:\n%+%c%-%|else:\n%+%c%-', 0, 1, 2, -2 ),
|
'whileelselaststmt': ( '%|while%b %c:\n%+%c%-%|else:\n%+%c%-', 0, 1, 2, -2 ),
|
||||||
'forstmt': ( '%|for%b %c in %c:\n%+%c%-\n\n', 0, 3, 1, 4 ),
|
'for': ( '%|for%b %c in %c:\n%+%c%-\n\n', 0, 3, 1, 4 ),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user