Appearance
| 1 | namespace Syntax.Process is | |
| 2 | use IO.Std | |
| 3 | ||
| 4 | ||
| 5 | use Logging | |
| 6 | use Trees | |
| 7 | ||
| 8 | class ScopedVisitor: ScopeVisitorBase abstract is | |
| 9 | _logger: Logger | |
| 10 | _symbol_table: Semantic.SYMBOL_TABLE | |
| 11 | ||
| 12 | init( | |
| 13 | logger: Logger, | |
| 14 | symbol_table: Semantic.SYMBOL_TABLE, | |
| 15 | namespaces: Semantic.NAMESPACES | |
| 16 | ) | |
| 17 | is | |
| 18 | super.init( | |
| 19 | symbol_table, | |
| 20 | namespaces | |
| 21 | ) | |
| 22 | ||
| 23 | _logger = logger | |
| 24 | _symbol_table = symbol_table | |
| 25 | si | |
| 26 | ||
| 27 | find(name: string) -> Semantic.Symbols.Symbol? => _symbol_table.current_scope.find_enclosing(name) | |
| 28 | find_matches(prefix: string, matches: Collections.MutableMap[string,Semantic.Symbols.Symbol]) is | |
| 29 | _symbol_table.current_scope.find_enclosing_matches(prefix, matches) | |
| 30 | si | |
| 31 | ||
| 32 | find(identifier: Identifiers.Identifier) -> Semantic.Symbols.Symbol? is | |
| 33 | let result: Semantic.Symbols.Symbol? mut = null | |
| 34 | ||
| 35 | if identifier.qualifier? then | |
| 36 | let qualifier = find(identifier.qualifier) | |
| 37 | ||
| 38 | if qualifier == null then | |
| 39 | return null | |
| 40 | fi | |
| 41 | ||
| 42 | result = qualifier.find_member(identifier.name) | |
| 43 | else | |
| 44 | result = | |
| 45 | _symbol_table | |
| 46 | .current_scope | |
| 47 | .find_enclosing(identifier.name) | |
| 48 | fi | |
| 49 | ||
| 50 | // A name the compiler synthesised carries an internal | |
| 51 | // location, and a scope broken enough not to hold it - a | |
| 52 | // file mixing globals with a namespace, say - has a real | |
| 53 | // diagnostic of its own. Reporting a name nobody wrote on | |
| 54 | // top of it points at nothing the author can fix. | |
| 55 | if | |
| 56 | result == null /\ | |
| 57 | !identifier.is_poisoned /\ | |
| 58 | !identifier.location.is_internal | |
| 59 | then | |
| 60 | _logger.error(identifier.location, "symbol not found: {identifier}") | |
| 61 | fi | |
| 62 | ||
| 63 | return result | |
| 64 | si | |
| 65 | ||
| 66 | // As find(identifier), but returns null silently instead of | |
| 67 | // logging "symbol not found" — for callers that resolve a name | |
| 68 | // speculatively and report their own diagnostic on failure. | |
| 69 | try_find(identifier: Identifiers.Identifier) -> Semantic.Symbols.Symbol? is | |
| 70 | if identifier.qualifier? then | |
| 71 | let qualifier = try_find(identifier.qualifier) | |
| 72 | ||
| 73 | if qualifier == null then | |
| 74 | return null | |
| 75 | fi | |
| 76 | ||
| 77 | return qualifier.find_member(identifier.name) | |
| 78 | fi | |
| 79 | ||
| 80 | return | |
| 81 | _symbol_table | |
| 82 | .current_scope | |
| 83 | .find_enclosing(identifier.name) | |
| 84 | si | |
| 85 | pre(`namespace: Definitions.NAMESPACE) -> bool is | |
| 86 | enter_namespace(`namespace) | |
| 87 | enter_uses(`namespace) | |
| 88 | return false | |
| 89 | si | |
| 90 | ||
| 91 | visit(`namespace: Definitions.NAMESPACE) is | |
| 92 | leave_uses(`namespace) | |
| 93 | leave_namespace(`namespace) | |
| 94 | si | |
| 95 | ||
| 96 | pre(`class: Definitions.CLASS) -> bool is | |
| 97 | enter_scope(`class) | |
| 98 | return false | |
| 99 | si | |
| 100 | ||
| 101 | visit(`class: Definitions.CLASS) is | |
| 102 | leave_scope(`class) | |
| 103 | si | |
| 104 | ||
| 105 | pre(`trait: Definitions.TRAIT) -> bool is | |
| 106 | enter_scope(`trait) | |
| 107 | return false | |
| 108 | si | |
| 109 | ||
| 110 | visit(`trait: Definitions.TRAIT) is | |
| 111 | leave_scope(`trait) | |
| 112 | si | |
| 113 | ||
| 114 | pre(`struct: Definitions.STRUCT) -> bool is | |
| 115 | enter_scope(`struct) | |
| 116 | return false | |
| 117 | si | |
| 118 | ||
| 119 | pre(`union: Definitions.UNION) -> bool is | |
| 120 | enter_scope(`union) | |
| 121 | return false | |
| 122 | si | |
| 123 | ||
| 124 | visit(`union: Definitions.UNION) is | |
| 125 | leave_scope(`union) | |
| 126 | si | |
| 127 | ||
| 128 | pre(variant: Definitions.VARIANT) -> bool is | |
| 129 | enter_scope(variant) | |
| 130 | return false | |
| 131 | si | |
| 132 | ||
| 133 | visit(variant: Definitions.VARIANT) is | |
| 134 | leave_scope(variant) | |
| 135 | si | |
| 136 | ||
| 137 | visit(`struct: Definitions.STRUCT) is | |
| 138 | leave_scope(`struct) | |
| 139 | si | |
| 140 | ||
| 141 | pre(`partial: Definitions.PARTIAL) -> bool is | |
| 142 | enter_scope(`partial) | |
| 143 | return false | |
| 144 | si | |
| 145 | ||
| 146 | visit(`partial: Definitions.PARTIAL) is | |
| 147 | leave_scope(`partial) | |
| 148 | si | |
| 149 | ||
| 150 | pre(`impl: Definitions.IMPL) -> bool is | |
| 151 | enter_scope(`impl) | |
| 152 | return false | |
| 153 | si | |
| 154 | ||
| 155 | visit(`impl: Definitions.IMPL) is | |
| 156 | leave_scope(`impl) | |
| 157 | si | |
| 158 | ||
| 159 | pre(`enum: Definitions.ENUM) -> bool is | |
| 160 | enter_scope(`enum) | |
| 161 | return false | |
| 162 | si | |
| 163 | ||
| 164 | visit(`enum: Definitions.ENUM) is | |
| 165 | leave_scope(`enum) | |
| 166 | si | |
| 167 | ||
| 168 | pre(function: Definitions.FUNCTION) -> bool is | |
| 169 | enter_scope(function) | |
| 170 | return false | |
| 171 | si | |
| 172 | ||
| 173 | visit(function: Definitions.FUNCTION) is | |
| 174 | leave_scope(function) | |
| 175 | si | |
| 176 | ||
| 177 | pre(property: Definitions.PROPERTY) -> bool => false | |
| 178 | visit(property: Definitions.PROPERTY) is | |
| 179 | si | |
| 180 | ||
| 181 | pre(indexer: Definitions.INDEXER) -> bool is | |
| 182 | // enter_scope(indexer); | |
| 183 | return true | |
| 184 | si | |
| 185 | ||
| 186 | visit(indexer: Definitions.INDEXER) is | |
| 187 | // leave_scope(indexer); | |
| 188 | si | |
| 189 | ||
| 190 | pre(if_branch: Statements.IF_BRANCH) -> bool is | |
| 191 | enter_scope(if_branch) | |
| 192 | return false | |
| 193 | si | |
| 194 | ||
| 195 | visit(if_branch: Statements.IF_BRANCH) is | |
| 196 | leave_scope(if_branch) | |
| 197 | si | |
| 198 | ||
| 199 | pre(`case: Statements.CASE) -> bool is | |
| 200 | enter_scope(`case) | |
| 201 | return false | |
| 202 | si | |
| 203 | ||
| 204 | visit(`case: Statements.CASE) is | |
| 205 | leave_scope(`case) | |
| 206 | si | |
| 207 | ||
| 208 | pre(case_match: Statements.CASE_MATCH) -> bool is | |
| 209 | enter_scope(case_match) | |
| 210 | return false | |
| 211 | si | |
| 212 | ||
| 213 | visit(case_match: Statements.CASE_MATCH) is | |
| 214 | leave_scope(case_match) | |
| 215 | si | |
| 216 | ||
| 217 | pre(`try: Statements.TRY) -> bool is | |
| 218 | enter_scope(`try) | |
| 219 | return false | |
| 220 | si | |
| 221 | ||
| 222 | visit(`try: Statements.TRY) is | |
| 223 | leave_scope(`try) | |
| 224 | si | |
| 225 | ||
| 226 | pre(`catch: Statements.CATCH) -> bool is | |
| 227 | enter_scope(`catch) | |
| 228 | return false | |
| 229 | si | |
| 230 | ||
| 231 | visit(`catch: Statements.CATCH) is | |
| 232 | leave_scope(`catch) | |
| 233 | si | |
| 234 | ||
| 235 | pre(`do: Statements.DO) -> bool is | |
| 236 | enter_scope(`do) | |
| 237 | return false | |
| 238 | si | |
| 239 | ||
| 240 | visit(`do: Statements.DO) is | |
| 241 | leave_scope(`do) | |
| 242 | si | |
| 243 | ||
| 244 | pre(`for: Statements.FOR) -> bool is | |
| 245 | enter_scope(`for) | |
| 246 | return false | |
| 247 | si | |
| 248 | ||
| 249 | visit(`for: Statements.FOR) is | |
| 250 | leave_scope(`for) | |
| 251 | si | |
| 252 | ||
| 253 | pre(function: Expressions.FUNCTION) -> bool is | |
| 254 | enter_scope(function) | |
| 255 | return false | |
| 256 | si | |
| 257 | ||
| 258 | visit(function: Expressions.FUNCTION) is | |
| 259 | leave_scope(function) | |
| 260 | si | |
| 261 | ||
| 262 | pre(let_in: Expressions.LET_IN) -> bool is | |
| 263 | enter_scope(let_in) | |
| 264 | return false | |
| 265 | si | |
| 266 | ||
| 267 | visit(let_in: Expressions.LET_IN) is | |
| 268 | leave_scope(let_in) | |
| 269 | si | |
| 270 | ||
| 271 | pre(expression: Bodies.EXPRESSION) -> bool is | |
| 272 | enter_scope(expression) | |
| 273 | return false | |
| 274 | si | |
| 275 | ||
| 276 | visit(expression: Bodies.EXPRESSION) is | |
| 277 | leave_scope(expression) | |
| 278 | si | |
| 279 | ||
| 280 | pre(block: Bodies.BLOCK) -> bool is | |
| 281 | enter_scope(block) | |
| 282 | return false | |
| 283 | si | |
| 284 | ||
| 285 | visit(block: Bodies.BLOCK) is | |
| 286 | leave_scope(block) | |
| 287 | si | |
| 288 | si | |
| 289 | si |