diff --git a/test/bytecode_2.6/03_weird26.pyc b/test/bytecode_2.6/03_weird26.pyc index b59367d3..3823cc5b 100644 Binary files a/test/bytecode_2.6/03_weird26.pyc and b/test/bytecode_2.6/03_weird26.pyc differ diff --git a/test/bytecode_2.7/03_weird26.pyc b/test/bytecode_2.7/03_weird26.pyc new file mode 100644 index 00000000..39e093f2 Binary files /dev/null and b/test/bytecode_2.7/03_weird26.pyc differ diff --git a/test/bytecode_3.2/03_weird26.pyc b/test/bytecode_3.2/03_weird26.pyc new file mode 100644 index 00000000..a47cc33a Binary files /dev/null and b/test/bytecode_3.2/03_weird26.pyc differ diff --git a/test/bytecode_3.3/03_weird26.pyc b/test/bytecode_3.3/03_weird26.pyc new file mode 100644 index 00000000..598460a1 Binary files /dev/null and b/test/bytecode_3.3/03_weird26.pyc differ diff --git a/test/bytecode_3.4/03_weird26.pyc b/test/bytecode_3.4/03_weird26.pyc new file mode 100644 index 00000000..68ef0ebe Binary files /dev/null and b/test/bytecode_3.4/03_weird26.pyc differ diff --git a/test/bytecode_3.5/03_weird26.pyc b/test/bytecode_3.5/03_weird26.pyc new file mode 100644 index 00000000..c8a337e6 Binary files /dev/null and b/test/bytecode_3.5/03_weird26.pyc differ diff --git a/test/bytecode_3.6/03_weird26.pyc b/test/bytecode_3.6/03_weird26.pyc new file mode 100644 index 00000000..82fe73ca Binary files /dev/null and b/test/bytecode_3.6/03_weird26.pyc differ diff --git a/uncompyle6/parsers/parse26.py b/uncompyle6/parsers/parse26.py index e0c368a4..2d40747c 100644 --- a/uncompyle6/parsers/parse26.py +++ b/uncompyle6/parsers/parse26.py @@ -269,7 +269,7 @@ class Python26Parser(Python2Parser): return_stmt_lambda LAMBDA_MARKER # conditional_true are for conditions which always evaluate true - # There is dead or non-optional remnants of the condition code though, + # There is dead or non-optional remnants of the condition code though, # and we use that to match on to reconstruct the source more accurately expr ::= conditional_true conditional_true ::= expr jf_pop expr COME_FROM diff --git a/uncompyle6/parsers/parse27.py b/uncompyle6/parsers/parse27.py index d39558e7..4876b5d7 100644 --- a/uncompyle6/parsers/parse27.py +++ b/uncompyle6/parsers/parse27.py @@ -85,7 +85,7 @@ class Python27Parser(Python2Parser): compare_chained2 ::= expr COMPARE_OP RETURN_VALUE # conditional_true are for conditions which always evaluate true - # There is dead or non-optional remnants of the condition code though, + # There is dead or non-optional remnants of the condition code though, # and we use that to match on to reconstruct the source more accurately expr ::= conditional_true conditional_true ::= expr JUMP_FORWARD expr COME_FROM diff --git a/uncompyle6/parsers/parse3.py b/uncompyle6/parsers/parse3.py index c4462b72..5b4d793b 100644 --- a/uncompyle6/parsers/parse3.py +++ b/uncompyle6/parsers/parse3.py @@ -39,6 +39,8 @@ class Python3Parser(PythonParser): comp_for ::= expr _for store comp_iter CONTINUE comp_for ::= expr _for store comp_iter JUMP_BACK + list_comp ::= BUILD_LIST_0 list_iter + lc_body ::= expr LIST_APPEND list_for ::= expr FOR_ITER store list_iter jb_or_c # This is seen in PyPy, but possibly it appears on other Python 3? @@ -402,6 +404,12 @@ class Python3Parser(PythonParser): # a JUMP_FORWARD to another JUMP_FORWARD can get turned into # a JUMP_ABSOLUTE with no COME_FROM conditional ::= expr jmp_false expr jump_absolute_else expr + + # conditional_true are for conditions which always evaluate true + # There is dead or non-optional remnants of the condition code though, + # and we use that to match on to reconstruct the source more accurately + expr ::= conditional_true + conditional_true ::= expr JUMP_FORWARD expr COME_FROM """ @staticmethod @@ -752,20 +760,25 @@ class Python3Parser(PythonParser): ('kwarg ' * args_kw) + 'expr ' * nak + opname) self.add_unique_rule(rule, opname, token.attr, customize) + elif opname == 'DELETE_DEREF': + self.addRule(""" + stmt ::= del_deref_stmt + del_deref_stmt ::= DELETE_DEREF + """, nop_func) elif opname == 'JUMP_IF_NOT_DEBUG': v = token.attr - self.add_unique_rule( - "stmt ::= assert_pypy", opname, v, customize) - self.add_unique_rule( - "stmt ::= assert2_pypy", opname_base, v, customize) - self.add_unique_rule( - "assert_pypy ::= JUMP_IF_NOT_DEBUG assert_expr jmp_true " - "LOAD_ASSERT RAISE_VARARGS_1 COME_FROM", - opname, token.attr, customize) - self.add_unique_rule( - "assert2_pypy ::= JUMP_IF_NOT_DEBUG assert_expr jmp_true " - "LOAD_ASSERT expr CALL_FUNCTION_1 RAISE_VARARGS_1 COME_FROM", - opname_base, v, customize) + self.addRule(""" + stmt ::= assert_pypy + stmt ::= assert2_pypy", nop_func) + assert_pypy ::= JUMP_IF_NOT_DEBUG assert_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 + LOAD_ASSERT expr CALL_FUNCTION_1 + RAISE_VARARGS_1 COME_FROM, + """, nop_func) continue elif opname == 'LOAD_BUILD_CLASS': seen_LOAD_BUILD_CLASS = True diff --git a/uncompyle6/parsers/parse32.py b/uncompyle6/parsers/parse32.py index f0f8121d..5392a0f6 100644 --- a/uncompyle6/parsers/parse32.py +++ b/uncompyle6/parsers/parse32.py @@ -45,11 +45,6 @@ class Python32Parser(Python3Parser): _ifstmts_jump ::= c_stmts_opt _ifstmts_jump ::= c_stmts_opt JUMP_FORWARD _come_froms - stmt ::= del_deref_stmt - del_deref_stmt ::= DELETE_DEREF - - list_comp ::= BUILD_LIST_0 list_iter - lc_body ::= expr LIST_APPEND kv3 ::= expr expr STORE_MAP """ pass diff --git a/uncompyle6/semantics/pysource.py b/uncompyle6/semantics/pysource.py index 44820b12..16265153 100644 --- a/uncompyle6/semantics/pysource.py +++ b/uncompyle6/semantics/pysource.py @@ -1082,9 +1082,10 @@ class SourceWalker(GenericASTTraversal, object): assert n == 'list_iter' - # find innermost node + # Find the list comprehension body. It is the inner-most + # node. while n == 'list_iter': - n = n[0] # recurse one step + n = n[0] # iterate one nesting deeper if n == 'list_for': n = n[3] elif n == 'list_if': n = n[2] elif n == 'list_if_not': n= n[2] @@ -1140,9 +1141,10 @@ class SourceWalker(GenericASTTraversal, object): assert n == 'list_iter' assert store == 'store' - # find innermost node + # Find the list comprehension body. It is the inner-most + # node. while n == 'list_iter': - n = n[0] # recurse one step + n = n[0] # iterate one nesting deeper if n == 'list_for': n = n[3] elif n == 'list_if': n = n[2] elif n == 'list_if_not': n= n[2]