@@ -20,14 +20,19 @@ public protocol ListNode : AnyObject {
20
20
associatedtype Element
21
21
var next : Element ? { get }
22
22
var previous : Element ? { get }
23
+
24
+ /// The first node in the list. Used to implement `reversed()`.
25
+ var _firstInList : Element { get }
26
+
27
+ /// The last node in the list. Used to implement `reversed()`.
28
+ var _lastInList : Element { get }
23
29
}
24
30
25
31
public struct List < NodeType: ListNode > :
26
- Sequence , IteratorProtocol , CustomReflectable
27
- where NodeType. Element == NodeType {
32
+ CollectionLikeSequence , IteratorProtocol where NodeType. Element == NodeType {
28
33
private var currentNode : NodeType ?
29
34
30
- public init ( startAt : NodeType ? ) { currentNode = startAt }
35
+ public init ( first : NodeType ? ) { currentNode = first }
31
36
32
37
public mutating func next( ) -> NodeType ? {
33
38
if let node = currentNode {
@@ -39,18 +44,19 @@ public struct List<NodeType: ListNode> :
39
44
40
45
public var first : NodeType ? { currentNode }
41
46
42
- public var customMirror : Mirror {
43
- let c : [ Mirror . Child ] = map { ( label: nil , value: $0) }
44
- return Mirror ( self , children: c)
47
+ public func reversed( ) -> ReverseList < NodeType > {
48
+ if let node = first {
49
+ return ReverseList ( first: node. _lastInList)
50
+ }
51
+ return ReverseList ( first: nil )
45
52
}
46
53
}
47
54
48
55
public struct ReverseList < NodeType: ListNode > :
49
- Sequence , IteratorProtocol , CustomReflectable
50
- where NodeType. Element == NodeType {
56
+ CollectionLikeSequence , IteratorProtocol where NodeType. Element == NodeType {
51
57
private var currentNode : NodeType ?
52
58
53
- public init ( startAt : NodeType ? ) { currentNode = startAt }
59
+ public init ( first : NodeType ? ) { currentNode = first }
54
60
55
61
public mutating func next( ) -> NodeType ? {
56
62
if let node = currentNode {
@@ -62,23 +68,101 @@ public struct ReverseList<NodeType: ListNode> :
62
68
63
69
public var first : NodeType ? { currentNode }
64
70
65
- public var customMirror : Mirror {
66
- let c : [ Mirror . Child ] = map { ( label: nil , value: $0) }
67
- return Mirror ( self , children: c)
71
+ public func reversed( ) -> ReverseList < NodeType > {
72
+ if let node = first {
73
+ return ReverseList ( first: node. _firstInList)
74
+ }
75
+ return ReverseList ( first: nil )
68
76
}
69
77
}
70
78
71
79
72
80
//===----------------------------------------------------------------------===//
73
- // General Utilities
81
+ // Sequence Utilities
74
82
//===----------------------------------------------------------------------===//
75
83
76
- extension Sequence {
77
- public var isEmpty : Bool {
78
- !contains( where: { _ in true } )
84
+ /// Types conforming to `HasName` will be displayed by their name (instead of the
85
+ /// full object) in collection descriptions.
86
+ ///
87
+ /// This is useful to make collections, e.g. of BasicBlocks or Functions, readable.
88
+ public protocol HasName {
89
+ var name : String { get }
90
+ }
91
+
92
+ private struct CustomMirrorChild : CustomStringConvertible , CustomReflectable {
93
+ public var description : String
94
+ public var customMirror : Mirror { Mirror ( self , children: [ ] ) }
95
+
96
+ public init ( description: String ) { self . description = description }
97
+ }
98
+
99
+ /// Makes a Sequence's `description` and `customMirror` formatted like Array, e.g. [a, b, c].
100
+ public protocol FormattedLikeArray : Sequence , CustomStringConvertible , CustomReflectable {
101
+ }
102
+
103
+ extension FormattedLikeArray {
104
+ /// Display a Sequence in an array like format, e.g. [a, b, c]
105
+ public var description : String {
106
+ " [ " + map {
107
+ if let named = $0 as? HasName {
108
+ return named. name
109
+ }
110
+ return String ( describing: $0)
111
+ } . joined ( separator: " , " ) + " ] "
112
+ }
113
+
114
+ /// The mirror which adds the children of a Sequence, similar to `Array`.
115
+ public var customMirror : Mirror {
116
+ // If the one-line description is not too large, print that instead of the
117
+ // children in separate lines.
118
+ if description. count <= 80 {
119
+ return Mirror ( self , children: [ ] )
120
+ }
121
+ let c : [ Mirror . Child ] = map {
122
+ let val : Any
123
+ if let named = $0 as? HasName {
124
+ val = CustomMirrorChild ( description: named. name)
125
+ } else {
126
+ val = $0
127
+ }
128
+ return ( label: nil , value: val)
129
+ }
130
+ return Mirror ( self , children: c, displayStyle: . collection)
79
131
}
80
132
}
81
133
134
+ /// A Sequence which is not consuming and therefore behaves like a Collection.
135
+ ///
136
+ /// Many sequences in SIL and the optimizer should be collections but cannot
137
+ /// because their Index cannot conform to Comparable. Those sequences conform
138
+ /// to CollectionLikeSequence.
139
+ ///
140
+ /// For convenience it also inherits from FormattedLikeArray.
141
+ public protocol CollectionLikeSequence : FormattedLikeArray {
142
+ }
143
+
144
+ public extension CollectionLikeSequence {
145
+ var isEmpty : Bool { !contains( where: { _ in true } ) }
146
+ }
147
+
148
+ // Also make the lazy sequences a CollectionLikeSequence if the underlying sequence is one.
149
+
150
+ extension LazySequence : CollectionLikeSequence ,
151
+ FormattedLikeArray , CustomStringConvertible , CustomReflectable
152
+ where Base: CollectionLikeSequence { }
153
+
154
+ extension FlattenSequence : CollectionLikeSequence ,
155
+ FormattedLikeArray , CustomStringConvertible , CustomReflectable
156
+ where Base: CollectionLikeSequence { }
157
+
158
+ extension LazyMapSequence : CollectionLikeSequence ,
159
+ FormattedLikeArray , CustomStringConvertible , CustomReflectable
160
+ where Base: CollectionLikeSequence { }
161
+
162
+ extension LazyFilterSequence : CollectionLikeSequence ,
163
+ FormattedLikeArray , CustomStringConvertible , CustomReflectable
164
+ where Base: CollectionLikeSequence { }
165
+
82
166
//===----------------------------------------------------------------------===//
83
167
// Bridging Utilities
84
168
//===----------------------------------------------------------------------===//
0 commit comments