Appearance
| 1 | namespace Syntax.Process is | |
| 2 | // Collects the names of variables written within a walked | |
| 3 | // subtree — by assignment (`=`, including destructuring) or by | |
| 4 | // being passed `ref`. Used to compute the loop kill-set: a | |
| 5 | // narrow on a variable the loop body writes cannot be assumed | |
| 6 | // across the back-edge and is dropped; a narrow on a variable | |
| 7 | // the body never writes survives the loop. | |
| 8 | // | |
| 9 | // A `Visitor` whose default per-node visits are no-ops, so only | |
| 10 | // ASSIGNMENT and REFERENCE need overriding; default `pre` | |
| 11 | // returns false, so the framework descends through everything. | |
| 12 | class LOOP_ASSIGNMENT_COLLECTOR: Visitor is | |
| 13 | names: Collections.SET[string] public; | |
| 14 | ||
| 15 | init() is | |
| 16 | super.init(); | |
| 17 | names = Collections.SET[string](); | |
| 18 | si | |
| 19 | ||
| 20 | visit(assignment: Trees.Statements.ASSIGNMENT) is | |
| 21 | let targets = Collections.LIST[Trees.Expressions.Expression](); | |
| 22 | assignment.left.get_names_into(targets); | |
| 23 | ||
| 24 | for target in targets do | |
| 25 | _collect(target); | |
| 26 | od | |
| 27 | si | |
| 28 | ||
| 29 | visit(reference: Trees.Expressions.REFERENCE) is | |
| 30 | // `x ref` — a `ref` argument may be written by the callee. | |
| 31 | _collect(reference.left); | |
| 32 | si | |
| 33 | ||
| 34 | _collect(expr: Trees.Expressions.Expression) is | |
| 35 | if !isa Trees.Expressions.IDENTIFIER(expr) then | |
| 36 | return; | |
| 37 | fi | |
| 38 | ||
| 39 | let identifier = expr; | |
| 40 | ||
| 41 | names.add(identifier.identifier.name); | |
| 42 | si | |
| 43 | si | |
| 44 | si |