You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-03 00:45:53 +08:00
More Python version comparison conversions
This commit is contained in:
@@ -1,29 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
function finish {
|
|
||||||
cd $owd
|
|
||||||
}
|
|
||||||
|
|
||||||
# FIXME put some of the below in a common routine
|
|
||||||
owd=$(pwd)
|
|
||||||
trap finish EXIT
|
|
||||||
|
|
||||||
cd $(dirname ${BASH_SOURCE[0]})
|
|
||||||
if ! source ./pyenv-newer-versions ; then
|
|
||||||
exit $?
|
|
||||||
fi
|
|
||||||
if ! source ./setup-master.sh ; then
|
|
||||||
exit $?
|
|
||||||
fi
|
|
||||||
cd ..
|
|
||||||
for version in $PYVERSIONS; do
|
|
||||||
echo --- $version ---
|
|
||||||
if ! pyenv local $version ; then
|
|
||||||
exit $?
|
|
||||||
fi
|
|
||||||
make clean && pip install -e .
|
|
||||||
if ! make check-short; then
|
|
||||||
exit $?
|
|
||||||
fi
|
|
||||||
echo === $version ===
|
|
||||||
done
|
|
||||||
make check
|
|
@@ -1,8 +0,0 @@
|
|||||||
# -*- shell-script -*-
|
|
||||||
# Sets PYVERSIONS to be pyenv versions that
|
|
||||||
# we can use in the master branch.
|
|
||||||
if [[ $0 == ${BASH_SOURCE[0]} ]] ; then
|
|
||||||
echo "This script should be *sourced* rather than run directly through bash"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
export PYVERSIONS='3.5.9 3.6.12 2.6.9 3.3.7 2.7.18 3.2.6 3.1.5 3.4.10 3.7.9 3.8.5'
|
|
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
from uncompyle6 import PYTHON_VERSION, IS_PYPY
|
from xdis.version_info import PYTHON_VERSION_TRIPLE, IS_PYPY
|
||||||
from uncompyle6.scanner import get_scanner
|
from uncompyle6.scanner import get_scanner
|
||||||
def bug(state, slotstate):
|
def bug(state, slotstate):
|
||||||
if state:
|
if state:
|
||||||
@@ -21,8 +21,8 @@ def bug_loop(disassemble, tb=None):
|
|||||||
|
|
||||||
def test_if_in_for():
|
def test_if_in_for():
|
||||||
code = bug.__code__
|
code = bug.__code__
|
||||||
scan = get_scanner(PYTHON_VERSION)
|
scan = get_scanner(PYTHON_VERSION_TRIPLE)
|
||||||
if 2.7 <= PYTHON_VERSION <= 3.0 and not IS_PYPY:
|
if (2, 7) <= PYTHON_VERSION_TRIPLE < (3, 1) and not IS_PYPY:
|
||||||
scan.build_instructions(code)
|
scan.build_instructions(code)
|
||||||
fjt = scan.find_jump_targets(False)
|
fjt = scan.find_jump_targets(False)
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ def test_if_in_for():
|
|||||||
# previous bug was not mistaking while-loop for if-then
|
# previous bug was not mistaking while-loop for if-then
|
||||||
{'start': 48, 'end': 67, 'type': 'while-loop'}]
|
{'start': 48, 'end': 67, 'type': 'while-loop'}]
|
||||||
|
|
||||||
elif 3.2 < PYTHON_VERSION <= 3.4:
|
elif (3, 2) < PYTHON_VERSION_TRIPLE <= (3, 4):
|
||||||
scan.build_instructions(code)
|
scan.build_instructions(code)
|
||||||
fjt = scan.find_jump_targets(False)
|
fjt = scan.find_jump_targets(False)
|
||||||
assert {69: [66], 63: [18]} == fjt
|
assert {69: [66], 63: [18]} == fjt
|
||||||
@@ -62,6 +62,6 @@ def test_if_in_for():
|
|||||||
{'end': 59, 'type': 'for-loop', 'start': 31},
|
{'end': 59, 'type': 'for-loop', 'start': 31},
|
||||||
{'end': 63, 'type': 'for-else', 'start': 62}]
|
{'end': 63, 'type': 'for-else', 'start': 62}]
|
||||||
else:
|
else:
|
||||||
print("FIXME: should fix for %s" % PYTHON_VERSION)
|
print("FIXME: should fix for %s" % ".".join([str(v) for v in PYTHON_VERSION_TRIPLE]))
|
||||||
assert True
|
assert True
|
||||||
return
|
return
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import re
|
import re
|
||||||
from uncompyle6 import PYTHON_VERSION, PYTHON3, IS_PYPY # , PYTHON_VERSION
|
|
||||||
from uncompyle6.parser import get_python_parser, python_parser
|
from uncompyle6.parser import get_python_parser, python_parser
|
||||||
from uncompyle6.scanner import get_scanner
|
from uncompyle6.scanner import get_scanner
|
||||||
|
from xdis.version_info import PYTHON_VERSION_TRIPLE, PYTHON3, IS_PYPY
|
||||||
|
|
||||||
|
|
||||||
def test_grammar():
|
def test_grammar():
|
||||||
@@ -16,19 +16,19 @@ def test_grammar():
|
|||||||
p.dump_grammar(),
|
p.dump_grammar(),
|
||||||
)
|
)
|
||||||
|
|
||||||
p = get_python_parser(PYTHON_VERSION, is_pypy=IS_PYPY)
|
p = get_python_parser(PYTHON_VERSION_TRIPLE, is_pypy=IS_PYPY)
|
||||||
(lhs, rhs, tokens, right_recursive, dup_rhs) = p.check_sets()
|
(lhs, rhs, tokens, right_recursive, dup_rhs) = p.check_sets()
|
||||||
|
|
||||||
# We have custom rules that create the below
|
# We have custom rules that create the below
|
||||||
expect_lhs = set(["pos_arg"])
|
expect_lhs = set(["pos_arg"])
|
||||||
|
|
||||||
if PYTHON_VERSION < 3.8:
|
if PYTHON_VERSION_TRIPLE < (3, 8):
|
||||||
if PYTHON_VERSION < 3.7:
|
if PYTHON_VERSION_TRIPLE < (3, 7):
|
||||||
expect_lhs.add("attribute")
|
expect_lhs.add("attribute")
|
||||||
|
|
||||||
expect_lhs.add("get_iter")
|
expect_lhs.add("get_iter")
|
||||||
|
|
||||||
if PYTHON_VERSION > 3.7 or PYTHON_VERSION < 3.0:
|
if PYTHON_VERSION_TRIPLE >= (3, 8) or PYTHON_VERSION_TRIPLE < (3, 0):
|
||||||
expect_lhs.add("stmts_opt")
|
expect_lhs.add("stmts_opt")
|
||||||
else:
|
else:
|
||||||
expect_lhs.add("async_with_as_stmt")
|
expect_lhs.add("async_with_as_stmt")
|
||||||
@@ -38,15 +38,15 @@ def test_grammar():
|
|||||||
|
|
||||||
expect_right_recursive = set([("designList", ("store", "DUP_TOP", "designList"))])
|
expect_right_recursive = set([("designList", ("store", "DUP_TOP", "designList"))])
|
||||||
|
|
||||||
if PYTHON_VERSION <= 3.6:
|
if PYTHON_VERSION_TRIPLE <= (3, 6):
|
||||||
unused_rhs.add("call")
|
unused_rhs.add("call")
|
||||||
|
|
||||||
if PYTHON_VERSION > 2.6:
|
if PYTHON_VERSION_TRIPLE >= (3, 0):
|
||||||
expect_lhs.add("kvlist")
|
expect_lhs.add("kvlist")
|
||||||
expect_lhs.add("kv3")
|
expect_lhs.add("kv3")
|
||||||
unused_rhs.add("dict")
|
unused_rhs.add("dict")
|
||||||
|
|
||||||
if PYTHON_VERSION < 3.7 and PYTHON_VERSION != 2.7:
|
if PYTHON_VERSION_TRIPLE < (3, 7) and PYTHON_VERSION_TRIPLE[:2] != (2, 7):
|
||||||
# NOTE: this may disappear
|
# NOTE: this may disappear
|
||||||
expect_lhs.add("except_handler_else")
|
expect_lhs.add("except_handler_else")
|
||||||
|
|
||||||
@@ -60,8 +60,8 @@ def test_grammar():
|
|||||||
""".split()
|
""".split()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if PYTHON_VERSION >= 3.0:
|
if PYTHON_VERSION_TRIPLE >= (3, 0):
|
||||||
if PYTHON_VERSION < 3.7:
|
if PYTHON_VERSION_TRIPLE < (3, 7):
|
||||||
expect_lhs.add("annotate_arg")
|
expect_lhs.add("annotate_arg")
|
||||||
expect_lhs.add("annotate_tuple")
|
expect_lhs.add("annotate_tuple")
|
||||||
unused_rhs.add("mkfunc_annotate")
|
unused_rhs.add("mkfunc_annotate")
|
||||||
@@ -69,7 +69,7 @@ def test_grammar():
|
|||||||
unused_rhs.add("dict_comp")
|
unused_rhs.add("dict_comp")
|
||||||
unused_rhs.add("classdefdeco1")
|
unused_rhs.add("classdefdeco1")
|
||||||
unused_rhs.add("tryelsestmtl")
|
unused_rhs.add("tryelsestmtl")
|
||||||
if PYTHON_VERSION >= 3.5:
|
if PYTHON_VERSION_TRIPLE >= (3, 7):
|
||||||
expect_right_recursive.add(
|
expect_right_recursive.add(
|
||||||
(("l_stmts", ("lastl_stmt", "come_froms", "l_stmts")))
|
(("l_stmts", ("lastl_stmt", "come_froms", "l_stmts")))
|
||||||
)
|
)
|
||||||
@@ -80,7 +80,7 @@ def test_grammar():
|
|||||||
expect_lhs.add("kwarg")
|
expect_lhs.add("kwarg")
|
||||||
|
|
||||||
# FIXME
|
# FIXME
|
||||||
if PYTHON_VERSION < 3.8:
|
if PYTHON_VERSION_TRIPLE < (3, 8):
|
||||||
assert expect_lhs == set(lhs)
|
assert expect_lhs == set(lhs)
|
||||||
assert unused_rhs == set(rhs)
|
assert unused_rhs == set(rhs)
|
||||||
|
|
||||||
@@ -103,7 +103,7 @@ def test_grammar():
|
|||||||
print(k, reduced_dup_rhs[k])
|
print(k, reduced_dup_rhs[k])
|
||||||
# assert not reduced_dup_rhs, reduced_dup_rhs
|
# assert not reduced_dup_rhs, reduced_dup_rhs
|
||||||
|
|
||||||
s = get_scanner(PYTHON_VERSION, IS_PYPY)
|
s = get_scanner(PYTHON_VERSION_TRIPLE, IS_PYPY)
|
||||||
ignore_set = set(
|
ignore_set = set(
|
||||||
"""
|
"""
|
||||||
JUMP_BACK CONTINUE
|
JUMP_BACK CONTINUE
|
||||||
@@ -116,12 +116,12 @@ def test_grammar():
|
|||||||
RETURN_END_IF RETURN_END_IF_LAMBDA RETURN_VALUE_LAMBDA RETURN_LAST
|
RETURN_END_IF RETURN_END_IF_LAMBDA RETURN_VALUE_LAMBDA RETURN_LAST
|
||||||
""".split()
|
""".split()
|
||||||
)
|
)
|
||||||
if 2.6 <= PYTHON_VERSION <= 2.7:
|
if (2, 6) <= PYTHON_VERSION_TRIPLE <= (2, 7):
|
||||||
opcode_set = set(s.opc.opname).union(ignore_set)
|
opcode_set = set(s.opc.opname).union(ignore_set)
|
||||||
if PYTHON_VERSION == 2.6:
|
if PYTHON_VERSION_TRIPLE[:2] == (2, 6):
|
||||||
opcode_set.add("THEN")
|
opcode_set.add("THEN")
|
||||||
check_tokens(tokens, opcode_set)
|
check_tokens(tokens, opcode_set)
|
||||||
elif PYTHON_VERSION == 3.4:
|
elif PYTHON_VERSION_TRIPLE[:2] == (3, 4):
|
||||||
ignore_set.add("LOAD_CLASSNAME")
|
ignore_set.add("LOAD_CLASSNAME")
|
||||||
ignore_set.add("STORE_LOCALS")
|
ignore_set.add("STORE_LOCALS")
|
||||||
opcode_set = set(s.opc.opname).union(ignore_set)
|
opcode_set = set(s.opc.opname).union(ignore_set)
|
||||||
@@ -132,7 +132,7 @@ def test_dup_rule():
|
|||||||
import inspect
|
import inspect
|
||||||
|
|
||||||
python_parser(
|
python_parser(
|
||||||
PYTHON_VERSION,
|
PYTHON_VERSION_TRIPLE,
|
||||||
inspect.currentframe().f_code,
|
inspect.currentframe().f_code,
|
||||||
is_pypy=IS_PYPY,
|
is_pypy=IS_PYPY,
|
||||||
parser_debug={
|
parser_debug={
|
||||||
|
@@ -9,12 +9,13 @@ import tempfile
|
|||||||
import functools
|
import functools
|
||||||
|
|
||||||
# uncompyle6 / xdis
|
# uncompyle6 / xdis
|
||||||
from uncompyle6 import PYTHON_VERSION, PYTHON3, IS_PYPY, code_deparse
|
from uncompyle6 import code_deparse
|
||||||
|
from xdis.version_info import PYTHON_VERSION_TRIPLE, PYTHON3, IS_PYPY
|
||||||
|
|
||||||
# TODO : I think we can get xdis to support the dis api (python 3 version) by doing something like this there
|
# TODO : I think we can get xdis to support the dis api (python 3 version) by doing something like this there
|
||||||
from xdis import Bytecode, get_opcode
|
from xdis import Bytecode, get_opcode
|
||||||
|
|
||||||
opc = get_opcode(PYTHON_VERSION, IS_PYPY)
|
opc = get_opcode(PYTHON_VERSION_TRIPLE, IS_PYPY)
|
||||||
Bytecode = functools.partial(Bytecode, opc=opc)
|
Bytecode = functools.partial(Bytecode, opc=opc)
|
||||||
import six
|
import six
|
||||||
|
|
||||||
@@ -127,7 +128,7 @@ def validate_uncompyle(text, mode="exec"):
|
|||||||
original_text = text
|
original_text = text
|
||||||
|
|
||||||
deparsed = code_deparse(
|
deparsed = code_deparse(
|
||||||
original_code, out=six.StringIO(), version=PYTHON_VERSION, compile_mode=mode
|
original_code, out=six.StringIO(), version=PYTHON_VERSION_TRIPLE, compile_mode=mode
|
||||||
)
|
)
|
||||||
uncompyled_text = deparsed.text
|
uncompyled_text = deparsed.text
|
||||||
uncompyled_code = compile(uncompyled_text, "<string>", "exec")
|
uncompyled_code = compile(uncompyled_text, "<string>", "exec")
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2015-2016, 2818-2020 by Rocky Bernstein
|
# Copyright (c) 2015-2016, 2818-2021 by Rocky Bernstein
|
||||||
# Copyright (c) 2005 by Dan Pascu <dan@windowmaker.org>
|
# Copyright (c) 2005 by Dan Pascu <dan@windowmaker.org>
|
||||||
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
||||||
# Copyright (c) 1999 John Aycock
|
# Copyright (c) 1999 John Aycock
|
||||||
@@ -47,7 +47,7 @@ def disco(version, co, out=None, is_pypy=False):
|
|||||||
|
|
||||||
# store final output stream for case of error
|
# store final output stream for case of error
|
||||||
real_out = out or sys.stdout
|
real_out = out or sys.stdout
|
||||||
print("# Python %s" % version, file=real_out)
|
print("# Python %s" % ".".join([str(v) for v in version]), file=real_out)
|
||||||
if co.co_filename:
|
if co.co_filename:
|
||||||
print("# Embedded file name: %s" % co.co_filename, file=real_out)
|
print("# Embedded file name: %s" % co.co_filename, file=real_out)
|
||||||
|
|
||||||
|
@@ -642,7 +642,7 @@ def get_python_parser(
|
|||||||
|
|
||||||
# If version is a string, turn that into the corresponding float.
|
# If version is a string, turn that into the corresponding float.
|
||||||
if isinstance(version, str):
|
if isinstance(version, str):
|
||||||
version = py_str2float(version)
|
version = tuple([int(v) for v in version.split(".")[:3]])
|
||||||
|
|
||||||
# FIXME: there has to be a better way...
|
# FIXME: there has to be a better way...
|
||||||
# We could do this as a table lookup, but that would force us
|
# We could do this as a table lookup, but that would force us
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2016, 2018-2020 by Rocky Bernstein
|
# Copyright (c) 2016, 2018-2021 by Rocky Bernstein
|
||||||
# Copyright (c) 2005 by Dan Pascu <dan@windowmaker.org>
|
# Copyright (c) 2005 by Dan Pascu <dan@windowmaker.org>
|
||||||
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
||||||
# Copyright (c) 1999 John Aycock
|
# Copyright (c) 1999 John Aycock
|
||||||
@@ -105,7 +105,7 @@ class Scanner(object):
|
|||||||
self.show_asm = show_asm
|
self.show_asm = show_asm
|
||||||
self.is_pypy = is_pypy
|
self.is_pypy = is_pypy
|
||||||
|
|
||||||
if version in PYTHON_VERSIONS:
|
if version[:2] in PYTHON_VERSIONS:
|
||||||
if is_pypy:
|
if is_pypy:
|
||||||
v_str = "opcode_%spypy" % ("".join([str(v) for v in version]))
|
v_str = "opcode_%spypy" % ("".join([str(v) for v in version]))
|
||||||
else:
|
else:
|
||||||
@@ -113,7 +113,7 @@ class Scanner(object):
|
|||||||
exec("from xdis.opcodes import %s" % v_str)
|
exec("from xdis.opcodes import %s" % v_str)
|
||||||
exec("self.opc = %s" % v_str)
|
exec("self.opc = %s" % v_str)
|
||||||
else:
|
else:
|
||||||
raise TypeError("%s is not a Python version I know about" % version)
|
raise TypeError("%s is not a Python version I know about" % ".".join([str(v) for v in version]))
|
||||||
|
|
||||||
self.opname = self.opc.opname
|
self.opname = self.opc.opname
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2015-2020 by Rocky Bernstein
|
# Copyright (c) 2015-2021 by Rocky Bernstein
|
||||||
# Copyright (c) 2005 by Dan Pascu <dan@windowmaker.org>
|
# Copyright (c) 2005 by Dan Pascu <dan@windowmaker.org>
|
||||||
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
||||||
#
|
#
|
||||||
@@ -288,7 +288,7 @@ class Scanner2(Scanner):
|
|||||||
# last_offset = jump_offset
|
# last_offset = jump_offset
|
||||||
come_from_name = "COME_FROM"
|
come_from_name = "COME_FROM"
|
||||||
op_name = self.opname_for_offset(jump_offset)
|
op_name = self.opname_for_offset(jump_offset)
|
||||||
if op_name.startswith("SETUP_") and self.version == 2.7:
|
if op_name.startswith("SETUP_") and self.version[:2] == (2, 7):
|
||||||
come_from_type = op_name[len("SETUP_") :]
|
come_from_type = op_name[len("SETUP_") :]
|
||||||
if come_from_type not in ("LOOP", "EXCEPT"):
|
if come_from_type not in ("LOOP", "EXCEPT"):
|
||||||
come_from_name = "COME_FROM_%s" % come_from_type
|
come_from_name = "COME_FROM_%s" % come_from_type
|
||||||
@@ -350,12 +350,12 @@ class Scanner2(Scanner):
|
|||||||
pattr = names[oparg]
|
pattr = names[oparg]
|
||||||
elif op in self.opc.JREL_OPS:
|
elif op in self.opc.JREL_OPS:
|
||||||
# use instead: hasattr(self, 'patch_continue'): ?
|
# use instead: hasattr(self, 'patch_continue'): ?
|
||||||
if self.version == 2.7:
|
if self.version[:2] == (2, 7):
|
||||||
self.patch_continue(tokens, offset, op)
|
self.patch_continue(tokens, offset, op)
|
||||||
pattr = repr(offset + 3 + oparg)
|
pattr = repr(offset + 3 + oparg)
|
||||||
elif op in self.opc.JABS_OPS:
|
elif op in self.opc.JABS_OPS:
|
||||||
# use instead: hasattr(self, 'patch_continue'): ?
|
# use instead: hasattr(self, 'patch_continue'): ?
|
||||||
if self.version == 2.7:
|
if self.version[:2] == (2, 7):
|
||||||
self.patch_continue(tokens, offset, op)
|
self.patch_continue(tokens, offset, op)
|
||||||
pattr = repr(oparg)
|
pattr = repr(oparg)
|
||||||
elif op in self.opc.LOCAL_OPS:
|
elif op in self.opc.LOCAL_OPS:
|
||||||
@@ -515,7 +515,7 @@ class Scanner2(Scanner):
|
|||||||
while code[j] == self.opc.JUMP_ABSOLUTE:
|
while code[j] == self.opc.JUMP_ABSOLUTE:
|
||||||
j = self.prev[j]
|
j = self.prev[j]
|
||||||
if (
|
if (
|
||||||
self.version >= 2.3 and self.opname_for_offset(j) == "LIST_APPEND"
|
self.version >= (2, 3) and self.opname_for_offset(j) == "LIST_APPEND"
|
||||||
): # list comprehension
|
): # list comprehension
|
||||||
stmts.remove(s)
|
stmts.remove(s)
|
||||||
continue
|
continue
|
||||||
@@ -529,7 +529,7 @@ class Scanner2(Scanner):
|
|||||||
prev = code[self.prev[s]]
|
prev = code[self.prev[s]]
|
||||||
if (
|
if (
|
||||||
prev == self.opc.ROT_TWO
|
prev == self.opc.ROT_TWO
|
||||||
or self.version < 2.7
|
or self.version < (2, 7)
|
||||||
and prev
|
and prev
|
||||||
in (
|
in (
|
||||||
self.opc.JUMP_IF_FALSE,
|
self.opc.JUMP_IF_FALSE,
|
||||||
@@ -543,7 +543,7 @@ class Scanner2(Scanner):
|
|||||||
j = self.prev[s]
|
j = self.prev[s]
|
||||||
while code[j] in self.designator_ops:
|
while code[j] in self.designator_ops:
|
||||||
j = self.prev[j]
|
j = self.prev[j]
|
||||||
if self.version > 2.1 and code[j] == self.opc.FOR_ITER:
|
if self.version > (2, 1) and code[j] == self.opc.FOR_ITER:
|
||||||
stmts.remove(s)
|
stmts.remove(s)
|
||||||
continue
|
continue
|
||||||
last_stmt = s
|
last_stmt = s
|
||||||
@@ -563,7 +563,7 @@ class Scanner2(Scanner):
|
|||||||
jmp = self.prev[self.get_target(except_match)]
|
jmp = self.prev[self.get_target(except_match)]
|
||||||
|
|
||||||
# In Python < 2.7 we may have jumps to jumps
|
# In Python < 2.7 we may have jumps to jumps
|
||||||
if self.version < 2.7 and self.code[jmp] in self.jump_forward:
|
if self.version < (2, 7) and self.code[jmp] in self.jump_forward:
|
||||||
self.not_continue.add(jmp)
|
self.not_continue.add(jmp)
|
||||||
jmp = self.get_target(jmp)
|
jmp = self.get_target(jmp)
|
||||||
prev_offset = self.prev[except_match]
|
prev_offset = self.prev[except_match]
|
||||||
@@ -587,7 +587,7 @@ class Scanner2(Scanner):
|
|||||||
op = self.code[i]
|
op = self.code[i]
|
||||||
if op == self.opc.END_FINALLY:
|
if op == self.opc.END_FINALLY:
|
||||||
if count_END_FINALLY == count_SETUP_:
|
if count_END_FINALLY == count_SETUP_:
|
||||||
if self.version == 2.7:
|
if self.version[:2] == (2, 7):
|
||||||
assert self.code[self.prev[i]] in self.jump_forward | frozenset(
|
assert self.code[self.prev[i]] in self.jump_forward | frozenset(
|
||||||
[self.opc.RETURN_VALUE]
|
[self.opc.RETURN_VALUE]
|
||||||
)
|
)
|
||||||
@@ -649,7 +649,7 @@ class Scanner2(Scanner):
|
|||||||
# Account for the fact that < 2.7 has an explicit
|
# Account for the fact that < 2.7 has an explicit
|
||||||
# POP_TOP instruction in the equivalate POP_JUMP_IF
|
# POP_TOP instruction in the equivalate POP_JUMP_IF
|
||||||
# construct
|
# construct
|
||||||
if self.version < 2.7:
|
if self.version < (2, 7):
|
||||||
jump_forward_offset = jump_back_offset + 4
|
jump_forward_offset = jump_back_offset + 4
|
||||||
return_val_offset1 = self.prev[
|
return_val_offset1 = self.prev[
|
||||||
self.prev[self.prev[loop_end_offset]]
|
self.prev[self.prev[loop_end_offset]]
|
||||||
@@ -691,7 +691,7 @@ class Scanner2(Scanner):
|
|||||||
jump_back_offset += 1
|
jump_back_offset += 1
|
||||||
|
|
||||||
if_offset = None
|
if_offset = None
|
||||||
if self.version < 2.7:
|
if self.version < (2, 7):
|
||||||
# Look for JUMP_IF POP_TOP ...
|
# Look for JUMP_IF POP_TOP ...
|
||||||
if code[self.prev[next_line_byte]] == self.opc.POP_TOP and (
|
if code[self.prev[next_line_byte]] == self.opc.POP_TOP and (
|
||||||
code[self.prev[self.prev[next_line_byte]]] in self.pop_jump_if
|
code[self.prev[self.prev[next_line_byte]]] in self.pop_jump_if
|
||||||
@@ -703,7 +703,7 @@ class Scanner2(Scanner):
|
|||||||
if if_offset:
|
if if_offset:
|
||||||
loop_type = "while"
|
loop_type = "while"
|
||||||
self.ignore_if.add(if_offset)
|
self.ignore_if.add(if_offset)
|
||||||
if self.version < 2.7 and (
|
if self.version < (2, 7) and (
|
||||||
code[self.prev[jump_back_offset]] == self.opc.RETURN_VALUE
|
code[self.prev[jump_back_offset]] == self.opc.RETURN_VALUE
|
||||||
):
|
):
|
||||||
self.ignore_if.add(self.prev[jump_back_offset])
|
self.ignore_if.add(self.prev[jump_back_offset])
|
||||||
@@ -735,7 +735,7 @@ class Scanner2(Scanner):
|
|||||||
|
|
||||||
setup_target = self.get_target(jump_back_offset, self.opc.JUMP_ABSOLUTE)
|
setup_target = self.get_target(jump_back_offset, self.opc.JUMP_ABSOLUTE)
|
||||||
|
|
||||||
if self.version > 2.1 and code[setup_target] in (
|
if self.version > (2, 1) and code[setup_target] in (
|
||||||
self.opc.FOR_ITER,
|
self.opc.FOR_ITER,
|
||||||
self.opc.GET_ITER,
|
self.opc.GET_ITER,
|
||||||
):
|
):
|
||||||
@@ -745,7 +745,7 @@ class Scanner2(Scanner):
|
|||||||
# Look for a test condition immediately after the
|
# Look for a test condition immediately after the
|
||||||
# SETUP_LOOP while
|
# SETUP_LOOP while
|
||||||
if (
|
if (
|
||||||
self.version < 2.7
|
self.version < (2, 7)
|
||||||
and self.code[self.prev[next_line_byte]] == self.opc.POP_TOP
|
and self.code[self.prev[next_line_byte]] == self.opc.POP_TOP
|
||||||
):
|
):
|
||||||
test_op_offset = self.prev[self.prev[next_line_byte]]
|
test_op_offset = self.prev[self.prev[next_line_byte]]
|
||||||
@@ -822,7 +822,7 @@ class Scanner2(Scanner):
|
|||||||
if target != start_else:
|
if target != start_else:
|
||||||
end_else = self.get_target(jmp)
|
end_else = self.get_target(jmp)
|
||||||
if self.code[jmp] == self.opc.JUMP_FORWARD:
|
if self.code[jmp] == self.opc.JUMP_FORWARD:
|
||||||
if self.version <= 2.6:
|
if self.version <= (2, 6):
|
||||||
self.fixed_jumps[jmp] = target
|
self.fixed_jumps[jmp] = target
|
||||||
else:
|
else:
|
||||||
self.fixed_jumps[jmp] = -1
|
self.fixed_jumps[jmp] = -1
|
||||||
@@ -833,7 +833,7 @@ class Scanner2(Scanner):
|
|||||||
if end_else != start_else:
|
if end_else != start_else:
|
||||||
r_end_else = self.restrict_to_parent(end_else, parent)
|
r_end_else = self.restrict_to_parent(end_else, parent)
|
||||||
# May be able to drop the 2.7 test.
|
# May be able to drop the 2.7 test.
|
||||||
if self.version == 2.7:
|
if self.version[:2] == (2, 7):
|
||||||
self.structs.append(
|
self.structs.append(
|
||||||
{"type": "try-else", "start": i + 1, "end": r_end_else}
|
{"type": "try-else", "start": i + 1, "end": r_end_else}
|
||||||
)
|
)
|
||||||
@@ -861,7 +861,7 @@ class Scanner2(Scanner):
|
|||||||
# possibly I am "skipping over" a "pass" or null statement.
|
# possibly I am "skipping over" a "pass" or null statement.
|
||||||
|
|
||||||
test_target = target
|
test_target = target
|
||||||
if self.version < 2.7:
|
if self.version < (2, 7):
|
||||||
# Before 2.7 we have to deal with the fact that there is an extra
|
# Before 2.7 we have to deal with the fact that there is an extra
|
||||||
# POP_TOP that is logically associated with the JUMP_IF's (even though
|
# POP_TOP that is logically associated with the JUMP_IF's (even though
|
||||||
# the instance set is called "self.pop_jump_if")
|
# the instance set is called "self.pop_jump_if")
|
||||||
@@ -981,7 +981,7 @@ class Scanner2(Scanner):
|
|||||||
self.fixed_jumps[offset] = fix or match[-1]
|
self.fixed_jumps[offset] = fix or match[-1]
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
if self.version < 2.7 and parent["type"] in (
|
if self.version < (2, 7) and parent["type"] in (
|
||||||
"root",
|
"root",
|
||||||
"for-loop",
|
"for-loop",
|
||||||
"if-then",
|
"if-then",
|
||||||
@@ -997,7 +997,7 @@ class Scanner2(Scanner):
|
|||||||
self.fixed_jumps[offset] = match[-1]
|
self.fixed_jumps[offset] = match[-1]
|
||||||
return
|
return
|
||||||
else: # op != self.opc.PJIT
|
else: # op != self.opc.PJIT
|
||||||
if self.version < 2.7 and code[offset + 3] == self.opc.POP_TOP:
|
if self.version < (2, 7) and code[offset + 3] == self.opc.POP_TOP:
|
||||||
assert_offset = offset + 4
|
assert_offset = offset + 4
|
||||||
else:
|
else:
|
||||||
assert_offset = offset + 3
|
assert_offset = offset + 3
|
||||||
@@ -1039,7 +1039,7 @@ class Scanner2(Scanner):
|
|||||||
if offset in self.ignore_if:
|
if offset in self.ignore_if:
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.version == 2.7:
|
if self.version == (2, 7):
|
||||||
if (
|
if (
|
||||||
code[pre_rtarget] == self.opc.JUMP_ABSOLUTE
|
code[pre_rtarget] == self.opc.JUMP_ABSOLUTE
|
||||||
and pre_rtarget in self.stmts
|
and pre_rtarget in self.stmts
|
||||||
@@ -1109,7 +1109,7 @@ class Scanner2(Scanner):
|
|||||||
|
|
||||||
if_then_maybe = None
|
if_then_maybe = None
|
||||||
|
|
||||||
if 2.2 <= self.version <= 2.6:
|
if (2, 2) <= self.version <= (2, 6):
|
||||||
# Take the JUMP_IF target. In an "if/then", it will be
|
# Take the JUMP_IF target. In an "if/then", it will be
|
||||||
# a POP_TOP instruction and the instruction before it
|
# a POP_TOP instruction and the instruction before it
|
||||||
# will be a JUMP_FORWARD to just after the POP_TOP.
|
# will be a JUMP_FORWARD to just after the POP_TOP.
|
||||||
@@ -1159,13 +1159,13 @@ class Scanner2(Scanner):
|
|||||||
"end": pre_rtarget,
|
"end": pre_rtarget,
|
||||||
}
|
}
|
||||||
|
|
||||||
elif self.version == 2.7:
|
elif self.version[:2] == (2, 7):
|
||||||
self.structs.append(
|
self.structs.append(
|
||||||
{"type": "if-then", "start": start - 3, "end": pre_rtarget}
|
{"type": "if-then", "start": start - 3, "end": pre_rtarget}
|
||||||
)
|
)
|
||||||
|
|
||||||
# FIXME: this is yet another case were we need dominators.
|
# FIXME: this is yet another case were we need dominators.
|
||||||
if pre_rtarget not in self.linestarts or self.version < 2.7:
|
if pre_rtarget not in self.linestarts or self.version < (2, 7):
|
||||||
self.not_continue.add(pre_rtarget)
|
self.not_continue.add(pre_rtarget)
|
||||||
|
|
||||||
if rtarget < end_offset:
|
if rtarget < end_offset:
|
||||||
@@ -1194,7 +1194,7 @@ class Scanner2(Scanner):
|
|||||||
{"type": "else", "start": rtarget, "end": end_offset}
|
{"type": "else", "start": rtarget, "end": end_offset}
|
||||||
)
|
)
|
||||||
elif code_pre_rtarget == self.opc.RETURN_VALUE:
|
elif code_pre_rtarget == self.opc.RETURN_VALUE:
|
||||||
if self.version == 2.7 or pre_rtarget not in self.ignore_if:
|
if self.version[:2] == (2, 7) or pre_rtarget not in self.ignore_if:
|
||||||
# Below, 10 is exception-match. If there is an exception
|
# Below, 10 is exception-match. If there is an exception
|
||||||
# match in the compare, then this is an exception
|
# match in the compare, then this is an exception
|
||||||
# clause not an if-then clause
|
# clause not an if-then clause
|
||||||
@@ -1207,7 +1207,7 @@ class Scanner2(Scanner):
|
|||||||
)
|
)
|
||||||
self.thens[start] = rtarget
|
self.thens[start] = rtarget
|
||||||
if (
|
if (
|
||||||
self.version == 2.7
|
self.version[:2] == (2, 7)
|
||||||
or code[pre_rtarget + 1] != self.opc.JUMP_FORWARD
|
or code[pre_rtarget + 1] != self.opc.JUMP_FORWARD
|
||||||
):
|
):
|
||||||
# The below is a big hack until we get
|
# The below is a big hack until we get
|
||||||
@@ -1220,7 +1220,7 @@ class Scanner2(Scanner):
|
|||||||
# instruction before.
|
# instruction before.
|
||||||
self.fixed_jumps[offset] = rtarget
|
self.fixed_jumps[offset] = rtarget
|
||||||
if (
|
if (
|
||||||
self.version == 2.7
|
self.version[:2] == (2, 7)
|
||||||
and self.insts[
|
and self.insts[
|
||||||
self.offset2inst_index[pre[pre_rtarget]]
|
self.offset2inst_index[pre[pre_rtarget]]
|
||||||
].is_jump_target
|
].is_jump_target
|
||||||
@@ -1291,7 +1291,7 @@ class Scanner2(Scanner):
|
|||||||
# if (op in self.opc.JREL_OPS and
|
# if (op in self.opc.JREL_OPS and
|
||||||
# (self.version < 2.0 or op != self.opc.FOR_ITER)):
|
# (self.version < 2.0 or op != self.opc.FOR_ITER)):
|
||||||
label = offset + 3 + oparg
|
label = offset + 3 + oparg
|
||||||
elif self.version == 2.7 and op in self.opc.JABS_OPS:
|
elif self.version[:2] == (2, 7) and op in self.opc.JABS_OPS:
|
||||||
if op in (
|
if op in (
|
||||||
self.opc.JUMP_IF_FALSE_OR_POP,
|
self.opc.JUMP_IF_FALSE_OR_POP,
|
||||||
self.opc.JUMP_IF_TRUE_OR_POP,
|
self.opc.JUMP_IF_TRUE_OR_POP,
|
||||||
@@ -1307,7 +1307,7 @@ class Scanner2(Scanner):
|
|||||||
# We REALLY REALLY need a better way to handle control flow
|
# We REALLY REALLY need a better way to handle control flow
|
||||||
# Expecially for < 2.7
|
# Expecially for < 2.7
|
||||||
if label is not None and label != -1:
|
if label is not None and label != -1:
|
||||||
if self.version == 2.7:
|
if self.version[:2] == (2, 7):
|
||||||
# FIXME: rocky: I think we need something like this...
|
# FIXME: rocky: I think we need something like this...
|
||||||
if label in self.setup_loops:
|
if label in self.setup_loops:
|
||||||
source = self.setup_loops[label]
|
source = self.setup_loops[label]
|
||||||
@@ -1342,7 +1342,7 @@ class Scanner2(Scanner):
|
|||||||
# handle COME_FROM's from a loop inside if's
|
# handle COME_FROM's from a loop inside if's
|
||||||
# It probably should.
|
# It probably should.
|
||||||
if (
|
if (
|
||||||
self.version > 2.6
|
self.version > (2, 6)
|
||||||
or self.code[source] != self.opc.SETUP_LOOP
|
or self.code[source] != self.opc.SETUP_LOOP
|
||||||
or self.code[label] != self.opc.JUMP_FORWARD
|
or self.code[label] != self.opc.JUMP_FORWARD
|
||||||
):
|
):
|
||||||
@@ -1354,7 +1354,7 @@ class Scanner2(Scanner):
|
|||||||
elif (
|
elif (
|
||||||
op == self.opc.END_FINALLY
|
op == self.opc.END_FINALLY
|
||||||
and offset in self.fixed_jumps
|
and offset in self.fixed_jumps
|
||||||
and self.version == 2.7
|
and self.version[:2] == (2, 7)
|
||||||
):
|
):
|
||||||
label = self.fixed_jumps[offset]
|
label = self.fixed_jumps[offset]
|
||||||
targets[label] = targets.get(label, []) + [offset]
|
targets[label] = targets.get(label, []) + [offset]
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2016-2018 by Rocky Bernstein
|
# Copyright (c) 2016-2018, 2021 by Rocky Bernstein
|
||||||
"""
|
"""
|
||||||
Python 2.2 bytecode massaging.
|
Python 2.2 bytecode massaging.
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2016-2018 by Rocky Bernstein
|
# Copyright (c) 2016-2018, 2021 by Rocky Bernstein
|
||||||
"""
|
"""
|
||||||
Python 2.3 bytecode massaging.
|
Python 2.3 bytecode massaging.
|
||||||
|
|
||||||
@@ -23,6 +23,6 @@ class Scanner23(scan.Scanner24):
|
|||||||
self.opname = opcode_23.opname
|
self.opname = opcode_23.opname
|
||||||
# These are the only differences in initialization between
|
# These are the only differences in initialization between
|
||||||
# 2.3-2.6
|
# 2.3-2.6
|
||||||
self.version = 2.3
|
self.version = (2, 3)
|
||||||
self.genexpr_name = '<generator expression>'
|
self.genexpr_name = '<generator expression>'
|
||||||
return
|
return
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2016-2017 by Rocky Bernstein
|
# Copyright (c) 2016-2017, 2021 by Rocky Bernstein
|
||||||
"""
|
"""
|
||||||
Python 2.4 bytecode massaging.
|
Python 2.4 bytecode massaging.
|
||||||
|
|
||||||
@@ -10,6 +10,7 @@ import uncompyle6.scanners.scanner25 as scan
|
|||||||
|
|
||||||
# bytecode verification, verify(), uses JUMP_OPs from here
|
# bytecode verification, verify(), uses JUMP_OPs from here
|
||||||
from xdis.opcodes import opcode_24
|
from xdis.opcodes import opcode_24
|
||||||
|
|
||||||
JUMP_OPS = opcode_24.JUMP_OPS
|
JUMP_OPS = opcode_24.JUMP_OPS
|
||||||
|
|
||||||
# We base this off of 2.5 instead of the other way around
|
# We base this off of 2.5 instead of the other way around
|
||||||
@@ -23,6 +24,6 @@ class Scanner24(scan.Scanner25):
|
|||||||
# 2.4, 2.5 and 2.6
|
# 2.4, 2.5 and 2.6
|
||||||
self.opc = opcode_24
|
self.opc = opcode_24
|
||||||
self.opname = opcode_24.opname
|
self.opname = opcode_24.opname
|
||||||
self.version = 2.4
|
self.version = (2, 4)
|
||||||
self.genexpr_name = '<generator expression>'
|
self.genexpr_name = "<generator expression>"
|
||||||
return
|
return
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2015-2017 by Rocky Bernstein
|
# Copyright (c) 2015-2017, 2021 by Rocky Bernstein
|
||||||
# Copyright (c) 2005 by Dan Pascu <dan@windowmaker.org>
|
# Copyright (c) 2005 by Dan Pascu <dan@windowmaker.org>
|
||||||
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
||||||
#
|
#
|
||||||
@@ -40,7 +40,7 @@ JUMP_OPS = opcode_26.JUMP_OPS
|
|||||||
|
|
||||||
class Scanner26(scan.Scanner2):
|
class Scanner26(scan.Scanner2):
|
||||||
def __init__(self, show_asm=False):
|
def __init__(self, show_asm=False):
|
||||||
super(Scanner26, self).__init__(2.6, show_asm)
|
super(Scanner26, self).__init__((2, 6), show_asm)
|
||||||
|
|
||||||
# "setup" opcodes
|
# "setup" opcodes
|
||||||
self.setup_ops = frozenset([
|
self.setup_ops = frozenset([
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2015-2018 by Rocky Bernstein
|
# Copyright (c) 2015-2018, 2021 by Rocky Bernstein
|
||||||
"""
|
"""
|
||||||
Python 2.7 bytecode ingester.
|
Python 2.7 bytecode ingester.
|
||||||
|
|
||||||
@@ -12,77 +12,115 @@ from __future__ import print_function
|
|||||||
from uncompyle6.scanners.scanner2 import Scanner2
|
from uncompyle6.scanners.scanner2 import Scanner2
|
||||||
|
|
||||||
from uncompyle6 import PYTHON3
|
from uncompyle6 import PYTHON3
|
||||||
|
|
||||||
if PYTHON3:
|
if PYTHON3:
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
intern = sys.intern
|
intern = sys.intern
|
||||||
|
|
||||||
# bytecode verification, verify(), uses JUMP_OPs from here
|
# bytecode verification, verify(), uses JUMP_OPs from here
|
||||||
from xdis.opcodes import opcode_27
|
from xdis.opcodes import opcode_27
|
||||||
|
|
||||||
JUMP_OPS = opcode_27.JUMP_OPs
|
JUMP_OPS = opcode_27.JUMP_OPs
|
||||||
|
|
||||||
|
|
||||||
class Scanner27(Scanner2):
|
class Scanner27(Scanner2):
|
||||||
def __init__(self, show_asm=False, is_pypy=False):
|
def __init__(self, show_asm=False, is_pypy=False):
|
||||||
super(Scanner27, self).__init__(2.7, show_asm, is_pypy)
|
super(Scanner27, self).__init__((2, 7), show_asm, is_pypy)
|
||||||
|
|
||||||
# opcodes that start statements
|
# opcodes that start statements
|
||||||
self.statement_opcodes = frozenset(
|
self.statement_opcodes = frozenset(
|
||||||
self.statement_opcodes | set([
|
self.statement_opcodes
|
||||||
# New in 2.7
|
| set(
|
||||||
self.opc.SETUP_WITH,
|
[
|
||||||
self.opc.STORE_SLICE_0, self.opc.STORE_SLICE_1,
|
# New in 2.7
|
||||||
self.opc.STORE_SLICE_2, self.opc.STORE_SLICE_3,
|
self.opc.SETUP_WITH,
|
||||||
self.opc.DELETE_SLICE_0, self.opc.DELETE_SLICE_1,
|
self.opc.STORE_SLICE_0,
|
||||||
self.opc.DELETE_SLICE_2, self.opc.DELETE_SLICE_3,
|
self.opc.STORE_SLICE_1,
|
||||||
]))
|
self.opc.STORE_SLICE_2,
|
||||||
|
self.opc.STORE_SLICE_3,
|
||||||
|
self.opc.DELETE_SLICE_0,
|
||||||
|
self.opc.DELETE_SLICE_1,
|
||||||
|
self.opc.DELETE_SLICE_2,
|
||||||
|
self.opc.DELETE_SLICE_3,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
# opcodes which expect a variable number pushed values and whose
|
# opcodes which expect a variable number pushed values and whose
|
||||||
# count is in the opcode. For parsing we generally change the
|
# count is in the opcode. For parsing we generally change the
|
||||||
# opcode name to include that number.
|
# opcode name to include that number.
|
||||||
varargs_ops = set([
|
varargs_ops = set(
|
||||||
self.opc.BUILD_LIST, self.opc.BUILD_TUPLE,
|
[
|
||||||
self.opc.BUILD_SLICE, self.opc.UNPACK_SEQUENCE,
|
self.opc.BUILD_LIST,
|
||||||
self.opc.MAKE_FUNCTION, self.opc.CALL_FUNCTION,
|
self.opc.BUILD_TUPLE,
|
||||||
self.opc.MAKE_CLOSURE, self.opc.CALL_FUNCTION_VAR,
|
self.opc.BUILD_SLICE,
|
||||||
self.opc.CALL_FUNCTION_KW, self.opc.CALL_FUNCTION_VAR_KW,
|
self.opc.UNPACK_SEQUENCE,
|
||||||
self.opc.DUP_TOPX, self.opc.RAISE_VARARGS,
|
self.opc.MAKE_FUNCTION,
|
||||||
# New in Python 2.7
|
self.opc.CALL_FUNCTION,
|
||||||
self.opc.BUILD_SET, self.opc.BUILD_MAP])
|
self.opc.MAKE_CLOSURE,
|
||||||
|
self.opc.CALL_FUNCTION_VAR,
|
||||||
|
self.opc.CALL_FUNCTION_KW,
|
||||||
|
self.opc.CALL_FUNCTION_VAR_KW,
|
||||||
|
self.opc.DUP_TOPX,
|
||||||
|
self.opc.RAISE_VARARGS,
|
||||||
|
# New in Python 2.7
|
||||||
|
self.opc.BUILD_SET,
|
||||||
|
self.opc.BUILD_MAP,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
if is_pypy:
|
if is_pypy:
|
||||||
varargs_ops.add(self.opc.CALL_METHOD)
|
varargs_ops.add(self.opc.CALL_METHOD)
|
||||||
self.varargs_ops = frozenset(varargs_ops)
|
self.varargs_ops = frozenset(varargs_ops)
|
||||||
|
|
||||||
# "setup" opcodes
|
# "setup" opcodes
|
||||||
self.setup_ops = frozenset([
|
self.setup_ops = frozenset(
|
||||||
self.opc.SETUP_EXCEPT, self.opc.SETUP_FINALLY,
|
[
|
||||||
# New in 2.7
|
self.opc.SETUP_EXCEPT,
|
||||||
self.opc.SETUP_WITH])
|
self.opc.SETUP_FINALLY,
|
||||||
|
# New in 2.7
|
||||||
|
self.opc.SETUP_WITH,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
# opcodes that store values into a variable
|
# opcodes that store values into a variable
|
||||||
self.designator_ops = frozenset([
|
self.designator_ops = frozenset(
|
||||||
self.opc.STORE_FAST, self.opc.STORE_NAME,
|
[
|
||||||
self.opc.STORE_GLOBAL, self.opc.STORE_DEREF, self.opc.STORE_ATTR,
|
self.opc.STORE_FAST,
|
||||||
self.opc.STORE_SLICE_0, self.opc.STORE_SLICE_1, self.opc.STORE_SLICE_2,
|
self.opc.STORE_NAME,
|
||||||
self.opc.STORE_SLICE_3, self.opc.STORE_SUBSCR, self.opc.UNPACK_SEQUENCE,
|
self.opc.STORE_GLOBAL,
|
||||||
self.opc.JUMP_ABSOLUTE
|
self.opc.STORE_DEREF,
|
||||||
])
|
self.opc.STORE_ATTR,
|
||||||
|
self.opc.STORE_SLICE_0,
|
||||||
|
self.opc.STORE_SLICE_1,
|
||||||
|
self.opc.STORE_SLICE_2,
|
||||||
|
self.opc.STORE_SLICE_3,
|
||||||
|
self.opc.STORE_SUBSCR,
|
||||||
|
self.opc.UNPACK_SEQUENCE,
|
||||||
|
self.opc.JUMP_ABSOLUTE,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
self.pop_jump_if_or_pop = frozenset([self.opc.JUMP_IF_FALSE_OR_POP,
|
self.pop_jump_if_or_pop = frozenset(
|
||||||
self.opc.JUMP_IF_TRUE_OR_POP])
|
[self.opc.JUMP_IF_FALSE_OR_POP, self.opc.JUMP_IF_TRUE_OR_POP]
|
||||||
|
)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
from uncompyle6 import PYTHON_VERSION
|
from xdis.version_info import PYTHON_VERSION_TRIPLE
|
||||||
if PYTHON_VERSION == 2.7:
|
|
||||||
|
if PYTHON_VERSION_TRIPLE[:2] == (2, 7):
|
||||||
import inspect
|
import inspect
|
||||||
|
|
||||||
co = inspect.currentframe().f_code
|
co = inspect.currentframe().f_code
|
||||||
tokens, customize = Scanner27().ingest(co)
|
tokens, customize = Scanner27().ingest(co)
|
||||||
for t in tokens:
|
for t in tokens:
|
||||||
print(t)
|
print(t)
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
print("Need to be Python 2.7 to demo; I am %s." %
|
print("Need to be Python 2.7 to demo; I am %s." % ".".join(str(v) for v in PYTHON_VERSION_TRIPLE))
|
||||||
PYTHON_VERSION)
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2016-2019 by Rocky Bernstein
|
# Copyright (c) 2016-2019, 2021 by Rocky Bernstein
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -33,7 +33,7 @@ JUMP_OPs = opc.JUMP_OPS
|
|||||||
|
|
||||||
class Scanner37(Scanner37Base):
|
class Scanner37(Scanner37Base):
|
||||||
def __init__(self, show_asm=None):
|
def __init__(self, show_asm=None):
|
||||||
Scanner37Base.__init__(self, 3.7, show_asm)
|
Scanner37Base.__init__(self, (3, 7), show_asm)
|
||||||
return
|
return
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
@@ -55,7 +55,7 @@ class Scanner37Base(Scanner):
|
|||||||
# Ops that start SETUP_ ... We will COME_FROM with these names
|
# Ops that start SETUP_ ... We will COME_FROM with these names
|
||||||
# Some blocks and END_ statements. And they can start
|
# Some blocks and END_ statements. And they can start
|
||||||
# a new statement
|
# a new statement
|
||||||
if self.version < 3.8:
|
if self.version < (3, 8):
|
||||||
setup_ops = [
|
setup_ops = [
|
||||||
self.opc.SETUP_LOOP,
|
self.opc.SETUP_LOOP,
|
||||||
self.opc.SETUP_EXCEPT,
|
self.opc.SETUP_EXCEPT,
|
||||||
@@ -468,7 +468,7 @@ class Scanner37Base(Scanner):
|
|||||||
and self.insts[i + 1].opname == "JUMP_FORWARD"
|
and self.insts[i + 1].opname == "JUMP_FORWARD"
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.version < 3.8 and (
|
if self.version < (3, 8) and (
|
||||||
is_continue
|
is_continue
|
||||||
or (
|
or (
|
||||||
inst.offset in self.stmts
|
inst.offset in self.stmts
|
||||||
@@ -712,7 +712,7 @@ class Scanner37Base(Scanner):
|
|||||||
end = current_end
|
end = current_end
|
||||||
parent = struct
|
parent = struct
|
||||||
|
|
||||||
if self.version < 3.8 and op == self.opc.SETUP_LOOP:
|
if self.version < (3, 8) and op == self.opc.SETUP_LOOP:
|
||||||
# We categorize loop types: 'for', 'while', 'while 1' with
|
# We categorize loop types: 'for', 'while', 'while 1' with
|
||||||
# possibly suffixes '-loop' and '-else'
|
# possibly suffixes '-loop' and '-else'
|
||||||
# Try to find the jump_back instruction of the loop.
|
# Try to find the jump_back instruction of the loop.
|
||||||
@@ -820,7 +820,7 @@ class Scanner37Base(Scanner):
|
|||||||
target = inst.argval
|
target = inst.argval
|
||||||
self.fixed_jumps[offset] = target
|
self.fixed_jumps[offset] = target
|
||||||
|
|
||||||
elif self.version < 3.8 and op == self.opc.SETUP_EXCEPT:
|
elif self.version < (3, 8) and op == self.opc.SETUP_EXCEPT:
|
||||||
target = self.get_target(offset)
|
target = self.get_target(offset)
|
||||||
end = self.restrict_to_parent(target, parent)
|
end = self.restrict_to_parent(target, parent)
|
||||||
self.fixed_jumps[offset] = end
|
self.fixed_jumps[offset] = end
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2019-2020 by Rocky Bernstein
|
# Copyright (c) 2019-2021 by Rocky Bernstein
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -35,7 +35,7 @@ JUMP_OPs = opc.JUMP_OPS
|
|||||||
|
|
||||||
class Scanner38(Scanner37):
|
class Scanner38(Scanner37):
|
||||||
def __init__(self, show_asm=None):
|
def __init__(self, show_asm=None):
|
||||||
Scanner37Base.__init__(self, 3.8, show_asm)
|
Scanner37Base.__init__(self, (3, 8), show_asm)
|
||||||
self.debug = False
|
self.debug = False
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ class Scanner38(Scanner37):
|
|||||||
if self.debug and jump_back_targets:
|
if self.debug and jump_back_targets:
|
||||||
print(jump_back_targets)
|
print(jump_back_targets)
|
||||||
loop_ends = []
|
loop_ends = []
|
||||||
next_end = tokens[len(tokens)-1].off2int() + 10
|
next_end = tokens[len(tokens) - 1].off2int() + 10
|
||||||
for i, token in enumerate(tokens):
|
for i, token in enumerate(tokens):
|
||||||
opname = token.kind
|
opname = token.kind
|
||||||
offset = token.offset
|
offset = token.offset
|
||||||
@@ -70,13 +70,19 @@ class Scanner38(Scanner37):
|
|||||||
if self.debug:
|
if self.debug:
|
||||||
print("%sremove loop offset %s" % (" " * len(loop_ends), offset))
|
print("%sremove loop offset %s" % (" " * len(loop_ends), offset))
|
||||||
pass
|
pass
|
||||||
next_end = loop_ends[-1] if len(loop_ends) else tokens[len(tokens)-1].off2int() + 10
|
next_end = (
|
||||||
|
loop_ends[-1]
|
||||||
|
if len(loop_ends)
|
||||||
|
else tokens[len(tokens) - 1].off2int() + 10
|
||||||
|
)
|
||||||
|
|
||||||
if offset in jump_back_targets:
|
if offset in jump_back_targets:
|
||||||
next_end = off2int(jump_back_targets[offset], prefer_last=False)
|
next_end = off2int(jump_back_targets[offset], prefer_last=False)
|
||||||
if self.debug:
|
if self.debug:
|
||||||
print("%sadding loop offset %s ending at %s" %
|
print(
|
||||||
(' ' * len(loop_ends), offset, next_end))
|
"%sadding loop offset %s ending at %s"
|
||||||
|
% (" " * len(loop_ends), offset, next_end)
|
||||||
|
)
|
||||||
loop_ends.append(next_end)
|
loop_ends.append(next_end)
|
||||||
|
|
||||||
# Turn JUMP opcodes into "BREAK_LOOP" opcodes.
|
# Turn JUMP opcodes into "BREAK_LOOP" opcodes.
|
||||||
@@ -107,10 +113,7 @@ class Scanner38(Scanner37):
|
|||||||
jump_back_token = tokens[jump_back_index]
|
jump_back_token = tokens[jump_back_index]
|
||||||
|
|
||||||
# Is this a forward jump not next to a JUMP_BACK ? ...
|
# Is this a forward jump not next to a JUMP_BACK ? ...
|
||||||
break_loop = (
|
break_loop = token.linestart and jump_back_token != "JUMP_BACK"
|
||||||
token.linestart
|
|
||||||
and jump_back_token != "JUMP_BACK"
|
|
||||||
)
|
|
||||||
|
|
||||||
# or if there is looping jump back, then that loop
|
# or if there is looping jump back, then that loop
|
||||||
# should start before where the "break" instruction sits.
|
# should start before where the "break" instruction sits.
|
||||||
@@ -136,5 +139,4 @@ if __name__ == "__main__":
|
|||||||
print(t.format())
|
print(t.format())
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
print("Need to be Python 3.8 to demo; I am %s." %
|
print("Need to be Python 3.8 to demo; I am %s." % PYTHON_VERSION)
|
||||||
PYTHON_VERSION)
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2018-2019 by Rocky Bernstein
|
# Copyright (c) 2018-2019, 2021 by Rocky Bernstein
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@@ -398,7 +398,7 @@ def customize_for_version3(self, version):
|
|||||||
self.default(node)
|
self.default(node)
|
||||||
|
|
||||||
self.n_call = n_call
|
self.n_call = n_call
|
||||||
elif version < 3.2:
|
elif version < (3, 2):
|
||||||
|
|
||||||
def n_call(node):
|
def n_call(node):
|
||||||
mapping = self._get_mapping(node)
|
mapping = self._get_mapping(node)
|
||||||
|
Reference in New Issue
Block a user