You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-03 00:45:53 +08:00
Redo the way we handle complex literals and 3.7+ bug fixes...
In 3.7+ remove assert_expr* parser rules Fix "call" precidence in 3.7+ for it children
This commit is contained in:
@@ -96,8 +96,10 @@ def test_grammar():
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
reduced_dup_rhs = dict((k, dup_rhs[k]) for k in dup_rhs if k not in expect_dup_rhs)
|
reduced_dup_rhs = dict((k, dup_rhs[k]) for k in dup_rhs if k not in expect_dup_rhs)
|
||||||
for k in reduced_dup_rhs:
|
if reduced_dup_rhs:
|
||||||
print(k, reduced_dup_rhs[k])
|
print("\nPossible duplicate RHS that might be folded, into one of the LHS symbols")
|
||||||
|
for k in reduced_dup_rhs:
|
||||||
|
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, IS_PYPY)
|
||||||
|
@@ -37,5 +37,15 @@ def test_truediv():
|
|||||||
for y in simple_complex:
|
for y in simple_complex:
|
||||||
check_div(x, y)
|
check_div(x, y)
|
||||||
|
|
||||||
z2 = -1e1000j # Check that we can handle -inf as a complex number
|
def test_plus_minus_0j():
|
||||||
|
z1, z2 = (0j, (-0 - 0j))
|
||||||
|
assert atan2(z1.imag, -1.0) == atan2(0.0, -1.0)
|
||||||
|
assert atan2(z2.imag, -1.0), atan2(-0.0, -1.0)
|
||||||
|
|
||||||
|
# Check that we can handle -inf, and inf as a complex numbers.
|
||||||
|
# And put it in a tuple and a list to make it harder.
|
||||||
|
z1, z2 = (-1e1000j, 1e1000j)
|
||||||
|
assert z1 in [-1e1000j, 1e1000j]
|
||||||
|
assert z1 == z2
|
||||||
test_truediv()
|
test_truediv()
|
||||||
|
test_plus_minus0j()
|
||||||
|
@@ -197,7 +197,6 @@ case $PYVERSION in
|
|||||||
[test_collections.py]=1 # Investigate syntax error: self.assertEqual(p, Point(**))
|
[test_collections.py]=1 # Investigate syntax error: self.assertEqual(p, Point(**))
|
||||||
[test_compare.py]=1
|
[test_compare.py]=1
|
||||||
[test_compile.py]=1
|
[test_compile.py]=1
|
||||||
[test_complex.py]=1 # Investigate: NameError: global name 'infj' is not defined
|
|
||||||
[test_contains.py]=1 # Code "while False: yield None" is optimized away in compilation
|
[test_contains.py]=1 # Code "while False: yield None" is optimized away in compilation
|
||||||
[test_contextlib_async.py]=1 # Investigate
|
[test_contextlib_async.py]=1 # Investigate
|
||||||
[test_context.py]=1
|
[test_context.py]=1
|
||||||
@@ -208,6 +207,7 @@ case $PYVERSION in
|
|||||||
[test_dis.py]=1 # We change line numbers - duh!
|
[test_dis.py]=1 # We change line numbers - duh!
|
||||||
# ...
|
# ...
|
||||||
)
|
)
|
||||||
|
;;
|
||||||
3.8)
|
3.8)
|
||||||
SKIP_TESTS=(
|
SKIP_TESTS=(
|
||||||
[test_contains.py]=1 # Code "while False: yield None" is optimized away in compilation
|
[test_contains.py]=1 # Code "while False: yield None" is optimized away in compilation
|
||||||
|
@@ -91,8 +91,6 @@ class Python37Parser(Python37BaseParser):
|
|||||||
else_suitec ::= c_stmts
|
else_suitec ::= c_stmts
|
||||||
else_suitec ::= returns
|
else_suitec ::= returns
|
||||||
|
|
||||||
stmt ::= assert
|
|
||||||
|
|
||||||
stmt ::= classdef
|
stmt ::= classdef
|
||||||
stmt ::= call_stmt
|
stmt ::= call_stmt
|
||||||
|
|
||||||
@@ -801,16 +799,6 @@ class Python37Parser(Python37BaseParser):
|
|||||||
classdefdeco ::= classdefdeco1 store
|
classdefdeco ::= classdefdeco1 store
|
||||||
|
|
||||||
expr ::= LOAD_ASSERT
|
expr ::= LOAD_ASSERT
|
||||||
assert ::= assert_expr jmp_true LOAD_ASSERT RAISE_VARARGS_1 COME_FROM
|
|
||||||
stmt ::= assert2
|
|
||||||
assert2 ::= assert_expr jmp_true LOAD_ASSERT expr
|
|
||||||
CALL_FUNCTION_1 RAISE_VARARGS_1 COME_FROM
|
|
||||||
|
|
||||||
assert_expr ::= expr
|
|
||||||
assert_expr ::= assert_expr_or
|
|
||||||
assert_expr ::= assert_expr_and
|
|
||||||
assert_expr_or ::= assert_expr jmp_true expr
|
|
||||||
assert_expr_and ::= assert_expr jmp_false expr
|
|
||||||
|
|
||||||
ifstmt ::= testexpr _ifstmts_jump
|
ifstmt ::= testexpr _ifstmts_jump
|
||||||
|
|
||||||
@@ -971,7 +959,6 @@ class Python37Parser(Python37BaseParser):
|
|||||||
|
|
||||||
and ::= expr JUMP_IF_FALSE_OR_POP expr COME_FROM
|
and ::= expr JUMP_IF_FALSE_OR_POP expr COME_FROM
|
||||||
and ::= expr JUMP_IF_FALSE expr COME_FROM
|
and ::= expr JUMP_IF_FALSE expr COME_FROM
|
||||||
and ::= expr jmp_false expr
|
|
||||||
|
|
||||||
## FIXME: Is the below needed or is it covered above??
|
## FIXME: Is the below needed or is it covered above??
|
||||||
and ::= expr jmp_false expr COME_FROM
|
and ::= expr jmp_false expr COME_FROM
|
||||||
|
@@ -537,12 +537,12 @@ class Python37BaseParser(PythonParser):
|
|||||||
"""
|
"""
|
||||||
stmt ::= assert_pypy
|
stmt ::= assert_pypy
|
||||||
stmt ::= assert2_pypy", nop_func)
|
stmt ::= assert2_pypy", nop_func)
|
||||||
assert_pypy ::= JUMP_IF_NOT_DEBUG assert_expr jmp_true
|
assert_pypy ::= JUMP_IF_NOT_DEBUG expr jmp_true
|
||||||
LOAD_ASSERT RAISE_VARARGS_1 COME_FROM
|
LOAD_ASSERT RAISE_VARARGS_1 COME_FROM
|
||||||
assert2_pypy ::= JUMP_IF_NOT_DEBUG assert_expr jmp_true
|
assert2_pypy ::= JUMP_IF_NOT_DEBUG assert_expr jmp_true
|
||||||
LOAD_ASSERT expr CALL_FUNCTION_1
|
LOAD_ASSERT expr CALL_FUNCTION_1
|
||||||
RAISE_VARARGS_1 COME_FROM
|
RAISE_VARARGS_1 COME_FROM
|
||||||
assert2_pypy ::= JUMP_IF_NOT_DEBUG assert_expr jmp_true
|
assert2_pypy ::= JUMP_IF_NOT_DEBUG expr jmp_true
|
||||||
LOAD_ASSERT expr CALL_FUNCTION_1
|
LOAD_ASSERT expr CALL_FUNCTION_1
|
||||||
RAISE_VARARGS_1 COME_FROM,
|
RAISE_VARARGS_1 COME_FROM,
|
||||||
""",
|
""",
|
||||||
|
@@ -42,6 +42,13 @@ else:
|
|||||||
# various templates we use odd values. Avoiding equal-precedent comparisons
|
# various templates we use odd values. Avoiding equal-precedent comparisons
|
||||||
# avoids ambiguity what to do when the precedence is equal.
|
# avoids ambiguity what to do when the precedence is equal.
|
||||||
|
|
||||||
|
# The precidence of a key below applies the key, a node, and the its
|
||||||
|
# *parent*. A node however sometimes sets the precidence for its
|
||||||
|
# children. For example, "call" has precidence 2 so we don't get
|
||||||
|
# additional the additional parenthesis of: ".. op (call())". However
|
||||||
|
# for call's children, it parameters, we set the the precidence high,
|
||||||
|
# say to 100, to make sure we avoid additional prenthesis in
|
||||||
|
# call((.. op ..)).
|
||||||
|
|
||||||
PRECEDENCE = {
|
PRECEDENCE = {
|
||||||
'yield': 102,
|
'yield': 102,
|
||||||
|
@@ -47,6 +47,7 @@ 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_expr")),
|
"assert": ("%|assert %c\n", (0, "assert_expr")),
|
||||||
"assert2": ("%|assert %c, %c\n", (0, "assert_expr"), 3),
|
"assert2": ("%|assert %c, %c\n", (0, "assert_expr"), 3),
|
||||||
|
|
||||||
|
@@ -123,6 +123,8 @@ def customize_for_version35(self, version):
|
|||||||
self.n_build_list_unpack = n_build_list_unpack
|
self.n_build_list_unpack = n_build_list_unpack
|
||||||
|
|
||||||
def n_call(node):
|
def n_call(node):
|
||||||
|
p = self.prec
|
||||||
|
self.prec = 100
|
||||||
mapping = self._get_mapping(node)
|
mapping = self._get_mapping(node)
|
||||||
table = mapping[0]
|
table = mapping[0]
|
||||||
key = node
|
key = node
|
||||||
@@ -159,7 +161,7 @@ def customize_for_version35(self, version):
|
|||||||
kwargs = (argc >> 8) & 0xFF
|
kwargs = (argc >> 8) & 0xFF
|
||||||
# FIXME: handle annotation args
|
# FIXME: handle annotation args
|
||||||
if nargs > 0:
|
if nargs > 0:
|
||||||
template = ("%c(%C, ", 0, (1, nargs + 1, ", "))
|
template = ("%c(%P, ", 0, (1, nargs + 1, ", ", 100))
|
||||||
else:
|
else:
|
||||||
template = ("%c(", 0)
|
template = ("%c(", 0)
|
||||||
self.template_engine(template, node)
|
self.template_engine(template, node)
|
||||||
@@ -172,14 +174,16 @@ def customize_for_version35(self, version):
|
|||||||
self.template_engine(template, args_node)
|
self.template_engine(template, args_node)
|
||||||
else:
|
else:
|
||||||
if len(node) - nargs > 3:
|
if len(node) - nargs > 3:
|
||||||
template = ("*%c, %C)", nargs + 1, (nargs + kwargs + 1, -1, ", "))
|
template = ("*%c, %P)", nargs + 1, (nargs + kwargs + 1, -1, ", ", 100))
|
||||||
else:
|
else:
|
||||||
template = ("*%c)", nargs + 1)
|
template = ("*%c)", nargs + 1)
|
||||||
self.template_engine(template, node)
|
self.template_engine(template, node)
|
||||||
|
self.prec = p
|
||||||
self.prune()
|
self.prune()
|
||||||
else:
|
else:
|
||||||
gen_function_parens_adjust(key, node)
|
gen_function_parens_adjust(key, node)
|
||||||
|
|
||||||
|
self.prec = 100
|
||||||
self.default(node)
|
self.default(node)
|
||||||
|
|
||||||
self.n_call = n_call
|
self.n_call = n_call
|
||||||
|
@@ -171,6 +171,8 @@ from uncompyle6.semantics.consts import (
|
|||||||
|
|
||||||
|
|
||||||
from uncompyle6.show import maybe_show_tree
|
from uncompyle6.show import maybe_show_tree
|
||||||
|
from uncompyle6.util import better_repr
|
||||||
|
|
||||||
|
|
||||||
if PYTHON3:
|
if PYTHON3:
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
@@ -565,6 +567,9 @@ class SourceWalker(GenericASTTraversal, object):
|
|||||||
if n == "LOAD_CONST" and repr(n.pattr)[0] == "-":
|
if n == "LOAD_CONST" and repr(n.pattr)[0] == "-":
|
||||||
self.prec = 6
|
self.prec = 6
|
||||||
|
|
||||||
|
# print(n.kind, p, "<", self.prec)
|
||||||
|
# print(self.f.getvalue())
|
||||||
|
|
||||||
if p < self.prec:
|
if p < self.prec:
|
||||||
self.write("(")
|
self.write("(")
|
||||||
self.preorder(node[0])
|
self.preorder(node[0])
|
||||||
@@ -608,7 +613,7 @@ class SourceWalker(GenericASTTraversal, object):
|
|||||||
for item in tup:
|
for item in tup:
|
||||||
self.write(sep)
|
self.write(sep)
|
||||||
l += len(sep)
|
l += len(sep)
|
||||||
s = repr(item)
|
s = better_repr(item)
|
||||||
l += len(s)
|
l += len(s)
|
||||||
self.write(s)
|
self.write(s)
|
||||||
sep = ","
|
sep = ","
|
||||||
@@ -627,22 +632,10 @@ class SourceWalker(GenericASTTraversal, object):
|
|||||||
attr = node.attr
|
attr = node.attr
|
||||||
data = node.pattr
|
data = node.pattr
|
||||||
datatype = type(data)
|
datatype = type(data)
|
||||||
if isinstance(data, float) and str(data) in frozenset(
|
if isinstance(data, float) :
|
||||||
["nan", "-nan", "inf", "-inf"]
|
self.write(better_repr(data))
|
||||||
):
|
elif isinstance(data, complex):
|
||||||
# float values 'nan' and 'inf' are not directly
|
self.write(better_repr(data))
|
||||||
# representable in Python before Python 3.5. In Python 3.5
|
|
||||||
# it is accessible via a library constant math.inf. So we
|
|
||||||
# will canonicalize representation of these value as
|
|
||||||
# float('nan') and float('inf')
|
|
||||||
self.write("float('%s')" % data)
|
|
||||||
elif isinstance(data, complex) and str(data.imag) in frozenset(
|
|
||||||
["nan", "-nan", "inf", "-inf"]
|
|
||||||
):
|
|
||||||
# Likewise, complex values with 'nan' and 'inf' are not
|
|
||||||
# directly representable in Python. So we will
|
|
||||||
# canonicalize like we did above.
|
|
||||||
self.write("complex('%s%sj')" % (data.real, data.imag))
|
|
||||||
elif isinstance(datatype, int) and data == minint:
|
elif isinstance(datatype, int) and data == minint:
|
||||||
# convert to hex, since decimal representation
|
# convert to hex, since decimal representation
|
||||||
# would result in 'LOAD_CONST; UNARY_NEGATIVE'
|
# would result in 'LOAD_CONST; UNARY_NEGATIVE'
|
||||||
|
@@ -121,9 +121,9 @@ class TreeTransform(GenericASTTraversal, object):
|
|||||||
assert jump_cond == "jmp_false"
|
assert jump_cond == "jmp_false"
|
||||||
kind = "assert2not"
|
kind = "assert2not"
|
||||||
|
|
||||||
if call[0] != "LOAD_ASSERT":
|
LOAD_ASSERT = call[0].first_child()
|
||||||
|
if LOAD_ASSERT != "LOAD_ASSERT":
|
||||||
return node
|
return node
|
||||||
LOAD_ASSERT = call[0]
|
|
||||||
if isinstance(call[1], SyntaxTree):
|
if isinstance(call[1], SyntaxTree):
|
||||||
expr = call[1][0]
|
expr = call[1][0]
|
||||||
node = SyntaxTree(
|
node = SyntaxTree(
|
||||||
|
Reference in New Issue
Block a user