Appearance
| 1 | namespace Syntax.Process is | |
| 2 | use Trees; | |
| 3 | ||
| 4 | // Tracks the `INTRINSIC_ATTRIBUTE` pragma scopes a tree walk is | |
| 5 | // currently nested inside: `enter` on the way in, `leave` on the way | |
| 6 | // out. Several passes need to know whether the node being walked sits | |
| 7 | // inside such a scope, so each visitor delegates here rather than | |
| 8 | // reimplementing the enter / leave bookkeeping. | |
| 9 | class PRAGMA_SCOPE_STACK is | |
| 10 | _intrinsic_operations: Collections.LIST[string]; | |
| 11 | ||
| 12 | // The operation named by the innermost enclosing | |
| 13 | // `INTRINSIC_ATTRIBUTE`, or null outside one. | |
| 14 | intrinsic_operation: string? => | |
| 15 | if _intrinsic_operations.count > 0 then | |
| 16 | _intrinsic_operations[_intrinsic_operations.count - 1] | |
| 17 | else | |
| 18 | null | |
| 19 | fi; | |
| 20 | ||
| 21 | is_balanced: bool => _intrinsic_operations.count == 0; | |
| 22 | ||
| 23 | init() is | |
| 24 | _intrinsic_operations = Collections.LIST[string](); | |
| 25 | si | |
| 26 | ||
| 27 | enter(pragma: Pragmas.PRAGMA) is | |
| 28 | _adjust(pragma, 1); | |
| 29 | si | |
| 30 | ||
| 31 | leave(pragma: Pragmas.PRAGMA) is | |
| 32 | _adjust(pragma, -1); | |
| 33 | si | |
| 34 | ||
| 35 | _adjust(pragma: Pragmas.PRAGMA, delta: int) is | |
| 36 | let name = pragma.name.to_string(); | |
| 37 | ||
| 38 | if name =~ "INTRINSIC_ATTRIBUTE" then | |
| 39 | if let operation = pragma.try_get_string_literal_at(0) then | |
| 40 | if delta > 0 then | |
| 41 | _intrinsic_operations.add(operation); | |
| 42 | else | |
| 43 | _intrinsic_operations.remove_at(_intrinsic_operations.count - 1); | |
| 44 | fi | |
| 45 | fi | |
| 46 | fi | |
| 47 | si | |
| 48 | si | |
| 49 | si |