You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-03 00:45:53 +08:00
Improve 3.5+ BUILD_MAP_UNPACK...
And add build_tuple_unpack runtime test from a previous commit. We are far from out of the woods, as there is more to do and we've uncovered more bugs in handling this.
This commit is contained in:
BIN
test/bytecode_3.5_run/07_build_map_unpack.pyc
Normal file
BIN
test/bytecode_3.5_run/07_build_map_unpack.pyc
Normal file
Binary file not shown.
10
test/simple_source/bug35/07_build_map_unpack.py
Normal file
10
test/simple_source/bug35/07_build_map_unpack.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# Adapted from Python 3.6 trace.py
|
||||||
|
# Bug was in handling BUID_TUPLE_UNPACK created via
|
||||||
|
# *opts.arguments
|
||||||
|
import argparse
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('filename', nargs='?')
|
||||||
|
parser.add_argument('arguments', nargs=argparse.REMAINDER)
|
||||||
|
opts = parser.parse_args(["foo", "a", "b"])
|
||||||
|
argv = opts.filename, *opts.arguments
|
||||||
|
assert argv == ('foo', 'a', 'b')
|
@@ -626,7 +626,7 @@ class Python3Parser(PythonParser):
|
|||||||
self.addRule(rule, nop_func)
|
self.addRule(rule, nop_func)
|
||||||
rule = 'expr ::= build_list_unpack'
|
rule = 'expr ::= build_list_unpack'
|
||||||
self.addRule(rule, nop_func)
|
self.addRule(rule, nop_func)
|
||||||
elif opname_base == 'BUILD_MAP':
|
elif opname_base in ('BUILD_MAP', 'BUILD_MAP_UNPACK'):
|
||||||
kvlist_n = "kvlist_%s" % token.attr
|
kvlist_n = "kvlist_%s" % token.attr
|
||||||
if opname == 'BUILD_MAP_n':
|
if opname == 'BUILD_MAP_n':
|
||||||
# PyPy sometimes has no count. Sigh.
|
# PyPy sometimes has no count. Sigh.
|
||||||
@@ -645,23 +645,21 @@ class Python3Parser(PythonParser):
|
|||||||
# FIXME: Use the attr
|
# FIXME: Use the attr
|
||||||
# so this doesn't run into exponential parsing time.
|
# so this doesn't run into exponential parsing time.
|
||||||
if opname.startswith('BUILD_MAP_UNPACK'):
|
if opname.startswith('BUILD_MAP_UNPACK'):
|
||||||
# FIXME: start here
|
|
||||||
# rule = "%s ::= %s %s" % (kvlist_n, 'expr ' * (token.attr*2), opname)
|
|
||||||
rule = kvlist_n + ' ::= ' + 'expr ' * (token.attr*2)
|
|
||||||
self.add_unique_rule(rule, opname, token.attr, customize)
|
self.add_unique_rule(rule, opname, token.attr, customize)
|
||||||
rule = 'dict_entry ::= ' + 'expr ' * (token.attr*2)
|
rule = 'dict_entry ::= ' + 'expr ' * (token.attr*2)
|
||||||
self.add_unique_rule(rule, opname, token.attr, customize)
|
self.add_unique_rule(rule, opname, token.attr, customize)
|
||||||
rule = 'dict ::= %s' % ('dict_entry ' * token.attr)
|
|
||||||
self.addRule(rule, nop_func)
|
|
||||||
|
|
||||||
|
# FIXME: start here. The LHS should be unmap_dict, not dict.
|
||||||
# FIXME: really we need a combination of dict_entry-like things.
|
# FIXME: really we need a combination of dict_entry-like things.
|
||||||
# It just so happens the most common case is not to mix
|
# It just so happens the most common case is not to mix
|
||||||
# dictionary comphensions with dictionary, elements
|
# dictionary comphensions with dictionary, elements
|
||||||
if self.seen_LOAD_DICTCOMP:
|
if self.seen_LOAD_DICTCOMP:
|
||||||
rule = 'dict ::= %s%s' % ('dict_comp ' * token.attr, opname)
|
rule = 'dict ::= %s%s' % ('dict_comp ' * token.attr, opname)
|
||||||
self.addRule(rule, nop_func)
|
self.addRule(rule, nop_func)
|
||||||
|
rule = """
|
||||||
rule = 'unmap_dict ::= %s%s' % (('dict ' * token.attr), opname)
|
expr ::= unmap_dict
|
||||||
|
unmap_dict ::= %s%s
|
||||||
|
""" % ('expr ' * token.attr, opname)
|
||||||
else:
|
else:
|
||||||
rule = "%s ::= %s %s" % (kvlist_n, 'expr ' * (token.attr*2), opname)
|
rule = "%s ::= %s %s" % (kvlist_n, 'expr ' * (token.attr*2), opname)
|
||||||
self.add_unique_rule(rule, opname, token.attr, customize)
|
self.add_unique_rule(rule, opname, token.attr, customize)
|
||||||
|
@@ -144,7 +144,7 @@ class Scanner3(Scanner):
|
|||||||
varargs_ops.add(self.opc.CALL_METHOD)
|
varargs_ops.add(self.opc.CALL_METHOD)
|
||||||
if self.version >= 3.5:
|
if self.version >= 3.5:
|
||||||
varargs_ops |= set([self.opc.BUILD_SET_UNPACK,
|
varargs_ops |= set([self.opc.BUILD_SET_UNPACK,
|
||||||
# self.opc.BUILD_MAP_UNPACK, # we will handle this later
|
self.opc.BUILD_MAP_UNPACK, # we will handle this later
|
||||||
self.opc.BUILD_LIST_UNPACK,
|
self.opc.BUILD_LIST_UNPACK,
|
||||||
self.opc.BUILD_TUPLE_UNPACK])
|
self.opc.BUILD_TUPLE_UNPACK])
|
||||||
if self.version >= 3.6:
|
if self.version >= 3.6:
|
||||||
|
@@ -351,6 +351,7 @@ def customize_for_version3(self, version):
|
|||||||
PRECEDENCE['call_ex_kw2'] = 100
|
PRECEDENCE['call_ex_kw2'] = 100
|
||||||
PRECEDENCE['call_ex_kw3'] = 100
|
PRECEDENCE['call_ex_kw3'] = 100
|
||||||
PRECEDENCE['call_ex_kw4'] = 100
|
PRECEDENCE['call_ex_kw4'] = 100
|
||||||
|
PRECEDENCE['unmap_dict'] = 0
|
||||||
|
|
||||||
TABLE_DIRECT.update({
|
TABLE_DIRECT.update({
|
||||||
'tryfinally36': ( '%|try:\n%+%c%-%|finally:\n%+%c%-\n\n',
|
'tryfinally36': ( '%|try:\n%+%c%-%|finally:\n%+%c%-\n\n',
|
||||||
|
Reference in New Issue
Block a user