diff --git a/test/bytecode_3.2/02_ifelse_comprehension.pyc b/test/bytecode_3.2/02_ifelse_comprehension.pyc new file mode 100644 index 00000000..a2e59dc6 Binary files /dev/null and b/test/bytecode_3.2/02_ifelse_comprehension.pyc differ diff --git a/test/bytecode_3.2/05_dup_top_two.pyc b/test/bytecode_3.2/05_dup_top_two.pyc index b131e1c0..190f23d0 100644 Binary files a/test/bytecode_3.2/05_dup_top_two.pyc and b/test/bytecode_3.2/05_dup_top_two.pyc differ diff --git a/test/bytecode_3.3/02_ifelse_comprehension.pyc b/test/bytecode_3.3/02_ifelse_comprehension.pyc new file mode 100644 index 00000000..a0c342af Binary files /dev/null and b/test/bytecode_3.3/02_ifelse_comprehension.pyc differ diff --git a/uncompyle6/parsers/parse3.py b/uncompyle6/parsers/parse3.py index 5c3d82c3..e7368305 100644 --- a/uncompyle6/parsers/parse3.py +++ b/uncompyle6/parsers/parse3.py @@ -483,8 +483,8 @@ class Python3Parser(PythonParser): return def custom_classfunc_rule(self, opname, token, customize, - seen_LOAD_BUILD_CLASS, - seen_GET_AWAITABLE_YIELD_FROM): + possible_class_decorator, + seen_GET_AWAITABLE_YIELD_FROM, next_token): """ call_function ::= expr {expr}^n CALL_FUNCTION_n call_function ::= expr {expr}^n CALL_FUNCTION_VAR_n @@ -543,10 +543,11 @@ class Python3Parser(PythonParser): self.add_unique_rule(rule, token.kind, uniq_param, customize) self.add_unique_rule('expr ::= async_call_function', token.kind, uniq_param, customize) - if seen_LOAD_BUILD_CLASS: - rule = ('classdefdeco2 ::= LOAD_BUILD_CLASS mkfunc %s%s_%d' + if possible_class_decorator: + if next_token == 'CALL_FUNCTION' and next_token.attr == 1: + rule = ('classdefdeco2 ::= LOAD_BUILD_CLASS mkfunc %s%s_%d' % (('expr ' * (args_pos-1)), opname, args_pos)) - self.add_unique_rule(rule, token.kind, uniq_param, customize) + self.add_unique_rule(rule, token.kind, uniq_param, customize) def add_make_function_rule(self, rule, opname, attr, customize): """Python 3.3 added a an addtional LOAD_CONST before MAKE_FUNCTION and @@ -628,6 +629,7 @@ class Python3Parser(PythonParser): seen_LOAD_DICTCOMP = False seen_LOAD_LISTCOMP = False seen_LOAD_SETCOMP = False + seen_classdeco_end = False seen_GET_AWAITABLE_YIELD_FROM = False # Loop over instructions adding custom grammar rules based on @@ -758,7 +760,7 @@ class Python3Parser(PythonParser): or opname.startswith('CALL_FUNCTION_KW')): self.custom_classfunc_rule(opname, token, customize, seen_LOAD_BUILD_CLASS, - seen_GET_AWAITABLE_YIELD_FROM) + seen_GET_AWAITABLE_YIELD_FROM, tokens[i+1]) elif opname_base == 'CALL_METHOD': # PyPy only - DRY with parse2 diff --git a/uncompyle6/parsers/parse36.py b/uncompyle6/parsers/parse36.py index 94f50797..8b094cb2 100644 --- a/uncompyle6/parsers/parse36.py +++ b/uncompyle6/parsers/parse36.py @@ -99,8 +99,8 @@ class Python36Parser(Python35Parser): self.add_unique_doc_rules(rules_str, customize) def custom_classfunc_rule(self, opname, token, customize, - seen_LOAD_BUILD_CLASS, - seen_GET_AWAITABLE_YIELD_FROM): + possible_class_decorator, + seen_GET_AWAITABLE_YIELD_FROM, next_token): if opname.startswith('CALL_FUNCTION_KW'): values = 'expr ' * token.attr rule = 'call_function ::= expr kwargs_only_36 {token.kind}'.format(**locals()) @@ -110,8 +110,9 @@ class Python36Parser(Python35Parser): else: super(Python36Parser, self).custom_classfunc_rule(opname, token, customize, - seen_LOAD_BUILD_CLASS, - seen_GET_AWAITABLE_YIELD_FROM) + possible_class_decorator, + seen_GET_AWAITABLE_YIELD_FROM, + next_token) class Python36ParserSingle(Python36Parser, PythonParserSingle): diff --git a/uncompyle6/scanners/scanner3.py b/uncompyle6/scanners/scanner3.py index ba4277eb..ced88098 100644 --- a/uncompyle6/scanners/scanner3.py +++ b/uncompyle6/scanners/scanner3.py @@ -219,6 +219,7 @@ class Scanner3(Scanner): argval = inst.argval op = inst.opcode + if op == self.opc.EXTENDED_ARG: # FIXME: The EXTENDED_ARG is used to signal annotation # parameters @@ -331,6 +332,7 @@ class Scanner3(Scanner): opname = 'BUILD_MAP_n' else: opname = '%s_%d' % (opname, pos_args) + elif self.is_pypy and opname in ('CALL_METHOD', 'JUMP_IF_NOT_DEBUG'): # 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