diff --git a/uncompyle6/semantics/pysource.py b/uncompyle6/semantics/pysource.py index 4991484c..f2bf4357 100644 --- a/uncompyle6/semantics/pysource.py +++ b/uncompyle6/semantics/pysource.py @@ -210,7 +210,8 @@ class SourceWalkerError(Exception): class SourceWalker(GenericASTTraversal, NonterminalActions, ComprehensionMixin): """ - Class to traverses a Parse Tree of the bytecode instruction built from parsing to produce some sort of source text. + Class to traverses a Parse Tree of the bytecode instruction built from parsing to + produce some sort of source text. The Parse tree may be turned an Abstract Syntax tree as an intermediate step. """ @@ -318,7 +319,7 @@ class SourceWalker(GenericASTTraversal, NonterminalActions, ComprehensionMixin): customize_for_version(self, is_pypy, version) return - def maybe_show_tree(self, ast, phase): + def maybe_show_tree(self, tree, phase): if self.showast.get("before", False): self.println( """ @@ -334,7 +335,7 @@ class SourceWalker(GenericASTTraversal, NonterminalActions, ComprehensionMixin): + " " ) if self.showast.get(phase, False): - maybe_show_tree(self, ast) + maybe_show_tree(self, tree) def str_with_template(self, ast): stream = sys.stdout diff --git a/uncompyle6/semantics/transform.py b/uncompyle6/semantics/transform.py index 0339d8af..430f1e0f 100644 --- a/uncompyle6/semantics/transform.py +++ b/uncompyle6/semantics/transform.py @@ -1,4 +1,4 @@ -# Copyright (c) 2019-2023 by Rocky Bernstein +# Copyright (c) 2019-2024 by Rocky Bernstein # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -14,6 +14,7 @@ # along with this program. If not, see . from copy import copy +from typing import Optional from spark_parser import GenericASTTraversal, GenericASTTraversalPruningException @@ -56,29 +57,34 @@ def is_docstring(node, version, co_consts): return node == ASSIGN_DOC_STRING(co_consts[0], doc_load) -def is_not_docstring(call_stmt_node): +def is_not_docstring(call_stmt_node) -> bool: try: return ( call_stmt_node == "call_stmt" and call_stmt_node[0][0] == "LOAD_STR" and call_stmt_node[1] == "POP_TOP" ) - except: + except Exception: return False class TreeTransform(GenericASTTraversal, object): - def __init__(self, version, show_ast=None, is_pypy=False): + def __init__( + self, + version: tuple, + is_pypy=False, + show_ast: Optional[dict] = None, + ): self.version = version self.showast = show_ast self.is_pypy = is_pypy return - def maybe_show_tree(self, ast): + def maybe_show_tree(self, tree): if isinstance(self.showast, dict) and ( self.showast.get("before") or self.showast.get("after") ): - maybe_show_tree(self, ast) + maybe_show_tree(self, tree) def preorder(self, node=None): """Walk the tree in roughly 'preorder' (a bit of a lie explained below). @@ -122,6 +128,7 @@ class TreeTransform(GenericASTTraversal, object): mkfunc_pattr = node[-1].pattr if isinstance(mkfunc_pattr, tuple): + assert isinstance(mkfunc_pattr, tuple) assert len(mkfunc_pattr) == 4 and isinstance(mkfunc_pattr, int) if len(code.co_consts) > 0 and isinstance(code.co_consts[0], str): @@ -216,6 +223,7 @@ class TreeTransform(GenericASTTraversal, object): return node if isinstance(call[1], SyntaxTree): expr = call[1][0] + assert_expr.transformed_by = "n_ifstmt" node = SyntaxTree( kind, [ @@ -225,8 +233,8 @@ class TreeTransform(GenericASTTraversal, object): expr, RAISE_VARARGS_1, ], + transformed_by="n_ifstmt", ) - node.transformed_by = "n_ifstmt" pass pass else: @@ -254,9 +262,10 @@ class TreeTransform(GenericASTTraversal, object): LOAD_ASSERT = expr[0] node = SyntaxTree( - kind, [assert_expr, jump_cond, LOAD_ASSERT, RAISE_VARARGS_1] + kind, + [assert_expr, jump_cond, LOAD_ASSERT, RAISE_VARARGS_1], + transformed_by="n_ifstmt", ) - node.transformed_by = ("n_ifstmt",) pass pass return node @@ -416,6 +425,12 @@ class TreeTransform(GenericASTTraversal, object): list_for_node.transformed_by = ("n_list_for",) return list_for_node + def n_negated_testtrue(self, node): + assert node[0] == "testtrue" + test_node = node[0][0] + test_node.transformed_by = "n_negated_testtrue" + return test_node + def n_stmts(self, node): if node.first_child() == "SETUP_ANNOTATIONS": prev = node[0][0] @@ -448,26 +463,28 @@ class TreeTransform(GenericASTTraversal, object): node = self.preorder(node) return node - def transform(self, ast, code): - self.maybe_show_tree(ast) - self.ast = copy(ast) + def transform(self, parse_tree: GenericASTTraversal, code) -> GenericASTTraversal: + self.maybe_show_tree(parse_tree) + self.ast = copy(parse_tree) + del parse_tree self.ast = self.traverse(self.ast, is_lambda=False) + n = len(self.ast) try: # Disambiguate a string (expression) which appears as a "call_stmt" at # the beginning of a function versus a docstring. Seems pretty academic, # but this is Python. - call_stmt = ast[0][0] + call_stmt = self.ast[0][0] if is_not_docstring(call_stmt): call_stmt.kind = "string_at_beginning" call_stmt.transformed_by = "transform" pass - except: + except Exception: pass try: - for i in range(len(self.ast)): - sstmt = ast[i] + for i in range(n): + sstmt = self.ast[i] if len(sstmt) == 1 and sstmt == "sstmt": self.ast[i] = self.ast[i][0] @@ -493,7 +510,7 @@ class TreeTransform(GenericASTTraversal, object): if self.ast[-1] == RETURN_NONE: self.ast.pop() # remove last node # todo: if empty, add 'pass' - except: + except Exception: pass return self.ast