@@ -15,34 +15,47 @@ import Foundation
15
15
/// A Syntax node represents a tree of nodes with tokens at the leaves.
16
16
/// Each node has accessors for its known children, and allows efficient
17
17
/// iteration over the children through its `children` property.
18
- public class Syntax : CustomStringConvertible {
18
+ public protocol Syntax :
19
+ CustomStringConvertible , TextOutputStreamable { }
20
+
21
+ internal protocol _SyntaxBase : Syntax {
19
22
/// The type of sequence containing the indices of present children.
20
- internal typealias PresentChildIndicesSequence =
23
+ typealias PresentChildIndicesSequence =
21
24
LazyFilterSequence < CountableRange < Int > >
22
-
25
+
23
26
/// The root of the tree this node is currently in.
24
- internal let _root : SyntaxData
27
+ var _root : SyntaxData { get } // Must be of type SyntaxData
25
28
26
29
/// The data backing this node.
27
30
/// - note: This is unowned, because the reference to the root data keeps it
28
31
/// alive. This means there is an implicit relationship -- the data
29
32
/// property must be a descendent of the root. This relationship must
30
33
/// be preserved in all circumstances where Syntax nodes are created.
31
- internal unowned var data : SyntaxData
34
+ var _data : SyntaxData { get }
32
35
33
36
#if DEBUG
34
- func validate( ) {
35
- // This is for subclasses to override to perform structural validation.
36
- }
37
+ func validate( )
37
38
#endif
39
+ }
40
+ extension _SyntaxBase {
41
+ public func validate( ) {
42
+ // This is for implementers to override to perform structural validation.
43
+ }
44
+ }
38
45
39
- /// Creates a Syntax node from the provided root and data.
40
- internal init ( root: SyntaxData , data: SyntaxData ) {
41
- self . _root = root
42
- self . data = data
43
- #if DEBUG
44
- validate ( )
45
- #endif
46
+ extension Syntax {
47
+ var data : SyntaxData {
48
+ guard let base = self as? _SyntaxBase else {
49
+ fatalError ( " only first-class syntax nodes can conform to Syntax " )
50
+ }
51
+ return base. _data
52
+ }
53
+
54
+ var _root : SyntaxData {
55
+ guard let base = self as? _SyntaxBase else {
56
+ fatalError ( " only first-class syntax nodes can conform to Syntax " )
57
+ }
58
+ return base. _root
46
59
}
47
60
48
61
/// Access the raw syntax assuming the node is a Syntax.
@@ -93,7 +106,7 @@ public class Syntax: CustomStringConvertible {
93
106
/// The parent of this syntax node, or `nil` if this node is the root.
94
107
public var parent : Syntax ? {
95
108
guard let parentData = data. parent else { return nil }
96
- return Syntax . make ( root: _root, data: parentData)
109
+ return makeSyntax ( root: _root, data: parentData)
97
110
}
98
111
99
112
/// The index of this node in the parent's children.
@@ -103,14 +116,14 @@ public class Syntax: CustomStringConvertible {
103
116
104
117
/// The root of the tree in which this node resides.
105
118
public var root : Syntax {
106
- return Syntax . make ( root: _root, data: _root)
119
+ return makeSyntax ( root: _root, data: _root)
107
120
}
108
121
109
122
/// The sequence of indices that correspond to child nodes that are not
110
123
/// missing.
111
124
///
112
125
/// This property is an implementation detail of `SyntaxChildren`.
113
- internal var presentChildIndices : PresentChildIndicesSequence {
126
+ internal var presentChildIndices : _SyntaxBase . PresentChildIndicesSequence {
114
127
return raw. layout. indices. lazy. filter { self . raw. layout [ $0] . isPresent }
115
128
}
116
129
@@ -121,7 +134,7 @@ public class Syntax: CustomStringConvertible {
121
134
public func child( at index: Int ) -> Syntax ? {
122
135
guard raw. layout. indices. contains ( index) else { return nil }
123
136
if raw. layout [ index] . isMissing { return nil }
124
- return Syntax . make ( root: _root, data: data. cachedChild ( at: index) )
137
+ return makeSyntax ( root: _root, data: data. cachedChild ( at: index) )
125
138
}
126
139
127
140
/// A source-accurate description of this node.
@@ -130,9 +143,7 @@ public class Syntax: CustomStringConvertible {
130
143
self . write ( to: & s)
131
144
return s
132
145
}
133
- }
134
-
135
- extension Syntax : TextOutputStreamable {
146
+
136
147
/// Prints the raw value of this node to the provided stream.
137
148
/// - Parameter stream: The stream to which to print the raw tree.
138
149
public func write< Target> ( to target: inout Target )
@@ -141,21 +152,27 @@ extension Syntax: TextOutputStreamable {
141
152
}
142
153
}
143
154
144
- extension Syntax : Hashable {
145
- /// Determines if two nodes are equal to each other.
146
- public static func == ( lhs: Syntax , rhs: Syntax ) -> Bool {
147
- return lhs. hashValue == rhs. hashValue
148
- }
149
- /// Use reference value as the hashValue for this Syntax
150
- public var hashValue : Int {
151
- return ObjectIdentifier ( data) . hashValue
152
- }
155
+ /// Determines if two nodes are equal to each other.
156
+ public func == ( lhs: Syntax , rhs: Syntax ) -> Bool {
157
+ return lhs. data === rhs. data
153
158
}
154
159
155
160
/// MARK: - Nodes
156
161
157
162
/// A Syntax node representing a single token.
158
- public class TokenSyntax : Syntax {
163
+ public struct TokenSyntax : _SyntaxBase , Hashable {
164
+ var _root : SyntaxData
165
+ unowned var _data : SyntaxData
166
+
167
+ /// Creates a Syntax node from the provided root and data.
168
+ internal init ( root: SyntaxData , data: SyntaxData ) {
169
+ self . _root = root
170
+ self . _data = data
171
+ #if DEBUG
172
+ validate ( )
173
+ #endif
174
+ }
175
+
159
176
/// The text of the token as written in the source code.
160
177
public var text : String {
161
178
return tokenKind. text
@@ -230,4 +247,12 @@ public class TokenSyntax: Syntax {
230
247
}
231
248
return kind
232
249
}
250
+
251
+ public static func == ( lhs: TokenSyntax , rhs: TokenSyntax ) -> Bool {
252
+ return lhs. _data === rhs. _data
253
+ }
254
+
255
+ public var hashValue : Int {
256
+ return ObjectIdentifier ( _data) . hashValue
257
+ }
233
258
}
0 commit comments