Propagate show_asm debug option down to functions

This commit is contained in:
rocky 2021-12-17 05:27:15 -05:00
parent ed5346e526
commit 16c900ff1d
8 changed files with 53 additions and 25 deletions

View File

@ -264,7 +264,7 @@ See Also
.. _Cython: https://en.wikipedia.org/wiki/Cython
.. _trepan: https://pypi.python.org/pypi/trepan2g
.. _trepan: https://pypi.python.org/pypi/trepan3k
.. _compiler: https://pypi.python.org/pypi/spark_parser
.. _HISTORY: https://github.com/rocky/python-uncompyle6/blob/master/HISTORY.md
.. _debuggers: https://pypi.python.org/pypi/trepan3k

View File

@ -92,11 +92,11 @@ class Code(object):
the diassembled code is stored in the attribute '_tokens'.
"""
def __init__(self, co, scanner, classname=None):
def __init__(self, co, scanner, classname=None, show_asm=None):
for i in dir(co):
if i.startswith("co_"):
setattr(self, i, getattr(co, i))
self._tokens, self._customize = scanner.ingest(co, classname)
self._tokens, self._customize = scanner.ingest(co, classname, show_asm=show_asm)
class Scanner(object):

View File

@ -194,6 +194,7 @@ class Scanner37Base(Scanner):
Also, when we encounter certain tokens, we add them to a set which will cause custom
grammar rules. Specifically, variable arg tokens like MAKE_FUNCTION or BUILD_LIST
cause specific rules for the specific number of arguments they take.
"""
def tokens_append(j, token):
@ -455,7 +456,7 @@ class Scanner37Base(Scanner):
# as CONTINUE, but that's okay since we add a grammar
# rule for that.
pattr = argval
target = self.get_target(inst.offset)
target = inst.argval
if target <= inst.offset:
next_opname = self.insts[i + 1].opname

View File

@ -84,12 +84,15 @@ def customize_for_version3(self, version):
"""List comprehensions in Python 3 when handled as a closure.
See if we can combine code.
"""
# FIXME: DRY with comprehension_walk_newer
p = self.prec
self.prec = 27
code_obj = node[1].attr
assert iscode(code_obj)
code = Code(code_obj, self.scanner, self.currentclass)
assert iscode(code_obj), node[1]
code = Code(code_obj, self.scanner, self.currentclass, self.debug_opts["asm"])
ast = self.build_ast(code._tokens, code._customize, code)
self.customize(code._customize)
@ -103,6 +106,10 @@ def customize_for_version3(self, version):
n = ast[1]
# Pick out important parts of the comprehension:
# * the variables we iterate over: "stores"
# * the results we accumulate: "n"
# collections is the name of the expression(s) we are iterating over
collections = [node[-3]]
list_ifs = []

View File

@ -1149,13 +1149,15 @@ class FragmentsWalker(pysource.SourceWalker, object):
n_classdefdeco2 = n_classdef
def gen_source(self, ast, name, customize, is_lambda=False, returnNone=False):
def gen_source(self, ast, name, customize, is_lambda=False, returnNone=False,
debug_opts=None):
"""convert parse tree to Python source code"""
rn = self.return_none
self.return_none = returnNone
old_name = self.name
self.name = name
self.debug_opts = debug_opts
# if code would be empty, append 'pass'
if len(ast) == 0:
self.println(self.indent, "pass")

View File

@ -659,7 +659,12 @@ def make_function3(self, node, is_lambda, nested=1, code_node=None):
has_none = "None" in code.co_names
rn = has_none and not find_none(ast)
self.gen_source(
ast, code.co_name, scanner_code._customize, is_lambda=is_lambda, returnNone=rn
ast,
code.co_name,
scanner_code._customize,
is_lambda=is_lambda,
returnNone=rn,
debug_opts=self.debug_opts,
)
# In obscure cases, a function may be a generator but the "yield"

View File

