diff --git a/test/simple_source/bug37/02_and_or.py b/test/simple_source/bug37/02_and_or.py new file mode 100644 index 00000000..281d1e71 --- /dev/null +++ b/test/simple_source/bug37/02_and_or.py @@ -0,0 +1,42 @@ +# from 3.7 decompyle3/pytest/validate.py +# 3.7 changes changes "and" to use JUMP_IF_FALSE_OR_POP instead of +# POP_JUMP_IF_FALSE + +# RUNNABLE! +def are_instructions_equal(a, b, c, d): + return a and (b or c) and d + +for a, b, c, d, expect in ( + (True, True, False, True, True), + (True, False, True, True, True), + (False, False, True, True, False), + (True, False, True, False, False), + ): + assert are_instructions_equal(a, b, c, d) == expect + + +# FIXME: figure out how to fix properly, and test. +# from 3.7 decompyle3/semantics/pysource.py + +# Bug *is* miscompiling to +# if a: +# if b or c: +# d = 1 +# else: +# d = 2 + +def n_alias(a, b, c, d=3): + if a and b or c: + d = 1 + else: + d = 2 + return d + +for a, b, c, expect in ( + (True, True, False, 1), + (True, False, True, 1), + # (True, False, False, 2), # miscompiles + # (False, False, True, 1), # miscompiles + (False, False, False, 2), + ): + assert n_alias(a, b, c) == expect, f"{a}, {b}, {c}, {expect}" diff --git a/test/simple_source/bug37/03_jump_to_jump.py b/test/simple_source/bug37/03_jump_to_jump.py new file mode 100644 index 00000000..8bd5ff46 --- /dev/null +++ b/test/simple_source/bug37/03_jump_to_jump.py @@ -0,0 +1,25 @@ +# From uncompyle6/verify.py +# Bug was POP_JUMP offset to short so we have a POP_JUMP +# to a JUMP_ABSOULTE and this messes up reduction rule checking. + +def cmp_code_objects(member, a, tokens1, tokens2, verify, f): + for member in members: + while a: + # Increase the bytecode length of the while statement + x = 1; x = 2; x = 3; x = 4; x = 5; x = 6; x = 7; x = 8 + x = 1; x = 2; x = 3; x = 4; x = 5; x = 6; x = 7; x = 8 + x = 1; x = 2; x = 3; x = 4; x = 5; x = 6; x = 7; x = 8 + x = 1; x = 2; x = 3; x = 4; x = 5; x = 6; x = 7; x = 8 + x = 1; x = 2; x = 3; x = 4; x = 5; x = 6; x = 7; x = 8 + x = 1; x = 2; x = 3; x = 4; x = 5; x = 6; x = 7; x = 8 + x = 49; x = 50; x = 51; x = 52; x = 53; + if tokens1: + if tokens2: + continue + elif f: + continue + else: + a = 2 + + i1 += 1 + x = 54 # comment this out and we're good diff --git a/uncompyle6/semantics/customize37.py b/uncompyle6/semantics/customize37.py index c559bfde..ba77f407 100644 --- a/uncompyle6/semantics/customize37.py +++ b/uncompyle6/semantics/customize37.py @@ -70,4 +70,6 @@ def customize_for_version37(self, version): 'testfalse_not_or': ( "not %c or %c", (0, "expr"), (2, "expr") ), + 'testfalse_not_and': ( "not (%c)", 0 ), + }) diff --git a/uncompyle6/semantics/transform.py b/uncompyle6/semantics/transform.py index b0a80060..d521f7c5 100644 --- a/uncompyle6/semantics/transform.py +++ b/uncompyle6/semantics/transform.py @@ -243,9 +243,7 @@ class TreeTransform(GenericASTTraversal, object): ) node[3] = elifelse_stmt else: - elif_stmt = SyntaxTree( - "elifstmt", [n[0], n[else_suite_index]] - ) + elif_stmt = SyntaxTree("elifstmt", [n[0], n[else_suite_index]]) node[3] = elif_stmt node.transformed_by = "n_ifelsestmt" @@ -260,11 +258,11 @@ class TreeTransform(GenericASTTraversal, object): def n_list_for(self, list_for_node): expr = list_for_node[0] - if (expr == "expr" and expr[0] == "get_iter"): + if expr == "expr" and expr[0] == "get_iter": # Remove extraneous get_iter() inside the "for" of a comprehension assert expr[0][0] == "expr" list_for_node[0] = expr[0][0] - list_for_node.transformed_by="n_list_for", + list_for_node.transformed_by = ("n_list_for",) return list_for_node def traverse(self, node, is_lambda=False):