Skip to content

Commit e4708c9

Browse files
committed
Made lazy-ness explicit. Added: Proposal.Lazy. Cleanup.
1 parent d7dd5b5 commit e4708c9

File tree

7 files changed

+118
-52
lines changed

7 files changed

+118
-52
lines changed

Sources/DiffableTextKit/Models/Proposal.swift

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,78 @@
88
//=----------------------------------------------------------------------------=
99

1010
//*============================================================================*
11-
// MARK: * Proposal [...]
11+
// MARK: * Proposal
1212
//*============================================================================*
1313

1414
/// A snapshot and a proposed change that has not yet been applied to it.
1515
public struct Proposal {
1616

1717
//=------------------------------------------------------------------------=
18+
// MARK: State
19+
//=------------------------------------------------------------------------=
1820

1921
public let base: Snapshot
2022
public var replacement: Snapshot
21-
public var range: Range<Index>
23+
public var range: Range<Snapshot.Index>
2224

25+
//=------------------------------------------------------------------------=
26+
// MARK: Initializers
2327
//=------------------------------------------------------------------------=
2428

25-
@inlinable init(_ base: Snapshot, with replacement: Snapshot, in range: Range<Index>) {
29+
@inlinable init(_ base: Snapshot, with replacement: Snapshot, in range: Range<Snapshot.Index>) {
2630
self.base = base; self.replacement = replacement; self.range = range
2731
}
2832

29-
/// Returns a new snapshot with the proposed change applied to it.
33+
//=------------------------------------------------------------------------=
34+
// MARK: Accessors
35+
//=------------------------------------------------------------------------=
36+
37+
@inlinable public var lazy: Lazy { Lazy(self) }
38+
39+
//=------------------------------------------------------------------------=
40+
// MARK: Utilities
41+
//=------------------------------------------------------------------------=
42+
43+
/// Returns a snapshot with the proposed change applied to it.
3044
@inlinable public func merged() -> Snapshot {
3145
var S0 = base; S0.replaceSubrange(range, with: replacement); return S0
3246
}
47+
48+
//*========================================================================*
49+
// MARK: * Lazy
50+
//*========================================================================*
51+
52+
public struct Lazy {
53+
54+
//=--------------------------------------------------------------------=
55+
// MARK: State
56+
//=--------------------------------------------------------------------=
57+
58+
@usableFromInline let proposal: Proposal
59+
60+
//=--------------------------------------------------------------------=
61+
// MARK: Initializers
62+
//=--------------------------------------------------------------------=
63+
64+
@inlinable init(_ proposal: Proposal) { self.proposal = proposal }
65+
66+
//=--------------------------------------------------------------------=
67+
// MARK: Accessors
68+
//=--------------------------------------------------------------------=
69+
70+
@inlinable public var base: Snapshot { proposal.base }
71+
72+
@inlinable public var replacement: Snapshot { proposal.replacement }
73+
74+
@inlinable public var range: Range<Snapshot.Index> { proposal.range }
75+
76+
//=--------------------------------------------------------------------=
77+
// MARK: Utilities
78+
//=--------------------------------------------------------------------=
79+
80+
/// Returns a lazy snapshot with the proposed change applied to it.
81+
@inlinable public func merged() -> LazySequence<FlattenSequence<[Snapshot.SubSequence]>> {
82+
[base[..<range.lowerBound], replacement[...], base[range.upperBound...]].lazy.joined()
83+
}
84+
}
3385
}

Sources/DiffableTextKit/Models/Snapshot.swift

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -110,15 +110,6 @@ ExpressibleByArrayLiteral, ExpressibleByStringLiteral, RangeReplaceableCollectio
110110
public mutating func select(_ positions: Range<Index>) {
111111
self.selection = Selection(positions)
112112
}
113-
114-
//=------------------------------------------------------------------------=
115-
// MARK: Utilities
116-
//=------------------------------------------------------------------------=
117-
118-
/// A lazy sequence of nonvirtual characters.
119-
@inlinable public var nonvirtuals: some BidirectionalCollection<Character> {
120-
self.lazy.filter({!$0.attribute.contains(.virtual)}).map({$0.character})
121-
}
122113
}
123114

124115
//=----------------------------------------------------------------------------=

Sources/DiffableTextKit/Models/Symbol.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,35 @@ ExpressibleByExtendedGraphemeClusterLiteral {
6262
"(\(character), \(attribute))"
6363
}
6464
}
65+
66+
//*============================================================================*
67+
// MARK: * Symbol x Sequence
68+
//*============================================================================*
69+
70+
extension Sequence where Element == Symbol {
71+
72+
//=------------------------------------------------------------------------=
73+
// MARK: Utilities
74+
//=------------------------------------------------------------------------=
75+
76+
/// A sequence of nonvirtual characters.
77+
@inlinable public func nonvirtuals() -> String {
78+
String(lazy.filter({!$0.attribute.contains(.virtual)}).map({$0.character}))
79+
}
80+
}
81+
82+
//*============================================================================*
83+
// MARK: * Symbol x Sequence x Lazy
84+
//*============================================================================*
85+
86+
extension LazySequenceProtocol where Element == Symbol {
87+
88+
//=------------------------------------------------------------------------=
89+
// MARK: Utilities
90+
//=------------------------------------------------------------------------=
91+
92+
/// A lazy sequence of nonvirtual characters.
93+
@inlinable public func nonvirtuals() -> LazyMapSequence<LazyFilterSequence<Elements>, Character> {
94+
filter({!$0.attribute.contains(.virtual)}).map({$0.character})
95+
}
96+
}

