diff --git a/test/Makefile b/test/Makefile index 04546f64..0869dae5 100644 --- a/test/Makefile +++ b/test/Makefile @@ -268,6 +268,7 @@ check-bytecode-3.6: #: Check deparsing Python 3.7 check-bytecode-3.7: + $(PYTHON) test_pythonlib.py --bytecode-3.7-run --verify-run $(PYTHON) test_pythonlib.py --bytecode-3.7 --weak-verify #: Check deparsing Python 3.8 diff --git a/test/bytecode_3.7_run/01_and_not_else.pyc b/test/bytecode_3.7_run/01_and_not_else.pyc new file mode 100644 index 00000000..797183f5 Binary files /dev/null and b/test/bytecode_3.7_run/01_and_not_else.pyc differ diff --git a/test/simple_source/bug37/01_and_not_else.py b/test/simple_source/bug37/01_and_not_else.py new file mode 100644 index 00000000..3a51716a --- /dev/null +++ b/test/simple_source/bug37/01_and_not_else.py @@ -0,0 +1,16 @@ +# From 3.7.3 base64.py +# Bug was handling "and not" in an +# if/else in the presence of better Python bytecode generatation + +# RUNNABLE! +def foo(foldnuls, word): + x = 5 if foldnuls and not word else 6 + return x + +for expect, foldnuls, word in ( + (6, True, True), + (5, True, False), + (6, False, True), + (6, False, False) + ): + assert foo(foldnuls, word) == expect diff --git a/uncompyle6/parsers/parse37.py b/uncompyle6/parsers/parse37.py index 7185a117..dc2a63d8 100644 --- a/uncompyle6/parsers/parse37.py +++ b/uncompyle6/parsers/parse37.py @@ -111,6 +111,12 @@ class Python37Parser(Python36Parser): ifelsestmt ::= testexpr c_stmts_opt jf_cfs else_suite opt_come_from_except _ifstmts_jump ::= c_stmts_opt come_froms + + and_not ::= expr jmp_false expr POP_JUMP_IF_TRUE + + expr ::= conditional37 + conditional37 ::= and_not expr JUMP_FORWARD COME_FROM expr COME_FROM + """ def customize_grammar_rules(self, tokens, customize): diff --git a/uncompyle6/semantics/customize37.py b/uncompyle6/semantics/customize37.py index d756920c..e0c67ced 100644 --- a/uncompyle6/semantics/customize37.py +++ b/uncompyle6/semantics/customize37.py @@ -24,6 +24,8 @@ def customize_for_version37(self, version): PRECEDENCE['attribute37'] = 2 TABLE_DIRECT.update({ + 'and_not': ( '%c and not %c', + (0, 'expr'), (2, 'expr') ), 'async_forelse_stmt': ( '%|async for %c in %c:\n%+%c%-%|else:\n%+%c%-\n\n', (7, 'store'), (1, 'expr'), (17, 'for_block'), (25, 'else_suite') ), @@ -54,5 +56,6 @@ def customize_for_version37(self, version): (0, 19 ) ), 'compare_chained2c_37': ( '%[3]{pattr.replace("-", " ")} %p %p', (0, 19), (6, 19) ), + 'conditional37': ( '%p if %p else %p', (1, 'expr', 27), (0, 27), (4, 'expr', 27) ), })