Files
python-uncompyle6/uncompyle6/parsers/reducecheck/or_check.py

35 lines
1.4 KiB
Python

# Copyright (c) 2020 Rocky Bernstein
def or_check(self, lhs, n, rule, ast, tokens, first, last):
if rule == ("or", ("expr", "jmp_true", "expr")):
if tokens[last] in (
"LOAD_ASSERT",
"RAISE_VARARGS_1",
):
return True
# The following test is be the most accurate. It prevents "or" from being
# mistake for part of an "assert".
# There one might conceivably be "expr or AssertionError" code, but the
# likelihood of that is vanishingly small.
# The below then is useful until we get better control-flow analysis.
# Note it is too hard in the scanner right nowto turn the LOAD_GLOBAL into
# int LOAD_ASSERT, however in 3.9ish code generation does this by default.
load_global = tokens[last-1]
if load_global == "LOAD_GLOBAL" and load_global.attr == "AssertionError":
return True
jmp_true_target = ast[1][0].attr
jmp_false = tokens[last]
# If the jmp is backwards
if jmp_false == "POP_JUMP_IF_FALSE":
if jmp_false.attr < jmp_false.off2int():
# For a backwards loop, well compare to the instruction *after*
# then POP_JUMP...
jmp_false = tokens[last+1]
return not (jmp_true_target == jmp_false.off2int() or
jmp_true_target < tokens[first].off2int())
return False