Sources/DiffableTextKitXNumber/Models/Interpreter.swift

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,19 @@ import Foundation
5050
// MARK: Utilities
5151
//=------------------------------------------------------------------------=
5252

53-
@inlinable func number(_ snapshot: Snapshot, as value: (some _Value).Type) throws -> Number? {
54-
try .init(unformatted: snapshot.nonvirtuals,signs: components.signs.tokens,
53+
@inlinable func number(_ symbols: some Sequence<Symbol>,
54+
as value: (some _Value).Type) throws -> Number? {
55+
let unformatted = symbols.lazy.nonvirtuals() /*--------------------------*/
56+
return try Number(unformatted: unformatted, signs: components.signs.tokens,
5557
digits: components.digits.tokens, separators: components.separators.tokens,
5658
optional: value.optional, unsigned: value.unsigned, integer: value.integer)
5759
}
5860

59-
@inlinable func number(_ proposal: Proposal, as value: (some _Value).Type) throws -> Number? {
61+
@inlinable func number(_ /**/ proposal: Proposal,
62+
as value: (some _Value).Type) throws -> Number? {
6063
var proposal = proposal; translator.translate(&proposal)
6164
let sign = components.process(&proposal) /*---------*/
62-
var number = try number(proposal.merged(), as: value)
65+
var number = try number(proposal.lazy.merged(),as:value)
6366
if sign != nil { number?.sign = sign! }; return number
6467
}
6568
}

Sources/DiffableTextKitXPattern/Style.swift

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -142,31 +142,33 @@ extension PatternTextStyle {
142142
/// - Mismatches throw an error.
143143
@inlinable @inline(never) public func resolve(_ proposal:
144144
Proposal, with cache: inout Void) throws -> Commit<Value> {
145-
var value = Value(); let proposal = proposal.merged()
146-
var nonvirtuals = proposal.nonvirtuals.makeIterator()
145+
var value = Value()
147146
//=--------------------------------------=
148-
// Parse
147+
// Content
149148
//=--------------------------------------=
150-
parse: for character in pattern {
151-
if let predicate = placeholders[character] {
152-
guard let nonvirtual = nonvirtuals.next() else { break parse }
153-
//=------------------------------=
154-
// Predicate
155-
//=------------------------------=
156-
guard predicate(nonvirtual) else {
157-
throw Info([.mark(nonvirtual), "is invalid"])
158-
}
159-
//=------------------------------=
160-
// Insertion
161-
//=------------------------------=
162-
value.append(nonvirtual)
149+
var nonvirtuals = proposal.lazy.merged().nonvirtuals().makeIterator()
150+
//=--------------------------------------=
151+
// Matches
152+
//=--------------------------------------=
153+
for character in pattern {
154+
guard let predicate = placeholders[character] else { continue }
155+
guard let nonvirtual = nonvirtuals.next() /**/ else { break }
156+
//=------------------------------=
157+
// Predicate
158+
//=------------------------------=
159+
guard predicate(nonvirtual) else {
160+
throw Info([.mark(nonvirtual), "is invalid"])
163161
}
162+
//=------------------------------=
163+
// Insertion
164+
//=------------------------------=
165+
value.append(nonvirtual)
164166
}
165167
//=--------------------------------------=
166168
// Capacity
167169
//=--------------------------------------=
168170
guard nonvirtuals.next() == nil else {
169-
throw Info([.mark(proposal.characters), "exceeded pattern capacity \(value.count)"])
171+
throw Info([.mark(proposal.merged().characters), "exceeded pattern capacity \(value.count)"])
170172
}
171173
//=--------------------------------------=
172174
// Interpret

Tests/DiffableTextKitTests/Models/Proposal.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,3 @@ final class ProposalTests: XCTestCase {
3434
}
3535

3636
#endif
37-

Tests/DiffableTextKitTests/Models/Snapshot.swift

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -61,19 +61,16 @@ final class SnapshotTests: XCTestCase {
6161

6262
func testInitWithCharacters() {
6363
snapshot = Snapshot("AB")
64-
6564
Assert("AB", [.content, .content])
6665
}
6766

6867
func testInitAsArrayLiteral() {
6968
snapshot = [Symbol("A"), Symbol("B", as: .phantom)]
70-
7169
Assert("AB", [.content, .phantom])
7270
}
7371

7472
func testInitAsStringLiteral() {
75-
snapshot = "AB" as Snapshot
76-
73+
snapshot = "AB"
7774
Assert("AB", [.content, .content])
7875
}
7976

@@ -83,7 +80,7 @@ final class SnapshotTests: XCTestCase {
8380

8481
func testNonvirtualsIgnoresVirtualSymbols() {
8582
snapshot = ["A", Symbol("_", as: .virtual), "B"]
86-
XCTAssertEqual(String(snapshot.nonvirtuals), "AB")
83+
XCTAssertEqual(snapshot.nonvirtuals(), "AB")
8784
}
8885

8986
//=------------------------------------------------------------------------=
@@ -92,10 +89,10 @@ final class SnapshotTests: XCTestCase {
9289

9390
func testSelectEndIndex() {
9491
snapshot.append(Symbol(" "))
95-
snapshot.select(snapshot.endIndex)
92+
let index = snapshot.endIndex;snapshot.select(index)
9693
snapshot.append(Symbol(" "))
9794

98-
XCTAssertEqual(snapshot.selection, Selection(snapshot.index(at: C(1))))
95+
XCTAssertEqual(snapshot.selection, Selection(index))
9996
}
10097

10198
//=------------------------------------------------------------------------=
@@ -105,14 +102,12 @@ final class SnapshotTests: XCTestCase {
105102
func testAppendSymbol() {
106103
snapshot.append(Symbol("A"))
107104
snapshot.append(Symbol("B", as: .phantom))
108-
109105
Assert("AB", [.content, .phantom])
110106
}
111107

112108
func testAppendCharacter() {
113109
snapshot.append(Character("A"))
114110
snapshot.append(Character("B"), as: .phantom)
115-
116111
Assert("AB", [.content, .phantom])
117112
}
118113

@@ -123,14 +118,12 @@ final class SnapshotTests: XCTestCase {
123118
func testAppendContentsOfSymbols() {
124119
snapshot.append(contentsOf: Snapshot("A", as: .content))
125120
snapshot.append(contentsOf: Snapshot("B", as: .phantom))
126-
127121
Assert("AB", [.content, .phantom])
128122
}
129123

130124
func testAppendContentsOfCharacters() {
131125
snapshot.append(contentsOf: String("A"))
132126
snapshot.append(contentsOf: String("B"), as: .phantom)
133-
134127
Assert("AB", [.content, .phantom])
135128
}
136129

@@ -141,14 +134,12 @@ final class SnapshotTests: XCTestCase {
141134
func testInsertSymbol() {
142135
snapshot.insert(Symbol("B", as: .phantom), at: snapshot.startIndex)
143136
snapshot.insert(Symbol("A", as: .content), at: snapshot.startIndex)
144-
145137
Assert("AB", [.content, .phantom])
146138
}
147139

148140
func testInsertCharacter() {
149141
snapshot.insert(Character("B"), at: snapshot.startIndex, as: .phantom)
150142
snapshot.insert(Character("A"), at: snapshot.startIndex)
151-
152143
Assert("AB", [.content, .phantom])
153144
}
154145

@@ -159,14 +150,12 @@ final class SnapshotTests: XCTestCase {
159150
func testInsertContentsOfSymbols() {
160151
snapshot.insert(contentsOf: Snapshot("B", as: .phantom), at: snapshot.startIndex)
161152
snapshot.insert(contentsOf: Snapshot("A", as: .content), at: snapshot.startIndex)
162-
163153
Assert("AB", [.content, .phantom])
164154
}
165155

166156
func testInsertContentsOfCharacters() {
167157
snapshot.insert(contentsOf: String("B"), at: snapshot.startIndex, as: .phantom)
168158
snapshot.insert(contentsOf: String("A"), at: snapshot.startIndex)
169-
170159
Assert("AB", [.content, .phantom])
171160
}
172161

@@ -178,15 +167,13 @@ final class SnapshotTests: XCTestCase {
178167
snapshot = Snapshot(repeating: " ", count: 4)
179168
snapshot.replaceSubrange(snapshot.indices(at: C(0) ..< 2), with: Snapshot("AA", as: .content))
180169
snapshot.replaceSubrange(snapshot.indices(at: C(2) ..< 4), with: Snapshot("BB", as: .phantom))
181-
182170
Assert("AABB", [.content, .content, .phantom, .phantom])
183171
}
184172

185173
func testReplaceSubrangeWithCharacters() {
186174
snapshot = Snapshot(repeating: " ", count: 4)
187175
snapshot.replaceSubrange(snapshot.indices(at: C(0) ..< 2), with: Snapshot("AA", as: .content))
188176
snapshot.replaceSubrange(snapshot.indices(at: C(2) ..< 4), with: Snapshot("BB", as: .phantom))
189-
190177
Assert("AABB", [.content, .content, .phantom, .phantom])
191178
}
192179

0 commit comments

Comments
 (0)