| 679 | return |
| 680 | |
| 681 | def reduce_is_invalid(self, rule, ast, tokens, first, last): |
| 682 | if tokens is None: |
| 683 | return False |
| 684 | lhs = rule[0] |
| 685 | n = len(tokens) |
| 686 | |
| 687 | fn = self.reduce_check_table.get(lhs, None) |
| 688 | if fn: |
| 689 | if fn(self, lhs, n, rule, ast, tokens, first, last): |
| 690 | return True |
| 691 | pass |
| 692 | if rule == ("and", ("expr", "jmp_false", "expr", "\\e_come_from_opt")): |
| 693 | # If the instruction after the instructions forming the "and" is an "YIELD_VALUE" |
| 694 | # then this is probably an "if" inside a comprehension. |
| 695 | if tokens[last] == "YIELD_VALUE": |
| 696 | # Note: We might also consider testing last+1 being "POP_TOP" |
| 697 | return True |
| 698 | |
| 699 | # Test that jump_false jump somewhere beyond the end of the "and" |
| 700 | # it might not be exactly the end of the "and" because this and can |
| 701 | # be a part of a larger condition. Oddly in 2.7 there doesn't seem to be |
| 702 | # an optimization where the "and" jump_false is back to a loop. |
| 703 | jmp_false = ast[1] |
| 704 | if jmp_false[0] == "POP_JUMP_IF_FALSE": |
| 705 | while first < last and isinstance(tokens[last].offset, str): |
| 706 | last -= 1 |
| 707 | if jmp_false[0].attr < tokens[last].offset: |
| 708 | return True |
| 709 | |
| 710 | # Test that jmp_false jumps to the end of "and" |
| 711 | # or that it jumps to the same place as the end of "and" |
| 712 | jmp_false = ast[1][0] |
| 713 | jmp_target = jmp_false.offset + jmp_false.attr + 3 |
| 714 | return not ( |
| 715 | jmp_target == tokens[last].offset |
| 716 | or tokens[last].pattr == jmp_false.pattr |
| 717 | ) |
| 718 | # Dead code testing... |
| 719 | # if lhs == 'while1elsestmt': |
| 720 | # from trepan.api import debug; debug() |
| 721 | elif ( |
| 722 | lhs in ("aug_assign1", "aug_assign2") |
| 723 | and ast[0] |
| 724 | and ast[0][0] in ("and", "or") |
| 725 | ): |
| 726 | return True |
| 727 | elif lhs == "assert_expr_and": |
| 728 | jmp_false = ast[1] |
| 729 | jump_target = jmp_false[0].attr |
| 730 | return jump_target > tokens[last].off2int() |
| 731 | elif lhs in ("raise_stmt1",): |
| 732 | # We will assume 'LOAD_ASSERT' will be handled by an assert grammar rule |
| 733 | return tokens[first] == "LOAD_ASSERT" and (last >= len(tokens)) |
| 734 | elif rule == ("or", ("expr", "jmp_true", "expr", "\\e_come_from_opt")): |
| 735 | expr2 = ast[2] |
| 736 | return expr2 == "expr" and expr2[0] == "LOAD_ASSERT" |
| 737 | elif lhs in ("delete_subscript", "del_expr"): |
| 738 | op = ast[0][0] |