You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-03 08:49:51 +08:00
Fix parser slowness in decompiling 3.x locale.py..
And remove grammar inefficiency in adding extraneous kwargs in <= 3.2 kwargs was nullable so it might not have been wasn't wrong, just inefficient.
This commit is contained in:
@@ -112,9 +112,10 @@ class Python3Parser(PythonParser):
|
||||
continues ::= continue
|
||||
|
||||
|
||||
kwarg ::= LOAD_CONST expr
|
||||
kwargs ::= kwarg*
|
||||
kwargs1 ::= kwarg+
|
||||
kwarg ::= LOAD_CONST expr
|
||||
kwargs ::= kwarg+
|
||||
no_kwargs ::=
|
||||
|
||||
|
||||
classdef ::= build_class store
|
||||
|
||||
@@ -527,7 +528,7 @@ class Python3Parser(PythonParser):
|
||||
subclassing is, well, is pretty base. And we want it that way: lean and
|
||||
mean so that parsing will go faster.
|
||||
|
||||
Here, we add additional grammra rules based on specific instructions
|
||||
Here, we add additional grammar rules based on specific instructions
|
||||
that are in the instruction/token stream. In classes that
|
||||
inherit from from here and other versions, grammar rules may
|
||||
also be removed.
|
||||
@@ -656,9 +657,9 @@ class Python3Parser(PythonParser):
|
||||
('dict ' * token.attr) +
|
||||
'BUILD_MAP_UNPACK')
|
||||
else:
|
||||
rule = kvlist_n + ' ::= ' + 'expr ' * (token.attr*2)
|
||||
rule = "%s ::= %s %s" % (kvlist_n, 'expr ' * (token.attr*2), opname)
|
||||
self.add_unique_rule(rule, opname, token.attr, customize)
|
||||
rule = "dict ::= %s %s" % (kvlist_n, opname)
|
||||
rule = "dict ::= %s" % kvlist_n
|
||||
else:
|
||||
rule = kvlist_n + ' ::= ' + 'expr expr STORE_MAP ' * token.attr
|
||||
self.add_unique_rule(rule, opname, token.attr, customize)
|
||||
@@ -866,13 +867,13 @@ class Python3Parser(PythonParser):
|
||||
opname, token.attr, customize)
|
||||
|
||||
if args_kw > 0:
|
||||
kwargs_str = 'kwargs1 '
|
||||
kwargs_str = 'kwargs '
|
||||
else:
|
||||
kwargs_str = ''
|
||||
|
||||
# Note order of kwargs and pos args changed between 3.3-3.4
|
||||
if self.version <= 3.2:
|
||||
rule = ('mkfunc ::= %s%sload_closure LOAD_CONST kwargs %s'
|
||||
rule = ('mkfunc ::= %s%sload_closure LOAD_CONST %s'
|
||||
% (kwargs_str, 'expr ' * args_pos, opname))
|
||||
elif self.version == 3.3:
|
||||
rule = ('mkfunc ::= %s%sload_closure LOAD_CONST LOAD_CONST %s'
|
||||
@@ -980,29 +981,37 @@ class Python3Parser(PythonParser):
|
||||
opname))
|
||||
self.add_make_function_rule(rule_pat, opname, token.attr, customize)
|
||||
|
||||
if args_kw == 0:
|
||||
kwargs = 'no_kwargs'
|
||||
else:
|
||||
kwargs = 'kwargs'
|
||||
if self.version < 3.3:
|
||||
# positional args after keyword args
|
||||
rule = ('mkfunc ::= kwargs %s%s %s' %
|
||||
rule = ('mkfunc ::= %s %s%s%s' %
|
||||
(kwargs, 'pos_arg ' * args_pos, 'LOAD_CONST ',
|
||||
opname))
|
||||
self.add_unique_rule(rule, opname, token.attr, customize)
|
||||
rule = ('mkfunc ::= %s%s%s' %
|
||||
('pos_arg ' * args_pos, 'LOAD_CONST ',
|
||||
opname))
|
||||
elif self.version == 3.3:
|
||||
# positional args after keyword args
|
||||
rule = ('mkfunc ::= kwargs %s%s %s' %
|
||||
('pos_arg ' * args_pos, 'LOAD_CONST '*2,
|
||||
rule = ('mkfunc ::= %s %s%s%s' %
|
||||
(kwargs, 'pos_arg ' * args_pos, 'LOAD_CONST '*2,
|
||||
opname))
|
||||
elif self.version > 3.5:
|
||||
# positional args before keyword args
|
||||
rule = ('mkfunc ::= %skwargs1 %s %s' %
|
||||
('pos_arg ' * args_pos, 'LOAD_CONST '*2,
|
||||
rule = ('mkfunc ::= %s%s %s%s' %
|
||||
('pos_arg ' * args_pos, kwargs, 'LOAD_CONST '*2,
|
||||
opname))
|
||||
elif self.version > 3.3:
|
||||
# positional args before keyword args
|
||||
rule = ('mkfunc ::= %skwargs %s %s' %
|
||||
('pos_arg ' * args_pos, 'LOAD_CONST '*2,
|
||||
rule = ('mkfunc ::= %s%s %s%s' %
|
||||
('pos_arg ' * args_pos, kwargs, 'LOAD_CONST '*2,
|
||||
opname))
|
||||
else:
|
||||
rule = ('mkfunc ::= kwargs %sexpr %s' %
|
||||
('pos_arg ' * args_pos, opname))
|
||||
rule = ('mkfunc ::= %s%sexpr %s' %
|
||||
(kwargs, 'pos_arg ' * args_pos, opname))
|
||||
self.add_unique_rule(rule, opname, token.attr, customize)
|
||||
if opname.startswith('MAKE_FUNCTION_A'):
|
||||
if self.version >= 3.6:
|
||||
|
@@ -563,8 +563,16 @@ def customize_for_version(self, is_pypy, version):
|
||||
kv_node = node[0]
|
||||
l = list(kv_node)
|
||||
i = 0
|
||||
|
||||
length = len(l)
|
||||
# FIXME: Parser-speed improved grammars will have BUILD_MAP
|
||||
# at the end. So in the future when everything is
|
||||
# complete, we can do an "assert" instead of "if".
|
||||
if kv_node[-1].kind.startswith("BUILD_MAP"):
|
||||
length -= 1
|
||||
|
||||
# Respect line breaks from source
|
||||
while i < len(l):
|
||||
while i < length:
|
||||
self.write(sep)
|
||||
name = self.traverse(l[i], indent='')
|
||||
# Strip off beginning and trailing quotes in name
|
||||
|
@@ -431,10 +431,7 @@ def make_function2(self, node, is_lambda, nested=1, codeNode=None):
|
||||
code, self.version)
|
||||
|
||||
# Python 2 doesn't support the "nonlocal" statement
|
||||
try:
|
||||
assert self.version >= 3.0 or not nonlocals
|
||||
except:
|
||||
from trepan.api import debug; debug()
|
||||
assert self.version >= 3.0 or not nonlocals
|
||||
|
||||
for g in sorted((all_globals & self.mod_globs) | globals):
|
||||
self.println(self.indent, 'global ', g)
|
||||
@@ -516,14 +513,22 @@ def make_function3(self, node, is_lambda, nested=1, codeNode=None):
|
||||
if isinstance(args_node.attr, tuple):
|
||||
pos_args, kw_args, annotate_argc = args_node.attr
|
||||
# FIXME: there is probably a better way to classify this.
|
||||
have_kwargs = node[0].kind.startswith('kwarg') or node[0] == 'no_kwargs'
|
||||
if len(node) >= 4:
|
||||
lc_index = -4
|
||||
else:
|
||||
lc_index = -3
|
||||
pass
|
||||
|
||||
if (self.version <= 3.3 and len(node) > 2 and
|
||||
node[lambda_index] != 'LOAD_LAMBDA' and
|
||||
(node[0].kind.startswith('kwarg') or node[-4].kind != 'load_closure')):
|
||||
node[lambda_index] != 'LOAD_LAMBDA' and
|
||||
(have_kwargs or node[lc_index].kind != 'load_closure')):
|
||||
# args are after kwargs; kwargs are bundled as one node
|
||||
defparams = node[1:args_node.attr[0]+1]
|
||||
else:
|
||||
# args are before kwargs; kwags as bundled as one node
|
||||
defparams = node[:args_node.attr[0]]
|
||||
pass
|
||||
else:
|
||||
if self.version < 3.6:
|
||||
defparams = node[:args_node.attr]
|
||||
@@ -653,7 +658,7 @@ def make_function3(self, node, is_lambda, nested=1, codeNode=None):
|
||||
for n in node:
|
||||
if n == 'pos_arg':
|
||||
continue
|
||||
elif self.version >= 3.4 and not (n.kind in ('kwargs', 'kwargs1', 'kwarg')):
|
||||
elif self.version >= 3.4 and not (n.kind in ('kwargs', 'no_kwargs', 'kwarg')):
|
||||
continue
|
||||
else:
|
||||
self.preorder(n)
|
||||
|
@@ -404,7 +404,7 @@ class SourceWalker(GenericASTTraversal, object):
|
||||
|
||||
def n_mkfunc_annotate(node):
|
||||
|
||||
if self.version >= 3.3 or node[-2] == 'kwargs':
|
||||
if self.version >= 3.3 or node[-2] in ('kwargs', 'no_kwargs'):
|
||||
# LOAD_CONST code object ..
|
||||
# LOAD_CONST 'x0' if >= 3.3
|
||||
# EXTENDED_ARG
|
||||
@@ -1041,7 +1041,7 @@ class SourceWalker(GenericASTTraversal, object):
|
||||
|
||||
def n_mkfunc(self, node):
|
||||
|
||||
if self.version >= 3.3 or node[-2] == 'kwargs':
|
||||
if self.version >= 3.3 or node[-2] in ('kwargs', 'no_kwargs'):
|
||||
# LOAD_CONST code object ..
|
||||
# LOAD_CONST 'x0' if >= 3.3
|
||||
# MAKE_FUNCTION ..
|
||||
@@ -1057,7 +1057,7 @@ class SourceWalker(GenericASTTraversal, object):
|
||||
self.write(func_name)
|
||||
|
||||
self.indent_more()
|
||||
self.make_function(node, is_lambda=False, codeNode=code_node)
|
||||
self.make_function(node, is_lambda=False, code_node=code_node)
|
||||
|
||||
if len(self.param_stack) > 1:
|
||||
self.write('\n\n')
|
||||
@@ -1067,14 +1067,14 @@ class SourceWalker(GenericASTTraversal, object):
|
||||
self.prune() # stop recursing
|
||||
|
||||
def make_function(self, node, is_lambda, nested=1,
|
||||
codeNode=None, annotate=None):
|
||||
code_node=None, annotate=None):
|
||||
if self.version >= 3.0:
|
||||
make_function3(self, node, is_lambda, nested, codeNode)
|
||||
make_function3(self, node, is_lambda, nested, code_node)
|
||||
else:
|
||||
make_function2(self, node, is_lambda, nested, codeNode)
|
||||
make_function2(self, node, is_lambda, nested, code_node)
|
||||
|
||||
def n_mklambda(self, node):
|
||||
self.make_function(node, is_lambda=True, codeNode=node[-2])
|
||||
self.make_function(node, is_lambda=True, code_node=node[-2])
|
||||
self.prune() # stop recursing
|
||||
|
||||
def n_list_comp(self, node):
|
||||
@@ -1563,7 +1563,7 @@ class SourceWalker(GenericASTTraversal, object):
|
||||
|
||||
assert 'mkfunc' == build_class[1]
|
||||
mkfunc = build_class[1]
|
||||
if mkfunc[0] == 'kwargs':
|
||||
if mkfunc[0] in ('kwargs', 'no_kwargs'):
|
||||
if 3.0 <= self.version <= 3.2:
|
||||
for n in mkfunc:
|
||||
if hasattr(n, 'attr') and iscode(n.attr):
|
||||
@@ -1608,7 +1608,10 @@ class SourceWalker(GenericASTTraversal, object):
|
||||
subclass_info = node
|
||||
subclass_code = build_class[1][0].attr
|
||||
elif not subclass_info:
|
||||
subclass_code = build_class[1][0].attr
|
||||
if mkfunc[0] in ('no_kwargs', 'kwargs'):
|
||||
subclass_code = mkfunc[1].attr
|
||||
else:
|
||||
subclass_code = mkfunc[0].attr
|
||||
subclass_info = node[0]
|
||||
else:
|
||||
if node == 'classdefdeco2':
|
||||
@@ -1764,9 +1767,17 @@ class SourceWalker(GenericASTTraversal, object):
|
||||
# Python 3.5+ style key/value list in dict
|
||||
kv_node = node[0]
|
||||
l = list(kv_node)
|
||||
length = len(l)
|
||||
|
||||
# FIXME: Parser-speed improved grammars will have BUILD_MAP
|
||||
# at the end. So in the future when everything is
|
||||
# complete, we can do an "assert" instead of "if".
|
||||
if kv_node[-1].kind.startswith("BUILD_MAP"):
|
||||
length -= 1
|
||||
i = 0
|
||||
|
||||
# Respect line breaks from source
|
||||
while i < len(l):
|
||||
while i < length:
|
||||
self.write(sep)
|
||||
name = self.traverse(l[i], indent='')
|
||||
if i > 0:
|
||||
|
Reference in New Issue
Block a user