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:
rocky
2019-12-18 12:00:33 -05:00
parent e39c6c7f0a
commit 28d9e66a53
10 changed files with 44 additions and 40 deletions

View File

@@ -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)
for k in reduced_dup_rhs:
print(k, reduced_dup_rhs[k])
if reduced_dup_rhs:
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
s = get_scanner(PYTHON_VERSION, IS_PYPY)

View File

@@ -37,5 +37,15 @@ def test_truediv():
for y in simple_complex:
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_plus_minus0j()

View File

@@ -197,7 +197,6 @@ case $PYVERSION in
[test_collections.py]=1 # Investigate syntax error: self.assertEqual(p, Point(**))
[test_compare.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_contextlib_async.py]=1 # Investigate
[test_context.py]=1
@@ -208,6 +207,7 @@ case $PYVERSION in
[test_dis.py]=1 # We change line numbers - duh!
# ...
)
;;
3.8)
SKIP_TESTS=(
[test_contains.py]=1 # Code "while False: yield None" is optimized away in compilation

View File

@@ -91,8 +91,6 @@ class Python37Parser(Python37BaseParser):
else_suitec ::= c_stmts
else_suitec ::= returns
stmt ::= assert
stmt ::= classdef
stmt ::= call_stmt
@@ -801,16 +799,6 @@ class Python37Parser(Python37BaseParser):
classdefdeco ::= classdefdeco1 store
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
@@ -971,7 +959,6 @@ class Python37Parser(Python37BaseParser):
and ::= expr JUMP_IF_FALSE_OR_POP 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??
and ::= expr jmp_false expr COME_FROM

View File

@@ -537,12 +537,12 @@ class Python37BaseParser(PythonParser):
"""
stmt ::= assert_pypy
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
assert2_pypy ::= JUMP_IF_NOT_DEBUG assert_expr jmp_true
LOAD_ASSERT expr CALL_FUNCTION_1
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
RAISE_VARARGS_1 COME_FROM,
""",

View File

@@ -42,6 +42,13 @@ else:
# various templates we use odd values. Avoiding equal-precedent comparisons
# 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 = {
'yield': 102,

View File

@@ -47,6 +47,7 @@ def customize_for_version(self, is_pypy, version):
# Without PyPy
#######################
TABLE_DIRECT.update({
# "assert" and "assert_expr" are added via transform rules.
"assert": ("%|assert %c\n", (0, "assert_expr")),
"assert2": ("%|assert %c, %c\n", (0, "assert_expr"), 3),

View File

@@ -123,6 +123,8 @@ def customize_for_version35(self, version):
self.n_build_list_unpack = n_build_list_unpack
def n_call(node):
p = self.prec
self.prec = 100
mapping = self._get_mapping(node)
table = mapping[0]
key = node
@@ -159,7 +161,7 @@ def customize_for_version35(self, version):
kwargs = (argc >> 8) & 0xFF
# FIXME: handle annotation args
if nargs > 0:
template = ("%c(%C, ", 0, (1, nargs + 1, ", "))
template = ("%c(%P, ", 0, (1, nargs + 1, ", ", 100))
else:
template = ("%c(", 0)
self.template_engine(template, node)
@@ -172,14 +174,16 @@ def customize_for_version35(self, version):
self.template_engine(template, args_node)
else:
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:
template = ("*%c)", nargs + 1)
self.template_engine(template, node)
self.prec = p
self.prune()
else:
gen_function_parens_adjust(key, node)
self.prec = 100
self.default(node)
self.n_call = n_call

View File

@@ -171,6 +171,8 @@ from uncompyle6.semantics.consts import (
from uncompyle6.show import maybe_show_tree
from uncompyle6.util import better_repr
if PYTHON3:
from io import StringIO
@@ -565,6 +567,9 @@ class SourceWalker(GenericASTTraversal, object):
if n == "LOAD_CONST" and repr(n.pattr)[0] == "-":
self.prec = 6
# print(n.kind, p, "<", self.prec)
# print(self.f.getvalue())
if p < self.prec:
self.write("(")
self.preorder(node[0])
@@ -608,7 +613,7 @@ class SourceWalker(GenericASTTraversal, object):
for item in tup:
self.write(sep)
l += len(sep)
s = repr(item)
s = better_repr(item)
l += len(s)
self.write(s)
sep = ","
@@ -627,22 +632,10 @@ class SourceWalker(GenericASTTraversal, object):
attr = node.attr
data = node.pattr
datatype = type(data)
if isinstance(data, float) and str(data) in frozenset(
["nan", "-nan", "inf", "-inf"]
):
# float values 'nan' and 'inf' are not directly
# 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))
if isinstance(data, float) :
self.write(better_repr(data))
elif isinstance(data, complex):
self.write(better_repr(data))
elif isinstance(datatype, int) and data == minint:
# convert to hex, since decimal representation
# would result in 'LOAD_CONST; UNARY_NEGATIVE'

View File

@@ -121,9 +121,9 @@ class TreeTransform(GenericASTTraversal, object):
assert jump_cond == "jmp_false"
kind = "assert2not"
if call[0] != "LOAD_ASSERT":
LOAD_ASSERT = call[0].first_child()
if LOAD_ASSERT != "LOAD_ASSERT":
return node
LOAD_ASSERT = call[0]
if isinstance(call[1], SyntaxTree):
expr = call[1][0]
node = SyntaxTree(