Skip to content

Commit 0877085

Browse files
authored
Add Stack implementation (#128)
1 parent bd95c92 commit 0877085

File tree

2 files changed

+165
-0
lines changed

2 files changed

+165
-0
lines changed
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
//
2+
// Stack.swift
3+
// OpenSwiftUICore
4+
//
5+
// Audited for RELEASE_2024
6+
// Status: Blocked by GraphReusable
7+
8+
package enum Stack<Value>: Sequence, IteratorProtocol {
9+
case empty
10+
indirect case node(value: Value, next: Stack<Value>)
11+
12+
@inlinable
13+
package init() {
14+
self = .empty
15+
}
16+
17+
package var top: Value? {
18+
switch self {
19+
case .empty:
20+
return nil
21+
case let .node(value, _):
22+
return value
23+
}
24+
}
25+
26+
@inlinable
27+
package var count: Int {
28+
var iterator = makeIterator()
29+
var count = 0
30+
while (iterator.next() != nil) {
31+
count &+= 1
32+
}
33+
return count
34+
}
35+
36+
@inlinable
37+
package var isEmpty: Bool {
38+
top == nil
39+
}
40+
41+
@inlinable
42+
package mutating func push(_ value: Value) {
43+
self = .node(value: value, next: self)
44+
}
45+
46+
@discardableResult
47+
@inlinable
48+
package mutating func pop() -> Value? {
49+
switch self {
50+
case .empty:
51+
return nil
52+
case let .node(value, next):
53+
self = next
54+
return value
55+
}
56+
}
57+
58+
@inlinable
59+
package mutating func popAll() {
60+
self = .empty
61+
}
62+
63+
package func map<T>(_ transform: (Value) -> T) -> Stack<T> {
64+
withUnsafeTemporaryAllocation(
65+
of: T.self,
66+
capacity: count
67+
) { buffer in
68+
var iterator = makeIterator()
69+
var next: Value?
70+
var index = 0
71+
repeat {
72+
index &+= 1
73+
next = iterator.next()
74+
guard let next else { break }
75+
buffer.initializeElement(at: count - index, to: transform(next))
76+
} while true
77+
78+
var stack = Stack<T>()
79+
for index in buffer.indices {
80+
stack.push(buffer[index])
81+
}
82+
return stack
83+
}
84+
}
85+
86+
package mutating func next() -> Value? {
87+
pop()
88+
}
89+
90+
package typealias Element = Value
91+
package typealias Iterator = Stack<Value>
92+
}
93+
94+
extension Stack: Equatable where Value: Equatable {
95+
package static func == (a: Stack<Value>, b: Stack<Value>) -> Bool {
96+
switch (a, b) {
97+
case (.empty, .empty):
98+
return true
99+
case let (.node(valueA, nextA), .node(valueB, nextB)):
100+
return valueA == valueB && nextA == nextB
101+
default:
102+
return false
103+
}
104+
}
105+
}
106+
107+
//extension Stack: GraphReusable where Value: GraphReusable {
108+
// @inlinable
109+
// package static var isTriviallyReusable: Bool {
110+
// Value.isTriviallyReusable
111+
// }
112+
//
113+
// package mutating func makeReusable(indirectMap: IndirectAttributeMap) {
114+
// guard !isEmpty else { return }
115+
// map { $0.makeReusable(indirectMap: indirectMap) }
116+
// }
117+
//
118+
// package func tryToReuse(by other: Stack<Value>, indirectMap: IndirectAttributeMap, testOnly: Bool) -> Bool
119+
//}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//
2+
// StackTests.swift
3+
// OpenSwiftUICore
4+
5+
@testable import OpenSwiftUICore
6+
import Testing
7+
8+
struct StackTests {
9+
@Test
10+
func exmpla() {
11+
var stack: Stack<Int> = Stack()
12+
#expect(stack.isEmpty)
13+
14+
stack.push(1)
15+
stack.push(2)
16+
#expect(stack.count == 2)
17+
#expect(!stack.isEmpty)
18+
19+
#expect(stack.pop() == 2)
20+
#expect(stack.count == 1)
21+
#expect(!stack.isEmpty)
22+
23+
#expect(stack.pop() == 1)
24+
#expect(stack.count == 0)
25+
#expect(stack.isEmpty)
26+
27+
stack.push(3)
28+
stack.push(4)
29+
stack.popAll()
30+
#expect(stack.count == 0)
31+
#expect(stack.isEmpty)
32+
33+
stack.push(5)
34+
stack.push(6)
35+
var newStack = stack.map { $0 * 2 }
36+
37+
#expect(newStack.pop() == 12)
38+
#expect(newStack.count == 1)
39+
#expect(!newStack.isEmpty)
40+
41+
#expect(newStack.pop() == 10)
42+
#expect(newStack.count == 0)
43+
#expect(newStack.isEmpty)
44+
}
45+
46+
}

0 commit comments

Comments
 (0)