You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-03 00:45:53 +08:00
91 lines
3.2 KiB
Python
91 lines
3.2 KiB
Python
# Copyright (c) 2022 Rocky Bernstein
|
|
"""
|
|
If statement reduction check for Python 2.6 (and older?)
|
|
"""
|
|
|
|
|
|
def ifstmt2(self, lhs, n, rule, ast, tokens, first, last):
|
|
|
|
# print("XXX", first, last)
|
|
# for t in range(first, last):
|
|
# print(tokens[t])
|
|
# print("=" * 30)
|
|
|
|
if lhs == "ifstmtl":
|
|
if last == n:
|
|
last -= 1
|
|
pass
|
|
if tokens[last].attr and isinstance(tokens[last].attr, int):
|
|
if tokens[first].offset >= tokens[last].attr:
|
|
return True
|
|
pass
|
|
pass
|
|
|
|
# Make sure jumps don't extend beyond the end of the if statement.
|
|
l = last
|
|
if l == n:
|
|
l -= 1
|
|
if isinstance(tokens[l].offset, str):
|
|
last_offset = int(tokens[l].offset.split("_")[0], 10)
|
|
else:
|
|
last_offset = tokens[l].offset
|
|
for i in range(first, l):
|
|
t = tokens[i]
|
|
# instead of POP_JUMP_IF, should we use op attributes?
|
|
if t.kind in ("JUMP_IF_FALSE", "JUMP_IF_TRUE"):
|
|
jif_target = int(t.pattr)
|
|
target_instr = self.insts[self.offset2inst_index[jif_target]]
|
|
if lhs == "iflaststmtl" and target_instr.opname == "JUMP_ABSOLUTE":
|
|
jif_target = target_instr.arg
|
|
if jif_target > last_offset:
|
|
# In come cases, where we have long bytecode, a
|
|
# "POP_JUMP_IF_TRUE/FALSE" offset might be too
|
|
# large for the instruction; so instead it
|
|
# jumps to a JUMP_FORWARD. Allow that here.
|
|
if tokens[l] == "JUMP_FORWARD":
|
|
return tokens[l].attr != jif_target
|
|
return True
|
|
elif lhs == "ifstmtl" and tokens[first].off2int() > jif_target:
|
|
# A conditional JUMP to the loop is expected for "ifstmtl"
|
|
return False
|
|
pass
|
|
pass
|
|
pass
|
|
|
|
if ast:
|
|
testexpr = ast[0]
|
|
|
|
if (last + 1) < n and tokens[last + 1] == "COME_FROM_LOOP":
|
|
# iflastsmtl jumped outside of loop. No good.
|
|
return True
|
|
|
|
if testexpr[0] in ("testtrue", "testfalse"):
|
|
test = testexpr[0]
|
|
if len(test) > 1 and test[1].kind.startswith("jmp_"):
|
|
jmp_target = int(test[1][0].pattr)
|
|
if last == len(tokens):
|
|
last -= 1
|
|
if (
|
|
tokens[first].off2int(prefer_last=True)
|
|
<= jmp_target
|
|
< tokens[last].off2int(prefer_last=False)
|
|
):
|
|
return True
|
|
# jmp_target less than tokens[first] is okay - is to a loop
|
|
# jmp_target equal tokens[last] is also okay: normal non-optimized non-loop jump
|
|
if jmp_target > tokens[last].off2int():
|
|
# One more weird case to look out for
|
|
# if c1:
|
|
# if c2: # Jumps around the *outer* "else"
|
|
# ...
|
|
# else:
|
|
if jmp_target == tokens[last - 1].attr:
|
|
return False
|
|
if last < n and tokens[last].kind.startswith("JUMP"):
|
|
return False
|
|
return True
|
|
|
|
pass
|
|
pass
|
|
return False
|