diff --git a/test/bytecode_3.4/04_multi_assign.pyc b/test/bytecode_3.4/04_multi_assign.pyc new file mode 100644 index 00000000..a6c35efe Binary files /dev/null and b/test/bytecode_3.4/04_multi_assign.pyc differ diff --git a/test/simple_source/stmts/04_multi_assign.py b/test/simple_source/stmts/04_multi_assign.py new file mode 100644 index 00000000..5e90ea12 --- /dev/null +++ b/test/simple_source/stmts/04_multi_assign.py @@ -0,0 +1,3 @@ +# Bug from Python 3.4 ftplib +cls_or_self, *rest = args +a, *b, c = args diff --git a/uncompyle6/parsers/parse3.py b/uncompyle6/parsers/parse3.py index 14b26b3a..dd668026 100644 --- a/uncompyle6/parsers/parse3.py +++ b/uncompyle6/parsers/parse3.py @@ -445,10 +445,6 @@ class Python3Parser(PythonParser): setcomp ::= {expr}^n LOAD_SETCOMP MAKE_CLOSURE GET_ITER CALL_FUNCTION_1 - dictcomp ::= LOAD_DICTCOMP MAKE_FUNCTION_0 expr - GET_ITER CALL_FUNCTION_1 - - # build_class (see load_build_class) build_list ::= {expr}^n BUILD_LIST_n @@ -456,9 +452,10 @@ class Python3Parser(PythonParser): load_closure ::= {LOAD_CLOSURE}^n BUILD_TUPLE_n - unpack_list ::= UNPACK_LIST {expr}^n - unpack ::= UNPACK_TUPLE {expr}^n - unpack ::= UNPACK_SEQEUENCE {expr}^n + unpack_list ::= UNPACK_LIST_n {expr}^n + unpack ::= UNPACK_TUPLE_n {expr}^n + unpack ::= UNPACK_SEQEUENCE_n {expr}^n + unpack_ex ::= UNPACK_EX_b_a {expr}^(a+b) mkfunc ::= {pos_arg}^n LOAD_CONST MAKE_FUNCTION_n mklambda ::= {pos_arg}^n LOAD_LAMBDA MAKE_FUNCTION_n @@ -524,6 +521,10 @@ class Python3Parser(PythonParser): self.add_unique_rule(rule, opname, token.attr, customize) rule = "mapexpr ::= %s %s" % (opname, kvlist_n) self.add_unique_rule(rule, opname, token.attr, customize) + elif opname_base in ('UNPACK_EX'): + before_count, after_count = token.attr + rule = 'unpack ::= ' + opname + ' designator' * (before_count + after_count + 1) + self.add_unique_rule(rule, opname, token.attr, customize) elif opname_base in ('UNPACK_TUPLE', 'UNPACK_SEQUENCE'): rule = 'unpack ::= ' + opname + ' designator' * token.attr self.add_unique_rule(rule, opname, token.attr, customize) diff --git a/uncompyle6/scanners/scanner3.py b/uncompyle6/scanners/scanner3.py index b87afc06..0a5a37a7 100644 --- a/uncompyle6/scanners/scanner3.py +++ b/uncompyle6/scanners/scanner3.py @@ -91,6 +91,7 @@ class Scanner3(scan.Scanner): for inst in bytecode: + argval = inst.argval if inst.offset in jump_targets: jump_idx = 0 for jump_offset in jump_targets[inst.offset]: @@ -153,6 +154,14 @@ class Scanner3(scan.Scanner): ): pos_args = inst.argval opname = '%s_%d' % (opname, pos_args) + elif opname == 'UNPACK_EX': + # FIXME: try with scanner and parser by + # changing inst.argval + before_args = inst.argval & 0xFF + after_args = (inst.argval >> 8) & 0xff + pattr = "%d before vararg, %d after" % (before_args, after_args) + argval = (before_args, after_args) + opname = '%s_%d+%d' % (opname, before_args, after_args) elif opname == 'JUMP_ABSOLUTE': pattr = inst.argval target = self.get_target(inst.offset) @@ -171,7 +180,7 @@ class Scanner3(scan.Scanner): tokens.append( Token( type_ = opname, - attr = inst.argval, + attr = argval, pattr = pattr, offset = inst.offset, linestart = inst.starts_line, @@ -308,7 +317,7 @@ class Scanner3(scan.Scanner): designator_ops = set([ STORE_FAST, STORE_NAME, STORE_GLOBAL, STORE_DEREF, STORE_ATTR, - STORE_SUBSCR, UNPACK_SEQUENCE, JUMP_ABSOLUTE + STORE_SUBSCR, UNPACK_SEQUENCE, JUMP_ABSOLUTE, UNPACK_EX ]) # Compose preliminary list of indices with statements, diff --git a/uncompyle6/semantics/pysource.py b/uncompyle6/semantics/pysource.py index ea932203..3e063d6f 100644 --- a/uncompyle6/semantics/pysource.py +++ b/uncompyle6/semantics/pysource.py @@ -1432,6 +1432,20 @@ class SourceWalker(GenericASTTraversal, object): self.prune() def n_unpack(self, node): + if node[0].type.startswith('UNPACK_EX'): + # Python 3+ + before_count, after_count = node[0].attr + for i in range(before_count+1): + self.preorder(node[i]) + if i != 0: + self.write(', ') + self.write('*') + for i in range(1, after_count+2): + self.preorder(node[before_count+i]) + if i != after_count + 1: + self.write(', ') + self.prune() + return for n in node[1:]: if n[0].type == 'unpack': n[0].type = 'unpack_w_parens'