diff --git a/test/bytecode_3.6/02_build_map_unpack_with_call.pyc b/test/bytecode_3.6/02_build_map_unpack_with_call.pyc-notyet similarity index 100% rename from test/bytecode_3.6/02_build_map_unpack_with_call.pyc rename to test/bytecode_3.6/02_build_map_unpack_with_call.pyc-notyet diff --git a/test/bytecode_3.6/04_CALL_FUNCTION_VAR_KW.pyc-notyet b/test/bytecode_3.6/04_CALL_FUNCTION_VAR_KW.pyc-notyet new file mode 100644 index 00000000..593aaeae Binary files /dev/null and b/test/bytecode_3.6/04_CALL_FUNCTION_VAR_KW.pyc-notyet differ diff --git a/uncompyle6/parsers/parse3.py b/uncompyle6/parsers/parse3.py index 43bbbd8f..88451d7f 100644 --- a/uncompyle6/parsers/parse3.py +++ b/uncompyle6/parsers/parse3.py @@ -507,11 +507,13 @@ class Python3Parser(PythonParser): ('pos_arg ' * args_pos) + ('kwarg ' * args_kw) + kw + token.type) self.add_unique_rule(rule, token.type, uniq_param, customize) - - rule = ('call_function ::= expr ' + - ('pos_arg ' * args_pos) + - ('kwarg ' * args_kw) + - 'expr ' * nak + token.type) + if self.version >= 3.6 and opname == 'CALL_FUNCTION_EX_KW': + rule = 'call_function ::= expr build_tuple_unpack_with_call build_map_unpack_with_call CALL_FUNCTION_EX_KW_1' + else: + rule = ('call_function ::= expr ' + + ('pos_arg ' * args_pos) + + ('kwarg ' * args_kw) + + 'expr ' * nak + token.type) self.add_unique_rule(rule, token.type, uniq_param, customize) if self.version >= 3.5: @@ -610,9 +612,9 @@ class Python3Parser(PythonParser): assign2_pypy ::= expr expr designator designator """, nop_func) continue - elif opname in ('CALL_FUNCTION', 'CALL_FUNCTION_VAR', - 'CALL_FUNCTION_VAR_KW') \ - or opname.startswith('CALL_FUNCTION_KW'): + elif (opname in ('CALL_FUNCTION', 'CALL_FUNCTION_VAR', + 'CALL_FUNCTION_VAR_KW', 'CALL_FUNCTION_EX_KW') + or opname.startswith('CALL_FUNCTION_KW')): self.custom_classfunc_rule(opname, token, customize) elif opname == 'LOAD_DICTCOMP': rule_pat = ("dictcomp ::= LOAD_DICTCOMP %sMAKE_FUNCTION_0 expr " @@ -633,6 +635,18 @@ class Python3Parser(PythonParser): self.add_unique_rule(rule, opname, token.attr, customize) rule = 'expr ::= build_list_unpack' self.add_unique_rule(rule, opname, token.attr, customize) + elif opname.startswith('BUILD_TUPLE_UNPACK_WITH_CALL'): + v = token.attr + rule = ('build_tuple_unpack_with_call ::= ' + 'expr1024 ' * int(v//1024) + + 'expr32 ' * int((v//32) % 32) + + 'expr ' * (v % 32) + opname) + self.add_unique_rule(rule, opname, token.attr, customize) + elif opname.startswith('BUILD_MAP_UNPACK_WITH_CALL'): + v = token.attr + rule = ('build_map_unpack_with_call ::= ' + 'expr1024 ' * int(v//1024) + + 'expr32 ' * int((v//32) % 32) + + 'expr ' * (v % 32) + opname) + self.add_unique_rule(rule, opname, token.attr, customize) elif opname_base in ('BUILD_LIST', 'BUILD_TUPLE', 'BUILD_SET'): v = token.attr rule = ('build_list ::= ' + 'expr1024 ' * int(v//1024) + @@ -642,7 +656,10 @@ class Python3Parser(PythonParser): if opname_base == 'BUILD_TUPLE': rule = ('load_closure ::= %s%s' % (('LOAD_CLOSURE ' * v), opname)) self.add_unique_rule(rule, opname, token.attr, customize) - + rule = ('build_tuple ::= ' + 'expr1024 ' * int(v//1024) + + 'expr32 ' * int((v//32) % 32) + + 'expr ' * (v % 32) + opname) + self.add_unique_rule(rule, opname, token.attr, customize) elif opname == 'LOOKUP_METHOD': # A PyPy speciality - DRY with parse2 self.add_unique_rule("load_attr ::= expr LOOKUP_METHOD", diff --git a/uncompyle6/parsers/parse36.py b/uncompyle6/parsers/parse36.py index 1b4c8022..0b7a8dcd 100644 --- a/uncompyle6/parsers/parse36.py +++ b/uncompyle6/parsers/parse36.py @@ -25,12 +25,13 @@ class Python36Parser(Python35Parser): func_args36 ::= expr BUILD_TUPLE_0 call_function ::= func_args36 unmapexpr CALL_FUNCTION_EX + call_function ::= func_args36 build_map_unpack_with_call CALL_FUNCTION_EX_KW_1 withstmt ::= expr SETUP_WITH POP_TOP suite_stmts_opt POP_BLOCK LOAD_CONST WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY call_function ::= expr expr CALL_FUNCTION_EX - call_function ::= expr expr expr CALL_FUNCTION_EX_KW + call_function ::= expr expr expr CALL_FUNCTION_EX_KW_1 """ def add_custom_rules(self, tokens, customize): diff --git a/uncompyle6/scanners/scanner36.py b/uncompyle6/scanners/scanner36.py index 15265f12..3c511937 100644 --- a/uncompyle6/scanners/scanner36.py +++ b/uncompyle6/scanners/scanner36.py @@ -1,4 +1,4 @@ -# Copyright (c) 2016 by Rocky Bernstein +# Copyright (c) 2016-2017 by Rocky Bernstein """ Python 3.6 bytecode scanner/deparser @@ -28,8 +28,12 @@ class Scanner36(Scanner3): if t.op == self.opc.CALL_FUNCTION_EX and t.attr & 1: t.type = 'CALL_FUNCTION_EX_KW' pass - if t.op == self.opc.CALL_FUNCTION_KW: + elif t.op == self.opc.CALL_FUNCTION_KW: t.type = 'CALL_FUNCTION_KW_{t.attr}'.format(**locals()) + elif t.op == self.opc.BUILD_TUPLE_UNPACK_WITH_CALL: + t.type = 'BUILD_TUPLE_UNPACK_WITH_CALL_%d' % t.attr + elif t.op == self.opc.BUILD_MAP_UNPACK_WITH_CALL: + t.type = 'BUILD_MAP_UNPACK_WITH_CALL_%d' % t.attr pass return tokens, customize