@@ -8,6 +8,11 @@ public protocol Show: ~Copyable {
8
8
borrowing func show( ) -> String
9
9
}
10
10
11
+ extension CustomStringConvertible {
12
+ public func show( ) -> String { return description }
13
+ }
14
+ extension Int : Show { }
15
+
11
16
public func print( _ s: borrowing some Show & ~ Copyable) {
12
17
print ( s. show ( ) )
13
18
}
@@ -50,37 +55,47 @@ public protocol Generator: ~Copyable {
50
55
func next( ) -> Maybe < Element >
51
56
}
52
57
58
+ /// Eager assertion function, to avoid autoclosures.
59
+ public func check( _ result: Bool , _ string: String ? = nil ,
60
+ _ file: String = #file, _ line: Int = #line) {
61
+ if result { return }
62
+ var msg = " assertion failure ( \( file) : \( line) ) "
63
+ if let extra = string {
64
+ msg += " : \t " + extra
65
+ }
66
+ fatalError ( msg)
67
+ }
68
+
53
69
// MARK: Tuples
54
70
public enum Pair < L: ~ Copyable, R: ~ Copyable> : ~ Copyable {
55
- case elms ( L , R )
71
+ case pair ( L , R )
56
72
}
73
+ extension Pair : Copyable where L: Copyable , R: Copyable { }
57
74
58
75
/// MARK: Data.Maybe
59
-
60
- public enum Maybe < Value: ~ Copyable> : ~ Copyable {
61
- case just( Value )
76
+ public enum Maybe < Wrapped: ~ Copyable> : ~ Copyable {
77
+ case just( Wrapped )
62
78
case nothing
63
79
}
64
-
65
80
extension Maybe : Copyable { }
66
81
67
- extension Maybe : Show where Value : Show & ~ Copyable {
82
+ extension Maybe : Show where Wrapped : Show & ~ Copyable {
68
83
public borrowing func show( ) -> String {
69
84
switch self {
70
- case let . just( borrowing elm) :
85
+ case let . just( elm) :
71
86
return elm. show ( )
72
87
case . nothing:
73
88
return " <nothing> "
74
89
}
75
90
}
76
91
}
77
92
78
- extension Maybe : Eq where Value : Eq , Value : ~ Copyable {
93
+ extension Maybe : Eq where Wrapped : Eq , Wrapped : ~ Copyable {
79
94
public static func == ( _ a: borrowing Self , _ b: borrowing Self ) -> Bool {
80
95
switch a {
81
- case let . just( borrowing a1 ) :
96
+ case let . just( a1) :
82
97
switch b {
83
- case let . just( borrowing b1 ) :
98
+ case let . just( b1) :
84
99
return a1 == b1
85
100
case . nothing:
86
101
return false
@@ -96,19 +111,6 @@ extension Maybe: Eq where Value: Eq, Value: ~Copyable {
96
111
}
97
112
}
98
113
99
-
100
- // FIXME: triggers crash!
101
- // @inlinable
102
- // public func fromMaybe<A: ~Copyable>(_ defaultVal: consuming A,
103
- // _ mayb: consuming Maybe<A>) -> A {
104
- // switch mayb {
105
- // case let .just(payload):
106
- // return payload
107
- // case .nothing:
108
- // return defaultVal
109
- // }
110
- // }
111
-
112
114
public func isJust< A: ~ Copyable> ( _ m: borrowing Maybe < A > ) -> Bool {
113
115
switch m {
114
116
case . just:
@@ -127,3 +129,168 @@ public struct UnownedRef<Instance: AnyObject> {
127
129
@usableFromInline
128
130
internal unowned(unsafe) var _value : Instance
129
131
}
132
+
133
+ /// Provides underlying support so that you can create recursive enums, because
134
+ /// noncopyable enums do not yet support indirect cases.
135
+ public struct Box < Wrapped: ~ Copyable> : ~ Copyable {
136
+ private let _pointer : UnsafeMutablePointer < Wrapped >
137
+
138
+ init ( _ wrapped: consuming Wrapped ) {
139
+ _pointer = . allocate( capacity: 1 )
140
+ _pointer. initialize ( to: wrapped)
141
+ }
142
+
143
+ deinit {
144
+ _pointer. deinitialize ( count: 1 )
145
+ _pointer. deallocate ( )
146
+ }
147
+
148
+ consuming func take( ) -> Wrapped {
149
+ let wrapped = _pointer. move ( )
150
+ _pointer. deallocate ( )
151
+ discard self
152
+ return wrapped
153
+ }
154
+
155
+ var borrow : Wrapped {
156
+ _read { yield _pointer. pointee }
157
+ }
158
+
159
+ consuming func map( _ transform: ( consuming Wrapped ) -> Wrapped ) -> Self {
160
+ _pointer. initialize ( to: transform ( _pointer. move ( ) ) )
161
+ return self
162
+ }
163
+ }
164
+
165
+
166
+ /// MARK: Data.List
167
+ ///
168
+ /// A singly-linked list
169
+ public enum List < Element: ~ Copyable> : ~ Copyable {
170
+ case cons( Element , Box < List < Element > > )
171
+ case empty
172
+
173
+ public init ( _ head: consuming Element ,
174
+ _ tail: consuming List < Element > ) {
175
+ self = . cons( head, Box ( tail) )
176
+ }
177
+
178
+ public init ( ) { self = . empty }
179
+ }
180
+
181
+ /// Pure Iteration
182
+ extension List where Element: ~ Copyable {
183
+ /// Performs forward iteration through the list, accumulating a result value.
184
+ /// Returns f(xn,...,f(x2, f(x1, init))...), or `init` if the list is empty.
185
+ public borrowing func foldl< Out> (
186
+ init initial: consuming Out ,
187
+ _ f: ( borrowing Element , consuming Out ) -> Out ) -> Out
188
+ where Out: ~ Copyable {
189
+ func loop( _ acc: consuming Out , _ lst: borrowing Self ) -> Out {
190
+ switch lst {
191
+ case . empty:
192
+ return acc
193
+ case let . cons( elm, tail) :
194
+ return loop ( f ( elm, acc) , tail. borrow)
195
+ }
196
+ }
197
+ return loop ( initial, self )
198
+ }
199
+
200
+ /// Performs reverse iteration through the list, accumulating a result value.
201
+ /// Returns f(x1, f(x2,...,f(xn, init)...)) or `init` if the list is empty.
202
+ public borrowing func foldr< Out> (
203
+ init initial: consuming Out ,
204
+ _ f: ( borrowing Element , consuming Out ) -> Out ) -> Out
205
+ where Out: ~ Copyable {
206
+ switch self {
207
+ case . empty:
208
+ return initial
209
+ case let . cons( elm, tail) :
210
+ return f ( elm, tail. borrow. foldr ( init: initial, f) )
211
+ }
212
+ }
213
+
214
+ // Forward iteration without accumulating a result.
215
+ public borrowing func forEach( _ f: ( borrowing Element ) -> Void ) -> Void {
216
+ switch self {
217
+ case . empty: return
218
+ case let . cons( elm, tail) :
219
+ f ( elm)
220
+ return tail. borrow. forEach ( f)
221
+ }
222
+ }
223
+ }
224
+
225
+ /// Initialization
226
+ extension List where Element: ~ Copyable {
227
+ // Generates a list of elements [f(0), f(1), ..., f(n-1)] from left to right.
228
+ // For n < 0, the empty list is created.
229
+ public init ( length n: Int , _ f: ( Int ) -> Element ) {
230
+ guard n > 0 else {
231
+ self = . empty
232
+ return
233
+ }
234
+
235
+ let cur = n- 1
236
+ let elm = f ( cur)
237
+ self = List ( elm, List ( length: cur, f) )
238
+ }
239
+ }
240
+
241
+ /// Basic utilities
242
+ extension List where Element: ~ Copyable {
243
+ /// Is this list empty?
244
+ ///
245
+ /// Complexity: O(1)
246
+ public var isEmpty : Bool {
247
+ borrowing get {
248
+ switch self {
249
+ case . empty: true
250
+ case . cons( _, _) : false
251
+ }
252
+ }
253
+ }
254
+
255
+ /// How many elements are in this list?
256
+ ///
257
+ /// Complexity: O(n)
258
+ public borrowing func length( ) -> Int {
259
+ return foldl ( init: 0 ) { $1 + 1 }
260
+ }
261
+
262
+ /// Pop the first element off the list, if present.
263
+ ///
264
+ /// Complexity: O(1)
265
+ public consuming func pop( ) -> Optional < Pair < Element , List < Element > > > {
266
+ switch consume self {
267
+ case . empty: . none
268
+ case let . cons( elm, tail) : . pair( elm, tail. take ( ) )
269
+ }
270
+ }
271
+
272
+ /// Push an element onto the front of the list.
273
+ ///
274
+ /// Complexity: O(1)
275
+ public consuming func push( _ newHead: consuming Element ) -> List < Element > {
276
+ return List ( newHead, self )
277
+ }
278
+
279
+ /// Produces a new list that is the reverse of this list.
280
+ ///
281
+ /// Complexity: O(n)
282
+ public consuming func reverse( ) -> List < Element > {
283
+ var new = List < Element > ( )
284
+ while case let . pair( head, tail) = pop ( ) {
285
+ new = new. push ( head)
286
+ self = tail
287
+ }
288
+ return new
289
+ }
290
+ }
291
+
292
+ extension List: Show where Element: Show & ~ Copyable {
293
+ public borrowing func show( ) - > String {
294
+ return " [ " + foldl( init: " ] " , { $0. show ( ) + " , " + $1 } )
295
+ }
296
+ }
0 commit comments