diff --git a/test/bytecode_2.6_run/00_generator.pyc b/test/bytecode_2.6_run/00_generator.pyc new file mode 100644 index 00000000..69486ad5 Binary files /dev/null and b/test/bytecode_2.6_run/00_generator.pyc differ diff --git a/test/simple_source/bug26/00_generator.py b/test/simple_source/bug26/00_generator.py new file mode 100644 index 00000000..12a4cfad --- /dev/null +++ b/test/simple_source/bug26/00_generator.py @@ -0,0 +1,7 @@ +# Issue #283 in Python 2.6 +# See https://github.com/rocky/python-uncompyle6/issues/283 + +# This code is RUNNABLE! + +G = ( c for c in "spam, Spam, SPAM!" if c > 'A' and c < 'S') +assert list(G) == ["P", "M"] diff --git a/uncompyle6/parsers/parse26.py b/uncompyle6/parsers/parse26.py index 969471e2..9b41ff9c 100644 --- a/uncompyle6/parsers/parse26.py +++ b/uncompyle6/parsers/parse26.py @@ -241,6 +241,9 @@ class Python26Parser(Python2Parser): genexpr_func ::= setup_loop_lf FOR_ITER store comp_iter JUMP_ABSOLUTE come_froms POP_TOP jb_pop jb_pb_come_from + genexpr_func ::= setup_loop_lf FOR_ITER store comp_iter JUMP_BACK come_froms + POP_TOP jb_pb_come_from + generator_exp ::= LOAD_GENEXPR MAKE_FUNCTION_0 expr GET_ITER CALL_FUNCTION_1 COME_FROM list_if ::= list_if ::= expr jmp_false_then list_iter ''' diff --git a/uncompyle6/parsers/parse27.py b/uncompyle6/parsers/parse27.py index 9bc8bf51..6e456422 100644 --- a/uncompyle6/parsers/parse27.py +++ b/uncompyle6/parsers/parse27.py @@ -234,7 +234,7 @@ class Python27Parser(Python2Parser): return invalid if rule == ('and', ('expr', 'jmp_false', 'expr', '\\e_come_from_opt')): - # If the instruction after the instructions formin "and" is an "YIELD_VALUE" + # If the instruction after the instructions forming "and" is a "YIELD_VALUE" # then this is probably an "if" inside a comprehension. if tokens[last] == 'YIELD_VALUE': # Note: We might also consider testing last+1 being "POP_TOP" @@ -243,6 +243,9 @@ class Python27Parser(Python2Parser): # Test that jmp_false jumps to the end of "and" # or that it jumps to the same place as the end of "and" jmp_false = ast[1][0] + + # FIXME: if the jmp_false is POP_JUMP_IF_FALSE is the address + # is *absoulte* and the calulation below is wrong! jmp_target = jmp_false.offset + jmp_false.attr + 3 return not (jmp_target == tokens[last].offset or tokens[last].pattr == jmp_false.pattr)