From 41f9e9e53e688353a116b568cd5feeb156251de5 Mon Sep 17 00:00:00 2001 From: rocky Date: Mon, 9 May 2016 06:57:13 -0400 Subject: [PATCH] Track recent lc changes in fragment semantics --- test/bytecode_3.2/05_closure_bug.pyc | Bin 596 -> 0 bytes test/simple_source/def/05_closure_bug.py | 5 +- uncompyle6/parsers/parse3.py | 9 +++- uncompyle6/semantics/fragments.py | 56 ++++++++++++++++++++++- uncompyle6/semantics/pysource.py | 5 +- 5 files changed, 69 insertions(+), 6 deletions(-) delete mode 100644 test/bytecode_3.2/05_closure_bug.pyc diff --git a/test/bytecode_3.2/05_closure_bug.pyc b/test/bytecode_3.2/05_closure_bug.pyc deleted file mode 100644 index d5440b5aac191214dc555c5b985b763454f1df23..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 596 zcmb7Bu}Z{15Ph3dQBgS%MG&#DN#$K*Cn8u_nZ`o6CdTY09&WN>H_IuUm7-RDvol%o zPHl9_zRZMq@6Al~+WP9X9A4#^I}ydFblo0-q(?vlmB2_q$OzBCD1z+aGG3sHFQ@U zY?K7|9SYNPRV$md#-5qFRrl>hR%fNMovvr8%$BYT?k3U&B7ZJ?oyYWsKOk`9s?jQS z#@k#Cq$&o(qcqpXd8^VJUmi9Oeu?UCm2Q;XW(K#4=*J#rwyZx#>8!rH|JithjPfvD y6{g$b26zgH-Ch#&!u<*Xo3_SiH~TaGH#_vg?EfubnHa~FkzT8lO^Uk}^rH_1#(0qc diff --git a/test/simple_source/def/05_closure_bug.py b/test/simple_source/def/05_closure_bug.py index fe192ca0..2a3b3c0c 100644 --- a/test/simple_source/def/05_closure_bug.py +++ b/test/simple_source/def/05_closure_bug.py @@ -1,4 +1,7 @@ -# Tests bug in Python 3 +# Tests closure bug in Python 3 + +# Note also check that *args, and **kwds are preserved +# on the call! # load_closure ::= LOAD_CLOSURE BUILD_TUPLE_1 diff --git a/uncompyle6/parsers/parse3.py b/uncompyle6/parsers/parse3.py index c091ed3c..b12f3b30 100644 --- a/uncompyle6/parsers/parse3.py +++ b/uncompyle6/parsers/parse3.py @@ -53,8 +53,6 @@ class Python3Parser(PythonParser): list_for ::= expr FOR_ITER designator list_iter JUMP_BACK # See also common Python p_list_comprehension - - load_closure ::= LOAD_CLOSURE BUILD_TUPLE_1 """ def p_setcomp3(self, args): @@ -432,6 +430,9 @@ class Python3Parser(PythonParser): build_list ::= {expr}^n BUILD_LIST_n build_list ::= {expr}^n BUILD_TUPLE_n + + load_closure ::= {LOAD_CLOSURE}^n BUILD_TUPLE_n + unpack_list ::= UNPACK_LIST {expr}^n unpack ::= UNPACK_TUPLE {expr}^n unpack ::= UNPACK_SEQEUENCE {expr}^n @@ -468,6 +469,10 @@ class Python3Parser(PythonParser): rule = ('build_list ::= ' + 'expr1024 ' * int(v//1024) + 'expr32 ' * int((v//32)%32) + 'expr '*(v%32) + opname) self.add_unique_rule(rule, opname, token.attr, customize) + if opname_base == 'BUILD_TUPLE': + rule = ('load_closure ::= %s%s' % (('LOAD_CLOSURE ' * v), opname)) + self.add_unique_rule(rule, opname, token.attr, customize) + elif self.version >= 3.5 and opname_base == 'BUILD_MAP': kvlist_n = "kvlist_%s" % token.attr rule = kvlist_n + ' ::= ' + 'expr ' * (token.attr*2) diff --git a/uncompyle6/semantics/fragments.py b/uncompyle6/semantics/fragments.py index 2ca4c05c..feff2cc1 100644 --- a/uncompyle6/semantics/fragments.py +++ b/uncompyle6/semantics/fragments.py @@ -550,8 +550,9 @@ class FragmentsWalker(pysource.SourceWalker, object): n = ast[iter_index] assert n == 'list_iter' + # find innermost node - while n == 'list_iter': # list_iter + while n == 'list_iter': n = n[0] # recurse one step if n == 'list_for': designator = n[2] @@ -580,6 +581,59 @@ class FragmentsWalker(pysource.SourceWalker, object): # self.preorder(ast[iter_index]) self.prec = p + def listcomprehension_walk2(self, node): + """List comprehensions the way they are done in Python3. + They're more other comprehensions, e.g. set comprehensions + See if we can combine code. + """ + p = self.prec + self.prec = 27 + + code = Code(node[1].attr, self.scanner, self.currentclass) + ast = self.build_ast(code._tokens, code._customize) + self.customize(code._customize) + ast = ast[0][0][0][0][0] + + n = ast[1] + collection = node[-3] + list_if = None + assert n == 'list_iter' + + # find innermost node + while n == 'list_iter': + n = n[0] # recurse one step + if n == 'list_for': + designator = n[2] + n = n[3] + elif n in ('list_if', 'list_if_not'): + # FIXME: just a guess + if n[0].type == 'expr': + list_if = n + else: + list_if = n[1] + n = n[2] + pass + pass + + assert n == 'lc_body', ast + + self.preorder(n[0]) + self.write(' for ') + start = len(self.f.getvalue()) + self.preorder(designator) + self.set_pos_info(designator, start, len(self.f.getvalue())) + self.write(' in ') + start = len(self.f.getvalue()) + node[-3].parent = node + self.preorder(collection) + self.set_pos_info(collection, start, len(self.f.getvalue())) + if list_if: + start = len(self.f.getvalue()) + self.preorder(list_if) + self.set_pos_info(list_if, start, len(self.f.getvalue())) + + self.prec = p + def n_genexpr(self, node): start = len(self.f.getvalue()) self.write('(') diff --git a/uncompyle6/semantics/pysource.py b/uncompyle6/semantics/pysource.py index 6502cc0d..e7b527d0 100644 --- a/uncompyle6/semantics/pysource.py +++ b/uncompyle6/semantics/pysource.py @@ -1047,8 +1047,9 @@ class SourceWalker(GenericASTTraversal, object): n = ast[iter_index] assert n == 'list_iter' + # find innermost node - while n == 'list_iter': # list_iter + while n == 'list_iter': n = n[0] # recurse one step if n == 'list_for': designator = n[2] @@ -1087,7 +1088,7 @@ class SourceWalker(GenericASTTraversal, object): assert n == 'list_iter' # find innermost node - while n == 'list_iter': # list_iter + while n == 'list_iter': n = n[0] # recurse one step if n == 'list_for': designator = n[2]