(instr: parser.CodeDef, escapes: dict[SimpleStmt, EscapingCall])
| 721 | |
| 722 | |
| 723 | def check_escaping_calls(instr: parser.CodeDef, escapes: dict[SimpleStmt, EscapingCall]) -> None: |
| 724 | error: lexer.Token | None = None |
| 725 | calls = {e.call for e in escapes.values()} |
| 726 | |
| 727 | def visit(stmt: Stmt) -> None: |
| 728 | nonlocal error |
| 729 | if isinstance(stmt, IfStmt) or isinstance(stmt, WhileStmt): |
| 730 | for tkn in stmt.condition: |
| 731 | if tkn in calls: |
| 732 | error = tkn |
| 733 | elif isinstance(stmt, SimpleStmt): |
| 734 | in_if = 0 |
| 735 | tkn_iter = iter(stmt.contents) |
| 736 | for tkn in tkn_iter: |
| 737 | if tkn.kind == "IDENTIFIER" and tkn.text in ("DEOPT_IF", "ERROR_IF", "EXIT_IF", "HANDLE_PENDING_AND_DEOPT_IF", "AT_END_EXIT_IF"): |
| 738 | in_if = 1 |
| 739 | next(tkn_iter) |
| 740 | elif tkn.kind == "LPAREN": |
| 741 | if in_if: |
| 742 | in_if += 1 |
| 743 | elif tkn.kind == "RPAREN": |
| 744 | if in_if: |
| 745 | in_if -= 1 |
| 746 | elif tkn in calls and in_if: |
| 747 | error = tkn |
| 748 | |
| 749 | |
| 750 | instr.block.accept(visit) |
| 751 | if error is not None: |
| 752 | raise analysis_error(f"Escaping call '{error.text} in condition", error) |
| 753 | |
| 754 | def escaping_call_in_simple_stmt(stmt: SimpleStmt, result: dict[SimpleStmt, EscapingCall]) -> None: |
| 755 | tokens = stmt.contents |
no test coverage detected
searching dependent graphs…