Appearance
| 1 | namespace Syntax.Process is | |
| 2 | use Collections; | |
| 3 | ||
| 4 | use LOCATION = Source.LOCATION; | |
| 5 | use Type = Semantic.Types.Type; | |
| 6 | use Value = IR.Values.Value; | |
| 7 | use VariableLeft = Trees.Variables.VariableLeft; | |
| 8 | ||
| 9 | // Compile-expressions output for one variable binding target (a | |
| 10 | // VariableLeft node). Owned by the compile-expressions pass and read | |
| 11 | // by IL generation; kept here, keyed by node, rather than in fields | |
| 12 | // on the node itself (see NodeStateStore). | |
| 13 | class VARIABLE_LEFT_STATE is | |
| 14 | // code to store into the bound variable, from the initializer | |
| 15 | value: Value? public; | |
| 16 | explicit_type: Type? public; | |
| 17 | // the compiled initializer, if any | |
| 18 | right_value: Value? public; | |
| 19 | right_location: LOCATION? public; | |
| 20 | variable_location: LOCATION? public; | |
| 21 | ||
| 22 | init() is | |
| 23 | si | |
| 24 | si | |
| 25 | ||
| 26 | // Entries are keyed by (file name, node id), not node object | |
| 27 | // identity — see Node.node_id. Ids are never reused, so an entry | |
| 28 | // orphaned by tree replacement can go stale but can never be | |
| 29 | // served for a different node. | |
| 30 | class VARIABLE_LEFT_STATE_STORE: NodeStateStore is | |
| 31 | _state_by_file: MutableMap[string, MutableMap[int, VARIABLE_LEFT_STATE]]; | |
| 32 | ||
| 33 | name: string => "variable-left"; | |
| 34 | ||
| 35 | entry_count: int => _count_entries(); | |
| 36 | ||
| 37 | init(registry: STATE_STORE_REGISTRY) is | |
| 38 | _state_by_file = MAP[string, MutableMap[int, VARIABLE_LEFT_STATE]](); | |
| 39 | ||
| 40 | registry.register(self); | |
| 41 | si | |
| 42 | ||
| 43 | // The state recorded for `left`, or null when none has been. | |
| 44 | get(left: VariableLeft) -> VARIABLE_LEFT_STATE? is | |
| 45 | let by_node: MutableMap[int, VARIABLE_LEFT_STATE] mut; | |
| 46 | ||
| 47 | if !_state_by_file.try_get_value(left.location.file_name, by_node ref) then | |
| 48 | return null; | |
| 49 | fi | |
| 50 | ||
| 51 | let result: VARIABLE_LEFT_STATE mut; | |
| 52 | ||
| 53 | if by_node.try_get_value(left.node_id, result ref) then | |
| 54 | return result; | |
| 55 | fi | |
| 56 | ||
| 57 | return null; | |
| 58 | si | |
| 59 | ||
| 60 | get_or_add(left: VariableLeft) -> VARIABLE_LEFT_STATE is | |
| 61 | let file_name = left.location.file_name; | |
| 62 | ||
| 63 | let by_node: MutableMap[int, VARIABLE_LEFT_STATE] mut; | |
| 64 | ||
| 65 | if !_state_by_file.try_get_value(file_name, by_node ref) then | |
| 66 | by_node = MAP[int, VARIABLE_LEFT_STATE](); | |
| 67 | _state_by_file[file_name] = by_node; | |
| 68 | fi | |
| 69 | ||
| 70 | let result: VARIABLE_LEFT_STATE mut; | |
| 71 | ||
| 72 | if !by_node.try_get_value(left.node_id, result ref) then | |
| 73 | result = VARIABLE_LEFT_STATE(); | |
| 74 | by_node[left.node_id] = result; | |
| 75 | fi | |
| 76 | ||
| 77 | return result; | |
| 78 | si | |
| 79 | ||
| 80 | remove(left: VariableLeft) is | |
| 81 | let by_node: MutableMap[int, VARIABLE_LEFT_STATE] mut; | |
| 82 | ||
| 83 | if _state_by_file.try_get_value(left.location.file_name, by_node ref) then | |
| 84 | by_node.remove(left.node_id); | |
| 85 | fi | |
| 86 | si | |
| 87 | ||
| 88 | drop_file(file_name: string) is | |
| 89 | _state_by_file.remove(file_name); | |
| 90 | si | |
| 91 | ||
| 92 | clear_all() is | |
| 93 | _state_by_file = MAP[string, MutableMap[int, VARIABLE_LEFT_STATE]](); | |
| 94 | si | |
| 95 | ||
| 96 | _count_entries() -> int is | |
| 97 | let result mut = 0; | |
| 98 | ||
| 99 | for by_node in _state_by_file.values do | |
| 100 | result = result + by_node.count; | |
| 101 | od | |
| 102 | ||
| 103 | return result; | |
| 104 | si | |
| 105 | si | |
| 106 | si |