From 93e889e82afab08b79930ba7b52d0907e235e705 Mon Sep 17 00:00:00 2001 From: rocky Date: Sun, 24 Jun 2018 16:46:56 -0400 Subject: [PATCH] Python 3.0 comprehensions are a snowflake --- uncompyle6/parsers/parse30.py | 19 +++++++++++++++---- uncompyle6/semantics/pysource.py | 31 ++++++++++++++++++++++++++++--- 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/uncompyle6/parsers/parse30.py b/uncompyle6/parsers/parse30.py index 9a0f257e..8d1365bc 100644 --- a/uncompyle6/parsers/parse30.py +++ b/uncompyle6/parsers/parse30.py @@ -59,11 +59,22 @@ class Python30Parser(Python31Parser): LOAD_FAST FOR_ITER store comp_iter JUMP_BACK POP_TOP JUMP_BACK RETURN_VALUE RETURN_LAST - list_comp_header ::= BUILD_LIST_0 DUP_TOP STORE_FAST - list_comp ::= list_comp_header - LOAD_FAST FOR_ITER store comp_iter - JUMP_BACK + list_comp_header ::= BUILD_LIST_0 DUP_TOP STORE_FAST + list_comp ::= list_comp_header + LOAD_FAST FOR_ITER store comp_iter + JUMP_BACK + set_comp_header ::= BUILD_SET_0 DUP_TOP STORE_FAST + set_comp ::= set_comp_header + LOAD_FAST FOR_ITER store comp_iter + JUMP_BACK + + dict_comp_header ::= BUILD_MAP_0 DUP_TOP STORE_FAST + dict_comp ::= dict_comp_header + LOAD_FAST FOR_ITER store dict_comp_iter + JUMP_BACK + + dict_comp_iter ::= expr expr ROT_TWO expr STORE_SUBSCR # JUMP_IF_TRUE POP_TOP as a replacement comp_if ::= expr jmp_false comp_iter diff --git a/uncompyle6/semantics/pysource.py b/uncompyle6/semantics/pysource.py index ad2f2498..860414ad 100644 --- a/uncompyle6/semantics/pysource.py +++ b/uncompyle6/semantics/pysource.py @@ -1051,10 +1051,15 @@ class SourceWalker(GenericASTTraversal, object): self.prec=100 ast = ast[0] + # Pick out important parts of the comprehension: + # * the variable we interate over: "store" + # * the results we accumulate: "n" + + is_30_dict_comp = False store = None n = ast[iter_index] - if ast in ['set_comp_func', 'dict_comp_func', - 'list_comp', 'set_comp_func_header']: + if ast in ('set_comp_func', 'dict_comp_func', + 'list_comp', 'set_comp_func_header'): for k in ast: if k == 'comp_iter': n = k @@ -1063,6 +1068,21 @@ class SourceWalker(GenericASTTraversal, object): pass pass pass + elif ast in ('dict_comp', 'set_comp'): + assert self.version == 3.0 + for k in ast: + if k in ('dict_comp_header', 'set_comp_header'): + n = k + elif k == 'store': + store = k + elif k == 'dict_comp_iter': + is_30_dict_comp = True + n = (k[3], k[1]) + pass + elif k == 'comp_iter': + n = k[1] + pass + pass else: assert n == 'list_iter', n @@ -1115,7 +1135,12 @@ class SourceWalker(GenericASTTraversal, object): # Another approach might be to be able to pass in the source name # for the dummy argument. - self.preorder(n[0]) + if is_30_dict_comp: + self.preorder(n[0]) + self.write(': ') + self.preorder(n[1]) + else: + self.preorder(n[0]) self.write(' for ') if comp_store: self.preorder(comp_store)