Sync with decompyle3

Better PyPy 3.7 tolerance
This commit is contained in:
rocky
2022-09-17 01:59:42 -04:00
parent f913306070
commit a68f440d6f
5 changed files with 119 additions and 45 deletions

View File

@@ -29,7 +29,19 @@ function displaytime {
# Python version setup # Python version setup
FULLVERSION=$(pyenv local) FULLVERSION=$(pyenv local)
PYVERSION=${FULLVERSION%.*} PYVERSION=${FULLVERSION%.*}
MINOR=${FULLVERSION##?.?.}
if [[ $PYVERSION =~ 'pypy' ]] ; then
IS_PYPY=1
else
IS_PYPY=0
fi
if [[ $FULLVERSION =~ pypy([2-3])\.([7-9]) ]]; then
MAJOR="${BASH_REMATCH[1]}"
MINOR="${BASH_REMATCH[2]}"
else
MINOR=${FULLVERSION##?.?.}
fi
STOP_ONERROR=${STOP_ONERROR:-1} STOP_ONERROR=${STOP_ONERROR:-1}
@@ -150,7 +162,12 @@ done
mkdir $TESTDIR || exit $? mkdir $TESTDIR || exit $?
cp -r ${PYENV_ROOT}/versions/${PYVERSION}.${MINOR}/lib/python${PYVERSION}/test $TESTDIR
if ((IS_PYPY)); then
cp -r ${PYENV_ROOT}/versions/${PYVERSION}.${MINOR}/lib-python/${MAJOR}/test $TESTDIR
else
cp -r ${PYENV_ROOT}/versions/${PYVERSION}.${MINOR}/lib/python${PYVERSION}/test $TESTDIR
fi
if [[ $PYVERSION == 3.2 ]] ; then if [[ $PYVERSION == 3.2 ]] ; then
cp ${PYENV_ROOT}/versions/${PYVERSION}.${MINOR}/lib/python${PYVERSION}/test/* $TESTDIR cp ${PYENV_ROOT}/versions/${PYVERSION}.${MINOR}/lib/python${PYVERSION}/test/* $TESTDIR
cd $TESTDIR cd $TESTDIR
@@ -209,7 +226,11 @@ for file in $files; do
((i++)) ((i++))
# (( i > 40 )) && break # (( i > 40 )) && break
short_name=$(basename $file .py) short_name=$(basename $file .py)
decompiled_file=$short_name-${PYVERSION}.pyc if ((IS_PYPY)); then
decompiled_file=$short_name-${MAJOR}.${MINOR}.pyc
else
decompiled_file=$short_name-${PYVERSION}.pyc
fi
$fulldir/compile-file.py $file && \ $fulldir/compile-file.py $file && \
mv $file{,.orig} && \ mv $file{,.orig} && \
echo ========== $(date +%X) Decompiling $file =========== echo ========== $(date +%X) Decompiling $file ===========

View File

@@ -138,7 +138,8 @@ class Python37Parser(Python37BaseParser):
returns ::= _stmts return returns ::= _stmts return
stmt ::= genexpr_func stmt ::= genexpr_func
genexpr_func ::= LOAD_ARG _come_froms FOR_ITER store comp_iter JUMP_BACK genexpr_func ::= LOAD_ARG _come_froms FOR_ITER store comp_iter
_come_froms JUMP_BACK _come_froms
""" """
pass pass
@@ -1365,7 +1366,7 @@ class Python37Parser(Python37BaseParser):
genexpr_func_async ::= LOAD_ARG func_async_prefix genexpr_func_async ::= LOAD_ARG func_async_prefix
store func_async_middle comp_iter store func_async_middle comp_iter
JUMP_LOOP COME_FROM JUMP_BACK COME_FROM
POP_TOP POP_TOP POP_TOP POP_EXCEPT POP_TOP POP_TOP POP_TOP POP_TOP POP_EXCEPT POP_TOP
# FIXME this is a workaround for probalby some bug in the Earley parser # FIXME this is a workaround for probalby some bug in the Earley parser
@@ -1377,7 +1378,7 @@ class Python37Parser(Python37BaseParser):
list_afor2 ::= func_async_prefix list_afor2 ::= func_async_prefix
store func_async_middle list_iter store func_async_middle list_iter
JUMP_LOOP COME_FROM JUMP_BACK COME_FROM
POP_TOP POP_TOP POP_TOP POP_EXCEPT POP_TOP POP_TOP POP_TOP POP_TOP POP_EXCEPT POP_TOP
list_comp_async ::= BUILD_LIST_0 LOAD_ARG list_afor2 list_comp_async ::= BUILD_LIST_0 LOAD_ARG list_afor2
@@ -1463,13 +1464,13 @@ class Python37Parser(Python37BaseParser):
genexpr_func_async ::= LOAD_ARG async_iter genexpr_func_async ::= LOAD_ARG async_iter
store_async_iter_end store_async_iter_end
comp_iter comp_iter
JUMP_LOOP COME_FROM JUMP_BACK COME_FROM
POP_TOP POP_TOP POP_TOP POP_EXCEPT POP_TOP POP_TOP POP_TOP POP_TOP POP_EXCEPT POP_TOP
list_afor2 ::= async_iter list_afor2 ::= async_iter
store store
list_iter list_iter
JUMP_LOOP JUMP_BACK
COME_FROM_FINALLY COME_FROM_FINALLY
END_ASYNC_FOR END_ASYNC_FOR
@@ -1479,7 +1480,7 @@ class Python37Parser(Python37BaseParser):
store store
func_async_middle func_async_middle
set_iter set_iter
JUMP_LOOP COME_FROM JUMP_BACK COME_FROM
POP_TOP POP_TOP POP_TOP POP_EXCEPT POP_TOP POP_TOP POP_TOP POP_TOP POP_EXCEPT POP_TOP
set_afor2 ::= expr_or_arg set_afor2 ::= expr_or_arg
@@ -1490,7 +1491,7 @@ class Python37Parser(Python37BaseParser):
set_iter_async ::= async_iter set_iter_async ::= async_iter
store store
set_iter set_iter
JUMP_LOOP JUMP_BACK
_come_froms _come_froms
END_ASYNC_FOR END_ASYNC_FOR

View File

@@ -17,7 +17,13 @@
""" """
from uncompyle6.parsers.treenode import SyntaxTree from uncompyle6.parsers.treenode import SyntaxTree
from uncompyle6.semantics.consts import INDENT_PER_LEVEL, NO_PARENTHESIS_EVER, PRECEDENCE, TABLE_R, TABLE_DIRECT from uncompyle6.semantics.consts import (
INDENT_PER_LEVEL,
NO_PARENTHESIS_EVER,
PRECEDENCE,
TABLE_R,
TABLE_DIRECT,
)
from uncompyle6.semantics.helper import flatten_list from uncompyle6.semantics.helper import flatten_list
from uncompyle6.scanners.tok import Token from uncompyle6.scanners.tok import Token
@@ -27,22 +33,29 @@ def customize_for_version(self, is_pypy, version):
######################## ########################
# PyPy changes # PyPy changes
####################### #######################
# fmt: off
TABLE_DIRECT.update({ TABLE_DIRECT.update({
"assert": ("%|assert %c\n", 0),
"assert_pypy": ( '%|assert %c\n' , (1, 'assert_expr') ),
# This is as a result of an if transformation
'assert0_pypy': ( '%|assert %c\n' , 0),
'assert_not_pypy': ( '%|assert not %c\n' , (1, 'assert_exp') ), "assert": ("%|assert %c\n", 0),
'assert2_not_pypy': ( '%|assert not %c, %c\n' , (1, 'assert_exp'), # This can happen as a result of an if transformation
(4, 'expr') ), "assert2": ("%|assert %c, %c\n", 0, 3),
'assert2_pypy': ( '%|assert %c, %c\n' , (1, 'assert_expr'), "assert_pypy": ( "%|assert %c\n" , (1, "assert_expr") ),
(4, 'expr') ), # This is as a result of an if transformation
'try_except_pypy': ( '%|try:\n%+%c%-%c\n\n', 1, 2 ), 'assert0_pypy': ( "%|assert %c\n" , 0),
'tryfinallystmt_pypy': ( '%|try:\n%+%c%-%|finally:\n%+%c%-\n\n', 1, 3 ),
'assign3_pypy': ( '%|%c, %c, %c = %c, %c, %c\n', 5, 4, 3, 0, 1, 2 ), 'assert_not_pypy': ( "%|assert not %c\n" , (1, "assert_exp") ),
'assign2_pypy': ( '%|%c, %c = %c, %c\n', 3, 2, 0, 1), "assert2_not_pypy": (
"%|assert not %c, %c\n",
(1, "assert_exp"),
(4, "expr"),
),
"try_except_pypy": ( "%|try:\n%+%c%-%c\n\n", 1, 2 ),
"tryfinallystmt_pypy": ( "%|try:\n%+%c%-%|finally:\n%+%c%-\n\n", 1, 3 ),
"assign3_pypy": ( "%|%c, %c, %c = %c, %c, %c\n", 5, 4, 3, 0, 1, 2 ),
"assign2_pypy": ( "%|%c, %c = %c, %c\n", 3, 2, 0, 1),
}) })
# fmt: on
if version[:2] >= (3, 7): if version[:2] >= (3, 7):
@@ -53,12 +66,18 @@ def customize_for_version(self, is_pypy, version):
kw_names = node[-2] kw_names = node[-2]
assert kw_names == "pypy_kw_keys" assert kw_names == "pypy_kw_keys"
flat_elems = flatten_list(node[1:-2])
n = len(flat_elems)
assert n == arg_count
kwargs_names = kw_names[0].attr kwargs_names = kw_names[0].attr
kwarg_count = len(kwargs_names) kwarg_count = len(kwargs_names)
pos_argc = arg_count - kwarg_count pos_argc = arg_count - kwarg_count
flat_elems = flatten_list(node[1:-2])
n = len(flat_elems)
assert n == arg_count, "n: %s, arg_count: %s\n%s" % (
n,
arg_count,
node,
)
sep = "" sep = ""
for i in range(pos_argc): for i in range(pos_argc):
@@ -95,20 +114,23 @@ def customize_for_version(self, is_pypy, version):
######################## ########################
# Without PyPy # Without PyPy
####################### #######################
TABLE_DIRECT.update({ TABLE_DIRECT.update(
# "assert" and "assert_expr" are added via transform rules. {
"assert": ("%|assert %c\n", 0), # "assert" and "assert_expr" are added via transform rules.
"assert2": ("%|assert %c, %c\n", 0, 3), "assert": ("%|assert %c\n", 0),
"assert2": ("%|assert %c, %c\n", 0, 3),
# Created only via transformation # Created only via transformation
"assertnot": ("%|assert not %p\n", (0, PRECEDENCE['unary_not'])), "assertnot": ("%|assert not %p\n", (0, PRECEDENCE["unary_not"])),
"assert2not": ( "%|assert not %p, %c\n" , "assert2not": (
(0, PRECEDENCE['unary_not']), 3 ), "%|assert not %p, %c\n",
(0, PRECEDENCE["unary_not"]),
"assign2": ("%|%c, %c = %c, %c\n", 3, 4, 0, 1), 3,
"assign3": ("%|%c, %c, %c = %c, %c, %c\n", 5, 6, 7, 0, 1, 2), ),
"try_except": ("%|try:\n%+%c%-%c\n\n", 1, 3), "assign2": ("%|%c, %c = %c, %c\n", 3, 4, 0, 1),
}) "assign3": ("%|%c, %c, %c = %c, %c, %c\n", 5, 6, 7, 0, 1, 2),
"try_except": ("%|try:\n%+%c%-%c\n\n", 1, 3),
}
)
if version >= (3, 0): if version >= (3, 0):
if version >= (3, 2): if version >= (3, 2):
TABLE_DIRECT.update( TABLE_DIRECT.update(
@@ -187,6 +209,7 @@ def customize_for_version(self, is_pypy, version):
} }
) )
if version == (2, 4): if version == (2, 4):
def n_iftrue_stmt24(node): def n_iftrue_stmt24(node):
self.template_engine(("%c", 0), node) self.template_engine(("%c", 0), node)
self.default(node) self.default(node)
@@ -195,6 +218,7 @@ def customize_for_version(self, is_pypy, version):
self.n_iftrue_stmt24 = n_iftrue_stmt24 self.n_iftrue_stmt24 = n_iftrue_stmt24
elif version < (1, 4): elif version < (1, 4):
from uncompyle6.semantics.customize14 import customize_for_version14 from uncompyle6.semantics.customize14 import customize_for_version14
customize_for_version14(self, version) customize_for_version14(self, version)
def n_call(node): def n_call(node):
@@ -210,9 +234,16 @@ def customize_for_version(self, is_pypy, version):
sep = ", " sep = ", "
self.write(")") self.write(")")
else: else:
self.template_engine(("%p(%P)", self.template_engine(
(0, "expr", 100), (1,-1,", ", NO_PARENTHESIS_EVER)), node) (
"%p(%P)",
(0, "expr", 100),
(1, -1, ", ", NO_PARENTHESIS_EVER),
),
node,
)
self.prune() self.prune()
self.n_call = n_call self.n_call = n_call
else: # 1.0 <= version <= 2.3: else: # 1.0 <= version <= 2.3:

View File

@@ -167,6 +167,8 @@ def customize_for_version36(self, version):
if node == "classdefdeco2": if node == "classdefdeco2":
if isinstance(node[1][1].attr, str): if isinstance(node[1][1].attr, str):
class_name = node[1][1].attr class_name = node[1][1].attr
if self.is_pypy and class_name.find("<locals>") > 0:
class_name = class_name.split(".")[-1]
else: else:
class_name = node[1][2].attr class_name = node[1][2].attr
build_class = node build_class = node

View File

@@ -97,9 +97,12 @@ class ComprehensionMixin:
self.prec = p self.prec = p
def comprehension_walk( def comprehension_walk(
self, node, iter_index: Optional[int], code_index: int = -5, self,
node,
iter_index: Optional[int],
code_index: int = -5,
): ):
p = self.prec p: int = self.prec
self.prec = PRECEDENCE["lambda_body"] - 1 self.prec = PRECEDENCE["lambda_body"] - 1
# FIXME: clean this up # FIXME: clean this up
@@ -152,6 +155,22 @@ class ComprehensionMixin:
while len(tree) == 1: while len(tree) == 1:
tree = tree[0] tree = tree[0]
if tree == "stmts":
# FIXME: rest is a return None?
# Verify this
# rest = tree[1:]
tree = tree[0]
elif tree == "lambda_start":
assert len(tree) <= 3
tree = tree[-2]
if tree == "return_expr_lambda":
tree = tree[1]
pass
if tree in ("genexpr_func_async",):
if tree[3] == "comp_iter":
iter_index = 3
n = tree[iter_index] n = tree[iter_index]
assert n == "comp_iter", n.kind assert n == "comp_iter", n.kind