diff --git a/test/bytecode_2.6/02_test_exec.pyc b/test/bytecode_2.6/02_test_exec.pyc new file mode 100644 index 00000000..e9274234 Binary files /dev/null and b/test/bytecode_2.6/02_test_exec.pyc differ diff --git a/test/simple_source/stmts/02_test_exec.py b/test/simple_source/stmts/02_test_exec.py new file mode 100644 index 00000000..ed448155 --- /dev/null +++ b/test/simple_source/stmts/02_test_exec.py @@ -0,0 +1,13 @@ +# exec.py -- source test pattern for exec statement +# +# This simple program is part of the decompyle test suite. +# +# decompyle is a Python byte-code decompiler +# See http://www.goebel-consult.de/decompyle/ for download and +# for further information + +testcode = 'a = 12' + +exec testcode +exec testcode in globals() +exec testcode in globals(), locals() diff --git a/uncompyle6/parser.py b/uncompyle6/parser.py index 74740c70..39697b5d 100644 --- a/uncompyle6/parser.py +++ b/uncompyle6/parser.py @@ -501,9 +501,6 @@ class PythonParser(GenericASTBuilder): # Non-null kvlist items are broken out in the indiviual grammars kvlist ::= - exprlist ::= exprlist expr - exprlist ::= expr - # Positional arguments in make_function pos_arg ::= expr diff --git a/uncompyle6/parsers/parse2.py b/uncompyle6/parsers/parse2.py index 6ef72140..9c4292cf 100644 --- a/uncompyle6/parsers/parse2.py +++ b/uncompyle6/parsers/parse2.py @@ -38,13 +38,6 @@ class Python2Parser(PythonParser): print_nl ::= PRINT_NEWLINE """ - def p_stmt2(self, args): - """ - exec_stmt ::= expr exprlist DUP_TOP EXEC_STMT - exec_stmt ::= expr exprlist EXEC_STMT - - """ - def p_print_to(self, args): ''' stmt ::= print_to @@ -341,6 +334,13 @@ class Python2Parser(PythonParser): # FIXME: remove these conditions if they are not needed. # no longer need to add a rule continue + elif opname == 'EXEC_STMT': + self.addRule(""" + exprlist ::= expr+ + exec_stmt ::= expr exprlist DUP_TOP EXEC_STMT + exec_stmt ::= expr exprlist EXEC_STMT + """, nop_func) + continue elif opname == 'JUMP_IF_NOT_DEBUG': self.add_unique_rules([ 'jmp_true_false ::= POP_JUMP_IF_TRUE', diff --git a/uncompyle6/parsers/parse35.py b/uncompyle6/parsers/parse35.py index 20420a58..c228ce34 100644 --- a/uncompyle6/parsers/parse35.py +++ b/uncompyle6/parsers/parse35.py @@ -35,11 +35,6 @@ class Python35Parser(Python34Parser): # Python 3.5+ has WITH_CLEANUP_START/FINISH - withstmt ::= expr - SETUP_WITH exprlist suite_stmts_opt - POP_BLOCK LOAD_CONST COME_FROM_WITH - WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY - withstmt ::= expr SETUP_WITH POP_TOP suite_stmts_opt POP_BLOCK LOAD_CONST COME_FROM_WITH diff --git a/uncompyle6/scanners/scanner2.py b/uncompyle6/scanners/scanner2.py index 8ea93a46..b5beea6b 100644 --- a/uncompyle6/scanners/scanner2.py +++ b/uncompyle6/scanners/scanner2.py @@ -250,17 +250,15 @@ class Scanner2(Scanner): else: op_name = '%s_%d' % (op_name, oparg) customize[op_name] = oparg - elif self.is_pypy and op_name in ('LOOKUP_METHOD', - 'JUMP_IF_NOT_DEBUG', - 'SETUP_EXCEPT', - 'SETUP_FINALLY'): + elif self.is_pypy and op_name in frozenset( + """LOOKUP_METHOD JUMP_IF_NOT_DEBUG SETUP_EXCEPT SETUP_FINALLY""".split()): # The value in the dict is in special cases in semantic actions, such # as CALL_FUNCTION. The value is not used in these cases, so we put # in arbitrary value 0. customize[op_name] = 0 - elif op == self.opc.CONTINUE_LOOP: - customize[op_name] = 0 - elif op_name in frozenset(('LOAD_LISTCOMP', 'LOAD_SETCOMP')): + elif op_name in """ + CONTINUE_LOOP EXEC_STMT LOAD_LISTCOMP LOAD_SETCOMP + """.split(): customize[op_name] = 0 elif op == self.opc.JUMP_ABSOLUTE: # Further classify JUMP_ABSOLUTE into backward jumps diff --git a/uncompyle6/scanners/scanner26.py b/uncompyle6/scanners/scanner26.py index 10d83388..58e1274e 100755 --- a/uncompyle6/scanners/scanner26.py +++ b/uncompyle6/scanners/scanner26.py @@ -238,6 +238,10 @@ class Scanner26(scan.Scanner2): customize[op_name] = oparg elif self.version > 2.0 and op == self.opc.CONTINUE_LOOP: customize[op_name] = 0 + elif op_name in """ + CONTINUE_LOOP EXEC_STMT LOAD_LISTCOMP LOAD_SETCOMP + """.split(): + customize[op_name] = 0 elif op == self.opc.JUMP_ABSOLUTE: # Further classify JUMP_ABSOLUTE into backward jumps # which are used in loops, and "CONTINUE" jumps which