Bug in 3.5 constant map parsing

This commit is contained in:
rocky
2016-05-01 20:54:42 -04:00
parent b52baddab6
commit dcbf8d2cf7
3 changed files with 42 additions and 34 deletions

View File

@@ -615,6 +615,12 @@ class Python3Parser(PythonParser):
elif opname_base in ('BUILD_LIST', 'BUILD_TUPLE', 'BUILD_SET'):
rule = 'build_list ::= ' + 'expr ' * token.attr + 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)
self.add_unique_rule(rule, opname, token.attr, customize)
rule = "mapexpr ::= %s %s" % (kvlist_n, opname)
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)

View File

@@ -14,7 +14,6 @@ import dis, inspect
from array import array
import uncompyle6.scanners.scanner3 as scan3
from uncompyle6 import PYTHON_VERSION
from uncompyle6.code import iscode
from uncompyle6.scanner import Token
@@ -29,13 +28,10 @@ from uncompyle6.opcodes.opcode_35 import *
class Scanner35(scan3.Scanner3):
def disassemble(self, co, classname=None, code_objects={}):
fn = self.disassemble_built_in if PYTHON_VERSION == 3.4 \
else self.disassemble_generic
return fn(co, classname, code_objects=code_objects)
def disassemble_built_in(self, co, classname=None,
code_objects={}):
# Note: we can't use built-in disassembly routines, unless
# we do post-processing like we do here.
def disassemble(self, co, classname=None,
code_objects={}):
# Container for tokens
tokens = []
customize = {}
@@ -116,17 +112,11 @@ class Scanner35(scan3.Scanner3):
pattr = const
pass
elif opname in ('BUILD_LIST', 'BUILD_TUPLE', 'BUILD_SET', 'BUILD_SLICE',
'BUILD_MAP',
'UNPACK_SEQUENCE',
'MAKE_FUNCTION', 'MAKE_CLOSURE',
'DUP_TOPX', 'RAISE_VARARGS'
):
# if opname == 'BUILD_TUPLE' and \
# self.code[self.prev[offset]] == LOAD_CLOSURE:
# continue
# else:
# op_name = '%s_%d' % (op_name, oparg)
# if opname != BUILD_SLICE:
# customize[op_name] = oparg
opname = '%s_%d' % (opname, inst.argval)
if inst.opname != 'BUILD_SLICE':
customize[opname] = inst.argval

View File

@@ -81,7 +81,6 @@ if PYTHON3:
minint = -sys.maxsize-1
maxint = sys.maxsize
else:
from itertools import izip_longest as zip_longest
from StringIO import StringIO
minint = -sys.maxint-1
maxint = sys.maxint
@@ -1148,29 +1147,42 @@ class SourceWalker(GenericASTTraversal, object):
"""
p = self.prec
self.prec = 100
assert node[-1] == 'kvlist'
node = node[-1] # goto kvlist
self.indentMore(INDENT_PER_LEVEL)
line_seperator = ',\n' + self.indent
sep = INDENT_PER_LEVEL[:-1]
self.write('{')
for kv in node:
assert kv in ('kv', 'kv2', 'kv3')
# kv ::= DUP_TOP expr ROT_TWO expr STORE_SUBSCR
# kv2 ::= DUP_TOP expr expr ROT_THREE STORE_SUBSCR
# kv3 ::= expr expr STORE_MAP
if kv == 'kv':
name = self.traverse(kv[-2], indent='')
value = self.traverse(kv[1], indent=self.indent+(len(name)+2)*' ')
elif kv == 'kv2':
name = self.traverse(kv[1], indent='')
value = self.traverse(kv[-3], indent=self.indent+(len(name)+2)*' ')
elif kv == 'kv3':
name = self.traverse(kv[-2], indent='')
value = self.traverse(kv[0], indent=self.indent+(len(name)+2)*' ')
self.write(sep, name, ': ', value)
sep = line_seperator
if node[0].type.startswith('kvlist'):
# Python 3.5 style key/value list in mapexpr
l = list(node[0])
i = 0
while i < len(l):
name = self.traverse(l[i], indent='')
value = self.traverse(l[i+1], indent=self.indent+(len(name)+2)*' ')
self.write(sep, name, ': ', value)
sep = line_seperator
i += 2
else:
assert node[-1] == 'kvlist'
node = node[-1] # goto kvlist
for kv in node:
assert kv in ('kv', 'kv2', 'kv3')
# kv ::= DUP_TOP expr ROT_TWO expr STORE_SUBSCR
# kv2 ::= DUP_TOP expr expr ROT_THREE STORE_SUBSCR
# kv3 ::= expr expr STORE_MAP
if kv == 'kv':
name = self.traverse(kv[-2], indent='')
value = self.traverse(kv[1], indent=self.indent+(len(name)+2)*' ')
elif kv == 'kv2':
name = self.traverse(kv[1], indent='')
value = self.traverse(kv[-3], indent=self.indent+(len(name)+2)*' ')
elif kv == 'kv3':
name = self.traverse(kv[-2], indent='')
value = self.traverse(kv[0], indent=self.indent+(len(name)+2)*' ')
self.write(sep, name, ': ', value)
sep = line_seperator
self.write('}')
self.indentLess(INDENT_PER_LEVEL)
self.prec = p