Appearance
| 1 | namespace Syntax.Trees.Identifiers is | |
| 2 | use IO.Std | |
| 3 | ||
| 4 | use Source | |
| 5 | ||
| 6 | // Constructed, so UPPER_SNAKE_CASE by convention, but the | |
| 7 | // UPPER_SNAKE_CASE name IDENTIFIER is already taken by | |
| 8 | // Trees.Expressions.IDENTIFIER, which many files reference | |
| 9 | // unqualified alongside this namespace. | |
| 10 | @suppress("non-upper-snake-case-name") | |
| 11 | class Identifier(location: LOCATION, name: string mut): Trees.Node, Collections.Iterable[string] is | |
| 12 | name: string public | |
| 13 | ||
| 14 | qualifier: Identifier? => null | |
| 15 | ||
| 16 | qualifier_names: Collections.LIST[string] => Collections.LIST[string](0) | |
| 17 | ||
| 18 | names: Collections.LIST[string] => Collections.LIST[string]([name]) // : string; | |
| 19 | ||
| 20 | is_qualified: bool => false | |
| 21 | ||
| 22 | right_location: LOCATION => location | |
| 23 | ||
| 24 | iterator: Collections.Iterator[string] => names.iterator | |
| 25 | ||
| 26 | super(location) | |
| 27 | ||
| 28 | init(..) is | |
| 29 | // A completion target - the user has typed a `.` and no name | |
| 30 | // yet - is built with no name. Poison it so it never resolves | |
| 31 | // and no diagnostic reports a member with an empty name. | |
| 32 | if name.length == 0 then | |
| 33 | poison() | |
| 34 | self.name = "$poisoned" | |
| 35 | fi | |
| 36 | si | |
| 37 | ||
| 38 | copy() -> Identifier => | |
| 39 | Identifier(location, name) | |
| 40 | ||
| 41 | copy_as_expression() -> Expressions.Expression is | |
| 42 | if let self.qualifier? then | |
| 43 | return Expressions.MEMBER(location, qualifier.copy_as_expression(), Identifier(right_location, name), right_location) | |
| 44 | else | |
| 45 | return Expressions.IDENTIFIER(location, self.copy()) | |
| 46 | fi | |
| 47 | si | |
| 48 | ||
| 49 | accept(visitor: Visitor) is | |
| 50 | visitor.visit(self) | |
| 51 | si | |
| 52 | si | |
| 53 | ||
| 54 | class QUALIFIED( | |
| 55 | location: LOCATION, | |
| 56 | _qualifier: Identifier, | |
| 57 | name: string, | |
| 58 | completion_target: LOCATION, | |
| 59 | // Assignable for the same reason `location` is: an incremental edit | |
| 60 | // moves the name, and a use of the symbol it resolves to is recorded | |
| 61 | // here rather than at the node's own span. Left read-only it keeps | |
| 62 | // its original parse position, and the reconciliation that translates | |
| 63 | // those uses is keyed on a position the text no longer has. | |
| 64 | right_location: LOCATION public | |
| 65 | ): Identifier is | |
| 66 | is_qualified: bool => true | |
| 67 | ||
| 68 | qualifier: Identifier => _qualifier | |
| 69 | ||
| 70 | qualifier_names: Collections.LIST[string] is | |
| 71 | let result = Collections.LIST[string]() | |
| 72 | let p: Identifier? mut = qualifier | |
| 73 | ||
| 74 | while p? do | |
| 75 | result.add(p.name) | |
| 76 | p = p.qualifier | |
| 77 | od | |
| 78 | ||
| 79 | return result | |
| 80 | si | |
| 81 | ||
| 82 | names: Collections.LIST[string] is | |
| 83 | let result = Collections.LIST[string]() | |
| 84 | ||
| 85 | result.add(name) | |
| 86 | ||
| 87 | let p: Identifier? mut = qualifier | |
| 88 | ||
| 89 | while p? do | |
| 90 | result.add(p.name) | |
| 91 | p = p.qualifier | |
| 92 | od | |
| 93 | ||
| 94 | return result | |
| 95 | si | |
| 96 | ||
| 97 | iterator: Collections.Iterator[string] is | |
| 98 | let result = Collections.LIST[string]() | |
| 99 | ||
| 100 | result.add(name) | |
| 101 | ||
| 102 | let p: Identifier? mut = qualifier | |
| 103 | ||
| 104 | while p? do | |
| 105 | result.add(p.name) | |
| 106 | p = p.qualifier | |
| 107 | od | |
| 108 | ||
| 109 | return result.iterator | |
| 110 | si | |
| 111 | ||
| 112 | super(location, name) | |
| 113 | ||
| 114 | init(..) is | |
| 115 | poison(qualifier.is_poisoned) | |
| 116 | si | |
| 117 | ||
| 118 | copy() -> Identifier is | |
| 119 | let np = qualifier.copy() | |
| 120 | ||
| 121 | return QUALIFIED( | |
| 122 | location, | |
| 123 | np, | |
| 124 | name, | |
| 125 | completion_target, | |
| 126 | right_location | |
| 127 | ) | |
| 128 | si | |
| 129 | ||
| 130 | accept(visitor: Visitor) is | |
| 131 | visitor.visit(self) | |
| 132 | si | |
| 133 | ||
| 134 | walk(visitor: Visitor) is | |
| 135 | if !visitor.pre(self) then | |
| 136 | qualifier.walk(visitor) | |
| 137 | fi | |
| 138 | ||
| 139 | accept(visitor) | |
| 140 | si | |
| 141 | si | |
| 142 | si |