diff --git a/test/bytecode_3.0_run/06_listcomp.pyc b/test/bytecode_3.0_run/06_listcomp.pyc index 90799847..66e65d44 100644 Binary files a/test/bytecode_3.0_run/06_listcomp.pyc and b/test/bytecode_3.0_run/06_listcomp.pyc differ diff --git a/test/bytecode_3.7_run/06_listcomp.pyc b/test/bytecode_3.7_run/06_listcomp.pyc new file mode 100644 index 00000000..08174ae6 Binary files /dev/null and b/test/bytecode_3.7_run/06_listcomp.pyc differ diff --git a/test/simple_source/bug30/06_listcomp.py b/test/simple_source/bug30/06_listcomp.py index 5ee9c295..98a99fe6 100644 --- a/test/simple_source/bug30/06_listcomp.py +++ b/test/simple_source/bug30/06_listcomp.py @@ -22,3 +22,11 @@ def columnize(l): return [i for i in range(len(l)) if not isinstance(l[i], str)] assert [0, 2] == columnize([1, 'a', 2]) + +# From 3.7 test_generators +# Bug was in handling the way list_if is optimized in 3.7+; +# We need list_if37 and compare_chained37. +def init_board(c): + return [io for io in c if 3 <= io < 5] + +assert init_board(list(range(6))) == [3, 4] diff --git a/uncompyle6/parsers/parse37.py b/uncompyle6/parsers/parse37.py index 0ddfcd64..057bf8bb 100644 --- a/uncompyle6/parsers/parse37.py +++ b/uncompyle6/parsers/parse37.py @@ -656,6 +656,7 @@ class Python37Parser(Python37BaseParser): testtrue ::= compare_chained37 testfalse ::= compare_chained37_false + compare_chained ::= compare_chained37 compare_chained37 ::= expr compare_chained1a_37 compare_chained37 ::= expr compare_chained1b_37 @@ -668,7 +669,8 @@ class Python37Parser(Python37BaseParser): compare_chained1a_37 ::= expr DUP_TOP ROT_THREE COMPARE_OP POP_JUMP_IF_FALSE compare_chained2a_37 COME_FROM POP_TOP COME_FROM compare_chained1b_37 ::= expr DUP_TOP ROT_THREE COMPARE_OP POP_JUMP_IF_FALSE - compare_chained2b_37 POP_TOP JUMP_FORWARD COME_FROM + compare_chained2b_37 POP_TOP _jump COME_FROM + compare_chained1c_37 ::= expr DUP_TOP ROT_THREE COMPARE_OP POP_JUMP_IF_FALSE compare_chained2a_37 POP_TOP @@ -697,6 +699,8 @@ class Python37Parser(Python37BaseParser): jmp_false37 ::= POP_JUMP_IF_FALSE COME_FROM list_if ::= expr jmp_false37 list_iter + list_iter ::= list_if37 + list_if37 ::= compare_chained37 list_iter _ifstmts_jump ::= c_stmts_opt come_froms diff --git a/uncompyle6/semantics/customize3.py b/uncompyle6/semantics/customize3.py index dae70e04..22cbb7a8 100644 --- a/uncompyle6/semantics/customize3.py +++ b/uncompyle6/semantics/customize3.py @@ -143,9 +143,14 @@ def customize_for_version3(self, version): list_ifs.append([1]) n = n[2] pass + elif n == "list_if37": + list_ifs.append(n) + n = n[-1] + pass pass assert n == "lc_body", ast + self.preorder(n[0]) # FIXME: add indentation around "for"'s and "in"'s diff --git a/uncompyle6/semantics/customize37.py b/uncompyle6/semantics/customize37.py index 73cd2230..a73cfcce 100644 --- a/uncompyle6/semantics/customize37.py +++ b/uncompyle6/semantics/customize37.py @@ -67,6 +67,7 @@ def customize_for_version37(self, version): '%[3]{pattr.replace("-", " ")} %p %p', (0, 19), (6, 19) ), 'if_exp_37a': ( '%p if %p else %p', (1, 'expr', 27), (0, 27), (4, 'expr', 27) ), 'if_exp_37b': ( '%p if %p else %p', (2, 'expr', 27), (0, 'expr', 27), (5, 'expr', 27) ), + 'list_if37': ( " if %p%c", (0, 27), 1 ), 'testfalse_not_or': ( "not %c or %c", (0, "expr"), (2, "expr") ), diff --git a/uncompyle6/semantics/pysource.py b/uncompyle6/semantics/pysource.py index 5f60a780..6c090f41 100644 --- a/uncompyle6/semantics/pysource.py +++ b/uncompyle6/semantics/pysource.py @@ -1263,6 +1263,7 @@ class SourceWalker(GenericASTTraversal, object): if self.version != 3.0: assert n.kind in ( "lc_body", + "list_if37", "comp_body", "set_comp_func", "set_comp_body", @@ -1369,7 +1370,11 @@ class SourceWalker(GenericASTTraversal, object): list_if = n else: list_if = n[1] - n = n[2] + n = n[-1] + pass + elif n == "list_if37": + list_ifs.append(n) + n = n[-1] pass pass