@@ -8,6 +8,11 @@ public protocol Show: ~Copyable {
88 borrowing func show( ) -> String
99}
1010
11+ extension CustomStringConvertible {
12+ public func show( ) -> String { return description }
13+ }
14+ extension Int : Show { }
15+
1116public func print( _ s: borrowing some Show & ~ Copyable) {
1217 print ( s. show ( ) )
1318}
@@ -50,37 +55,47 @@ public protocol Generator: ~Copyable {
5055 func next( ) -> Maybe < Element >
5156}
5257
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+
5369// MARK: Tuples
5470public enum Pair < L: ~ Copyable, R: ~ Copyable> : ~ Copyable {
55- case elms ( L , R )
71+ case pair ( L , R )
5672}
73+ extension Pair : Copyable where L: Copyable , R: Copyable { }
5774
5875/// 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 )
6278 case nothing
6379}
64-
6580extension Maybe : Copyable { }
6681
67- extension Maybe : Show where Value : Show & ~ Copyable {
82+ extension Maybe : Show where Wrapped : Show & ~ Copyable {
6883 public borrowing func show( ) -> String {
6984 switch self {
70- case let . just( borrowing elm) :
85+ case let . just( elm) :
7186 return elm. show ( )
7287 case . nothing:
7388 return " <nothing> "
7489 }
7590 }
7691}
7792
78- extension Maybe : Eq where Value : Eq , Value : ~ Copyable {
93+ extension Maybe : Eq where Wrapped : Eq , Wrapped : ~ Copyable {
7994 public static func == ( _ a: borrowing Self , _ b: borrowing Self ) -> Bool {
8095 switch a {
81- case let . just( borrowing a1 ) :
96+ case let . just( a1) :
8297 switch b {
83- case let . just( borrowing b1 ) :
98+ case let . just( b1) :
8499 return a1 == b1
85100 case . nothing:
86101 return false
@@ -96,19 +111,6 @@ extension Maybe: Eq where Value: Eq, Value: ~Copyable {
96111 }
97112}
98113
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-
112114public func isJust< A: ~ Copyable> ( _ m: borrowing Maybe < A > ) -> Bool {
113115 switch m {
114116 case . just:
@@ -127,3 +129,168 @@ public struct UnownedRef<Instance: AnyObject> {
127129 @usableFromInline
128130 internal unowned(unsafe) var _value : Instance
129131}
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