ifstmts_jump.py 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. # Copyright (c) 2020 Rocky Bernstein
  2. from uncompyle6.scanners.tok import Token
  3. def ifstmts_jump(self, lhs, n, rule, ast, tokens, first, last):
  4. if len(rule[1]) <= 1 or not ast:
  5. return False
  6. come_froms = ast[-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. "ELSE",
  15. "POP_TOP",
  16. "JUMP_FORWARD",
  17. "COME_FROM",
  18. ):
  19. pop_jump_index -= 1
  20. # FIXME: something is fishy when and EXTENDED ARG is needed before the
  21. # pop_jump_index instruction to get the argument. In this case, the
  22. # _ifsmtst_jump can jump to a spot beyond the come_froms.
  23. # That is going on in the non-EXTENDED_ARG case is that the POP_JUMP_IF
  24. # jumps to a JUMP_(FORWARD) which is changed into an EXTENDED_ARG POP_JUMP_IF
  25. # to the jumped forwarded address
  26. if tokens[pop_jump_index].attr > 256:
  27. return False
  28. pop_jump_offset = tokens[pop_jump_index].off2int(prefer_last=False)
  29. if isinstance(come_froms, Token):
  30. if tokens[pop_jump_index].attr < pop_jump_offset and ast[0] != "pass":
  31. # This is a jump backwards to a loop. All bets are off here when there the
  32. # unless statement is "pass" which has no instructions associated with it.
  33. return False
  34. return come_froms.attr is not None and pop_jump_offset > come_froms.attr
  35. elif len(come_froms) == 0:
  36. return False
  37. else:
  38. return pop_jump_offset > come_froms[-1].attr