| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465 |
- # Copyright (c) 2020 Rocky Bernstein
- ASSERT_OPS = frozenset(["LOAD_ASSERT", "RAISE_VARARGS_1"])
- def or_check(self, lhs, n, rule, ast, tokens, first, last):
- rhs = rule[1]
- # print("XXX", first, last, rule)
- # for t in range(first, last): print(tokens[t])
- # print("="*40)
- if rhs[0:2] in (("expr_jt", "expr"),
- ("expr_jitop", "expr"),
- ("expr_jit", "expr")):
- if tokens[last] in ASSERT_OPS or tokens[last-1] in ASSERT_OPS:
- 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
- first_offset = tokens[first].off2int()
- expr_jt = ast[0]
- if expr_jt == "expr_jitop":
- jump_true = expr_jt[1]
- else:
- jump_true = expr_jt[1][0]
- jmp_true_target = jump_true.attr
- last_token = tokens[last]
- last_token_offset = last_token.off2int()
- # FIXME: use instructions for all of this
- if jmp_true_target < first_offset:
- return False
- elif jmp_true_target < last_token_offset:
- return True
- # If the jmp is backwards
- if last_token == "POP_JUMP_IF_FALSE" and not self.version[:2] in ((2, 7), (3, 5), (3, 6)):
- if last_token.attr < last_token_offset:
- # For a backwards loop, well compare to the instruction *after*
- # then POP_JUMP...
- last_token = tokens[last + 1]
- # HACK alert 3 is the Python < 3.6ish thing.
- # Convert to using instructions
- return not (
- (last_token_offset <= jmp_true_target <= last_token_offset + 3)
- or jmp_true_target < tokens[first].off2int()
- )
- elif last_token == "JUMP_FORWARD" and expr_jt.kind != "expr_jitop":
- # "or" has to fall through to the next statement
- # FIXME: use instructions for all of this
- return True
- return False
|