You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-02 16:44:46 +08:00
final RETURN removal bug
We want to remove a final return from a module, but otherwise not. Note we'll no lonager be able to verify functools.pyc as there is now a return after a raise statement. That will have to be delt with separately. May address Issue #17.
This commit is contained in:
BIN
test/bytecode_2.7/06_return_bug.pyc
Normal file
BIN
test/bytecode_2.7/06_return_bug.pyc
Normal file
Binary file not shown.
Binary file not shown.
11
test/simple_source/def/06_ifTrue_optimize_bug.py
Normal file
11
test/simple_source/def/06_ifTrue_optimize_bug.py
Normal file
@@ -0,0 +1,11 @@
|
||||
# Bug in uncompyle6 and pycdc for (some) Python 3 bytecodes.
|
||||
# Problem is JUMP_IF_FALSE is optimized away leaving
|
||||
# the unreachible LOAD_CONST below
|
||||
|
||||
# Disassembly of lambda is:
|
||||
# 0 LOAD_CONST 2: 2
|
||||
# 3 RETURN_VALUE
|
||||
# 4 LOAD_CONST 3: 3
|
||||
# 7 RETURN_VALUE
|
||||
|
||||
lambda: 2 if True else 3
|
7
test/simple_source/def/06_return_bug.py
Normal file
7
test/simple_source/def/06_return_bug.py
Normal file
@@ -0,0 +1,7 @@
|
||||
# But is that we were removing the return 3 at the end of the function
|
||||
# and a the end of *any* function. We do want to remove "return None"
|
||||
# at the end of a main program, but that's something different.
|
||||
def fn(self):
|
||||
if self.id == 'hat':
|
||||
return 4
|
||||
return 3
|
@@ -550,7 +550,7 @@ class SourceWalker(GenericASTTraversal, object):
|
||||
def indentLess(self, indent=TAB):
|
||||
self.indent = self.indent[:-len(indent)]
|
||||
|
||||
def traverse(self, node, indent=None, isLambda=0):
|
||||
def traverse(self, node, indent=None, isLambda=False):
|
||||
self.param_stack.append(self.params)
|
||||
if indent is None: indent = self.indent
|
||||
p = self.pending_newlines
|
||||
@@ -1059,7 +1059,10 @@ class SourceWalker(GenericASTTraversal, object):
|
||||
self.customize(code._customize)
|
||||
ast = ast[0][0][0][0][0]
|
||||
|
||||
n = ast[iter_index]
|
||||
try:
|
||||
n = ast[iter_index]
|
||||
except:
|
||||
from trepan.api import debug; debug()
|
||||
assert n == 'list_iter'
|
||||
|
||||
# find innermost node
|
||||
@@ -1814,7 +1817,8 @@ class SourceWalker(GenericASTTraversal, object):
|
||||
self.println(self.text)
|
||||
self.return_none = rn
|
||||
|
||||
def build_ast(self, tokens, customize, isLambda=0, noneInNames=False):
|
||||
def build_ast(self, tokens, customize, isLambda=False,
|
||||
noneInNames=False, isTopLevel=False):
|
||||
|
||||
# assert isinstance(tokens[0], Token)
|
||||
|
||||
@@ -1835,8 +1839,12 @@ class SourceWalker(GenericASTTraversal, object):
|
||||
if self.hide_internal:
|
||||
if len(tokens) >= 2 and not noneInNames:
|
||||
if tokens[-1].type == 'RETURN_VALUE':
|
||||
# Should we also check for returning None?
|
||||
if tokens[-2].type == 'LOAD_CONST':
|
||||
del tokens[-2:]
|
||||
if True or isTopLevel:
|
||||
del tokens[-2:]
|
||||
else:
|
||||
tokens.append(Token('RETURN_LAST'))
|
||||
else:
|
||||
tokens.append(Token('RETURN_LAST'))
|
||||
if len(tokens) == 0:
|
||||
@@ -1877,7 +1885,8 @@ def deparse_code(version, co, out=sys.stdout, showasm=False, showast=False,
|
||||
deparsed = SourceWalker(version, out, scanner, showast=showast,
|
||||
debug_parser=debug_parser, compile_mode=compile_mode)
|
||||
|
||||
deparsed.ast = deparsed.build_ast(tokens, customize)
|
||||
isTopLevel = co.co_name == '<module>'
|
||||
deparsed.ast = deparsed.build_ast(tokens, customize, isTopLevel=isTopLevel)
|
||||
|
||||
assert deparsed.ast == 'stmts', 'Should have parsed grammar start'
|
||||
|
||||
|
Reference in New Issue
Block a user