@ -38,7 +38,7 @@ from uncompyle6.show import maybe_show_tree_param_default
def make_function36(self, node, is_lambda, nested=1, code_node=None):
"""Dump function definition, doc string, and function body in
Python version 3.6 and above.
Python version 3.6 and above.
"""
# MAKE_CLOSURE adds an additional closure slot
@ -51,8 +51,8 @@ def make_function36(self, node, is_lambda, nested=1, code_node=None):
def build_param(ast, name, default, annotation=None):
"""build parameters:
- handle defaults
- handle format tuple parameters
- handle defaults
- handle format tuple parameters
"""
value = default
maybe_show_tree_param_default(self.showast, name, value)
@ -124,8 +124,6 @@ def make_function36(self, node, is_lambda, nested=1, code_node=None):
kw_node = node[pos_args]
if kw_node == "expr":
kw_node = kw_node[0]
if kw_node == "dict":
kw_pairs = kw_node[-1].attr
defparams = []
# FIXME: DRY with code below
@ -150,7 +148,8 @@ def make_function36(self, node, is_lambda, nested=1, code_node=None):
code = code_node.attr
assert iscode(code)
scanner_code = Code(code, self.scanner, self.currentclass)
debug_opts = self.debug_opts["asm"] if self.debug_opts else None
scanner_code = Code(code, self.scanner, self.currentclass, debug_opts)
# add defaults values to parameter names
argc = code.co_argcount
@ -347,7 +346,12 @@ def make_function36(self, node, is_lambda, nested=1, code_node=None):
has_none = "None" in code.co_names
rn = has_none and not find_none(ast)
self.gen_source(
ast, code.co_name, scanner_code._customize, is_lambda=is_lambda, returnNone=rn
ast,
code.co_name,
scanner_code._customize,
is_lambda=is_lambda,
returnNone=rn,
debug_opts=self.debug_opts,
)
# In obscure cases, a function may be a generator but the "yield"

View File

@ -182,6 +182,7 @@ from uncompyle6.semantics.consts import (
from uncompyle6.show import maybe_show_tree
from uncompyle6.util import better_repr
DEFAULT_DEBUG_OPTS = {"asm": False, "tree": False, "grammar": False}
def unicode(x): return x
from io import StringIO
@ -648,7 +649,7 @@ class SourceWalker(GenericASTTraversal, object):
attr = node.attr
data = node.pattr
datatype = type(data)
if isinstance(data, float) :
if isinstance(data, float):
self.write(better_repr(data, self.version))
elif isinstance(data, complex):
self.write(better_repr(data, self.version))
@ -1179,10 +1180,11 @@ class SourceWalker(GenericASTTraversal, object):
"""
p = self.prec
self.prec = 27
code = node[code_index].attr
assert iscode(code), node[code_index]
code = Code(code, self.scanner, self.currentclass)
code_obj = node[code_index].attr
assert iscode(code_obj), node[code_index]
code = Code(code_obj, self.scanner, self.currentclass, self.debug_opts["asm"])
ast = self.build_ast(code._tokens, code._customize, code)
self.customize(code._customize)
@ -2426,13 +2428,22 @@ class SourceWalker(GenericASTTraversal, object):
self.classes.pop(-1)
def gen_source(self, ast, name, customize, is_lambda=False, returnNone=False):
def gen_source(
self,
ast,
name,
customize,
is_lambda=False,
returnNone=False,
debug_opts=DEFAULT_DEBUG_OPTS,
):
"""convert SyntaxTree to Python source code"""
rn = self.return_none
self.return_none = returnNone
old_name = self.name
self.name = name
self.debug_opts = debug_opts
# if code would be empty, append 'pass'
if len(ast) == 0:
self.println(self.indent, "pass")
@ -2525,10 +2536,6 @@ class SourceWalker(GenericASTTraversal, object):
return MAP.get(node, MAP_DIRECT)
#
DEFAULT_DEBUG_OPTS = {"asm": False, "tree": False, "grammar": False}
def code_deparse(
co,
out=sys.stdout,
@ -2623,7 +2630,9 @@ def code_deparse(
)
# What we've been waiting for: Generate source from Syntax Tree!
deparsed.gen_source(deparsed.ast, co.co_name, customize)
deparsed.gen_source(
deparsed.ast, name=co.co_name, customize=customize, debug_opts=debug_opts
)
for g in sorted(deparsed.mod_globs):
deparsed.write("# global %s ## Warning: Unused global\n" % g)