ifstmts_jump.py 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. # Copyright (c) 2020, 2023 Rocky Bernstein
  2. from decompyle3.scanners.tok import Token
  3. def ifstmts_jump_invalid(
  4. self, lhs: str, n: int, rule, tree, tokens: list, first: int, last: int
  5. ) -> bool:
  6. come_froms = tree[-1]
  7. # This is complicated, but note that the JUMP_IF instruction comes immediately
  8. # *before* _ifstmts_jump so that's what we have to test
  9. # the COME_FROM against. This can be complicated by intervening
  10. # POP_TOP, and pseudo COME_FROM, ELSE instructions
  11. #
  12. pop_jump_index = first - 1
  13. while pop_jump_index > 0 and tokens[pop_jump_index] in (
  14. "POP_TOP",
  15. "JUMP_FORWARD",
  16. "COME_FROM",
  17. ):
  18. pop_jump_index -= 1
  19. if pop_jump_index == 0:
  20. return True
  21. jump_token = tokens[pop_jump_index]
  22. if jump_token.op not in self.opc.JUMP_OPS:
  23. return False
  24. # FIXME: something is fishy when and EXTENDED ARG is needed before the
  25. # pop_jump_index instruction to get the argument. In this case, the
  26. # _ifsmtst_jump can jump to a spot beyond the come_froms.
  27. # That is going on in the non-EXTENDED_ARG case is that the POP_JUMP_IF
  28. # jumps to a JUMP_(FORWARD) which is changed into an EXTENDED_ARG POP_JUMP_IF
  29. # to the jumped forwarded address
  30. if jump_token.attr > 256:
  31. return False
  32. pop_jump_offset = jump_token.off2int(prefer_last=False)
  33. if isinstance(come_froms, Token):
  34. if jump_token.attr < pop_jump_offset and tree[0] != "pass":
  35. # This is a jump backwards to a loop. All bets are off here when there the
  36. # unless statement is "pass" which has no instructions associated with it.
  37. return False
  38. return come_froms.attr is not None and pop_jump_offset > come_froms.attr
  39. elif len(come_froms) == 0:
  40. return False
  41. else:
  42. return pop_jump_offset > come_froms[-1].attr