Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -141,129 +141,129 @@
<key>com.apple.dt.XCTMetric_CPU.instructions_retired</key>
<dict>
<key>baselineAverage</key>
<real>1.3081e+06</real>
<real>1.1767e+06</real>
<key>baselineIntegrationDisplayName</key>
<string>19 Aug 2020 at 20:14:16</string>
<string>4 Sep 2020 at 18:29:36</string>
</dict>
</dict>
<key>testContainsClosure()</key>
<dict>
<key>com.apple.dt.XCTMetric_CPU.instructions_retired</key>
<dict>
<key>baselineAverage</key>
<real>1.5442e+06</real>
<real>1.0476e+06</real>
<key>baselineIntegrationDisplayName</key>
<string>19 Aug 2020 at 20:14:16</string>
<string>4 Sep 2020 at 18:29:36</string>
</dict>
</dict>
<key>testGrammarLiteralSearch()</key>
<dict>
<key>com.apple.dt.XCTMetric_CPU.instructions_retired</key>
<dict>
<key>baselineAverage</key>
<real>6.0042e+05</real>
<real>5.4628e+05</real>
<key>baselineIntegrationDisplayName</key>
<string>19 Aug 2020 at 20:14:16</string>
<string>4 Sep 2020 at 18:29:36</string>
</dict>
</dict>
<key>testLine()</key>
<dict>
<key>com.apple.dt.XCTMetric_CPU.instructions_retired</key>
<dict>
<key>baselineAverage</key>
<real>1.7144e+06</real>
<real>1.7351e+06</real>
<key>baselineIntegrationDisplayName</key>
<string>19 Aug 2020 at 20:14:16</string>
<string>4 Sep 2020 at 18:29:36</string>
</dict>
</dict>
<key>testLiteralSearch()</key>
<dict>
<key>com.apple.dt.XCTMetric_CPU.instructions_retired</key>
<dict>
<key>baselineAverage</key>
<real>6.3992e+06</real>
<real>6.3384e+06</real>
<key>baselineIntegrationDisplayName</key>
<string>19 Aug 2020 at 20:14:16</string>
<string>4 Sep 2020 at 18:29:36</string>
</dict>
</dict>
<key>testNonExistentLiteralSearch()</key>
<dict>
<key>com.apple.dt.XCTMetric_CPU.instructions_retired</key>
<dict>
<key>baselineAverage</key>
<real>3.4154e+06</real>
<real>3.4736e+06</real>
<key>baselineIntegrationDisplayName</key>
<string>19 Aug 2020 at 20:14:16</string>
<string>4 Sep 2020 at 18:29:36</string>
</dict>
</dict>
<key>testNotNewLine()</key>
<dict>
<key>com.apple.dt.XCTMetric_CPU.instructions_retired</key>
<dict>
<key>baselineAverage</key>
<real>1.5535e+06</real>
<real>1.5674e+06</real>
<key>baselineIntegrationDisplayName</key>
<string>19 Aug 2020 at 20:14:16</string>
<string>4 Sep 2020 at 18:29:36</string>
</dict>
</dict>
<key>testOneOrMore()</key>
<dict>
<key>com.apple.dt.XCTMetric_CPU.instructions_retired</key>
<dict>
<key>baselineAverage</key>
<real>9.2286e+05</real>
<real>8.66e+05</real>
<key>baselineIntegrationDisplayName</key>
<string>19 Aug 2020 at 20:14:16</string>
<string>4 Sep 2020 at 18:29:36</string>
</dict>
</dict>
<key>testOptionalStringFollowedByNonOptionalString()</key>
<dict>
<key>com.apple.dt.XCTMetric_CPU.instructions_retired</key>
<dict>
<key>baselineAverage</key>
<real>1.0759e+06</real>
<real>9.5629e+05</real>
<key>baselineIntegrationDisplayName</key>
<string>19 Aug 2020 at 20:14:16</string>
<string>4 Sep 2020 at 18:29:36</string>
</dict>
</dict>
<key>testSkipping1()</key>
<dict>
<key>com.apple.dt.XCTMetric_CPU.instructions_retired</key>
<dict>
<key>baselineAverage</key>
<real>1.1965e+06</real>
<real>1.2135e+06</real>
<key>baselineIntegrationDisplayName</key>
<string>19 Aug 2020 at 20:14:16</string>
<string>4 Sep 2020 at 18:29:36</string>
</dict>
</dict>
<key>testUppercaseWord()</key>
<dict>
<key>com.apple.dt.XCTMetric_CPU.instructions_retired</key>
<dict>
<key>baselineAverage</key>
<real>2.9068e+06</real>
<real>2.6215e+06</real>
<key>baselineIntegrationDisplayName</key>
<string>19 Aug 2020 at 20:14:16</string>
<string>4 Sep 2020 at 18:29:36</string>
</dict>
</dict>
<key>testWordBoundary()</key>
<dict>
<key>com.apple.dt.XCTMetric_CPU.instructions_retired</key>
<dict>
<key>baselineAverage</key>
<real>2.5362e+06</real>
<real>1.7362e+06</real>
<key>baselineIntegrationDisplayName</key>
<string>19 Aug 2020 at 20:14:16</string>
<string>4 Sep 2020 at 18:29:36</string>
</dict>
</dict>
<key>testWordBoundaryManyLanguages()</key>
<dict>
<key>com.apple.dt.XCTMetric_CPU.instructions_retired</key>
<dict>
<key>baselineAverage</key>
<real>3.7748e+06</real>
<real>3.257e+06</real>
<key>baselineIntegrationDisplayName</key>
<string>19 Aug 2020 at 20:14:16</string>
<string>4 Sep 2020 at 18:29:36</string>
</dict>
</dict>
</dict>
Expand All @@ -274,69 +274,69 @@
<key>com.apple.dt.XCTMetric_CPU.instructions_retired</key>
<dict>
<key>baselineAverage</key>
<real>4.1135e+05</real>
<real>3.7555e+05</real>
<key>baselineIntegrationDisplayName</key>
<string>19 Aug 2020 at 20:14:16</string>
<string>4 Sep 2020 at 18:29:36</string>
</dict>
</dict>
<key>testLine()</key>
<dict>
<key>com.apple.dt.XCTMetric_CPU.instructions_retired</key>
<dict>
<key>baselineAverage</key>
<real>9.6233e+05</real>
<real>9.8235e+05</real>
<key>baselineIntegrationDisplayName</key>
<string>19 Aug 2020 at 20:14:16</string>
<string>4 Sep 2020 at 18:29:36</string>
</dict>
</dict>
<key>testLiteralSearch()</key>
<dict>
<key>com.apple.dt.XCTMetric_CPU.instructions_retired</key>
<dict>
<key>baselineAverage</key>
<real>8.3321e+05</real>
<real>8.3797e+05</real>
<key>baselineIntegrationDisplayName</key>
<string>19 Aug 2020 at 20:14:16</string>
<string>4 Sep 2020 at 18:29:36</string>
</dict>
</dict>
<key>testNonExistentLiteralSearch()</key>
<dict>
<key>com.apple.dt.XCTMetric_CPU.instructions_retired</key>
<dict>
<key>baselineAverage</key>
<real>6.0671e+05</real>
<real>6.0681e+05</real>
<key>baselineIntegrationDisplayName</key>
<string>19 Aug 2020 at 20:14:16</string>
<string>4 Sep 2020 at 18:29:36</string>
</dict>
</dict>
<key>testNotNewLine()</key>
<dict>
<key>com.apple.dt.XCTMetric_CPU.instructions_retired</key>
<dict>
<key>baselineAverage</key>
<real>7.4556e+05</real>
<real>7.6005e+05</real>
<key>baselineIntegrationDisplayName</key>
<string>19 Aug 2020 at 20:14:16</string>
<string>4 Sep 2020 at 18:29:36</string>
</dict>
</dict>
<key>testOptionalStringFollowedByNonOptionalString()</key>
<dict>
<key>com.apple.dt.XCTMetric_CPU.instructions_retired</key>
<dict>
<key>baselineAverage</key>
<real>8.219e+05</real>
<real>7.4862e+05</real>
<key>baselineIntegrationDisplayName</key>
<string>19 Aug 2020 at 20:14:16</string>
<string>4 Sep 2020 at 18:29:36</string>
</dict>
</dict>
<key>testSkipping1()</key>
<dict>
<key>com.apple.dt.XCTMetric_CPU.instructions_retired</key>
<dict>
<key>baselineAverage</key>
<real>2.2521e+05</real>
<real>2.4327e+05</real>
<key>baselineIntegrationDisplayName</key>
<string>19 Aug 2020 at 20:14:16</string>
<string>4 Sep 2020 at 18:29:36</string>
</dict>
</dict>
</dict>
Expand Down
6 changes: 6 additions & 0 deletions Sources/Patterns/General/General.swift
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,12 @@ extension RangeReplaceableCollection where SubSequence == Self, Self: Bidirectio
}
removeAll()
}

@inlinable
mutating func removeSuffix(from index: Index) {
guard index < endIndex else { return }
removeLast(distance(from: index, to: endIndex))
}
}

extension RangeReplaceableCollection {
Expand Down
48 changes: 23 additions & 25 deletions Sources/Patterns/VMBacktrack.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ struct VMEngine<Input: BidirectionalCollection> where Input.Element: Hashable {
@usableFromInline
typealias Instructions = ContiguousArray<Instruction<Input>>
@usableFromInline
typealias Captures = ContiguousArray<(index: Input.Index,
instruction: VMEngine<Input>.Instructions.Index)>.SubSequence
@usableFromInline
let instructions: Instructions

@usableFromInline
Expand All @@ -34,25 +37,27 @@ struct VMEngine<Input: BidirectionalCollection> where Input.Element: Hashable {

extension Parser.Match {
@usableFromInline
init(_ thread: VMEngine<Input>.Thread, instructions: VMEngine<Input>.Instructions) {
var captures = [(name: String?, range: Range<Input.Index>)]()
captures.reserveCapacity(thread.captures.count / 2)
init(_ thread: VMEngine<Input>.Thread,
instructions: VMEngine<Input>.Instructions,
captures: VMEngine<Input>.Captures) {
var newCaptures = [(name: String?, range: Range<Input.Index>)]()
newCaptures.reserveCapacity(captures.count / 2)
var captureBeginnings = [(name: String?, start: Input.Index)]()
captureBeginnings.reserveCapacity(captures.capacity)
for capture in thread.captures {
for capture in captures {
switch instructions[capture.instruction] {
case let .captureStart(name, _):
captureBeginnings.append((name, capture.index))
case .captureEnd:
let beginning = captureBeginnings.removeLast()
captures.append((name: beginning.name, range: beginning.start ..< capture.index))
newCaptures.append((name: beginning.name, range: beginning.start ..< capture.index))
default:
fatalError("Captured wrong instructions.")
}
}
assert(captureBeginnings.isEmpty)
self.endIndex = thread.inputIndex
self.captures = captures
self.captures = newCaptures
}
}

Expand All @@ -64,40 +69,36 @@ extension VMEngine {
@usableFromInline
var inputIndex: Input.Index
@usableFromInline
var captures: ContiguousArray<(index: Input.Index, instruction: Instructions.Index)>
var capturesEndIndex: Captures.Index
@usableFromInline
var isReturnAddress: Bool = false

@usableFromInline
init(startAt instructionIndex: Int, withDataFrom other: Thread) {
self.instructionIndex = instructionIndex
self.inputIndex = other.inputIndex
self.captures = other.captures
self.capturesEndIndex = other.capturesEndIndex
}

@usableFromInline
init(instructionIndex: Instructions.Index, inputIndex: Input.Index) {
self.instructionIndex = instructionIndex
self.inputIndex = inputIndex
self.captures = []
self.capturesEndIndex = 0
}
}

@usableFromInline
func launch(input: Input, startIndex: Input.Index? = nil) -> Parser<Input>.Match? {
// Skip the first instruction, which is always '.fail'.
let thread = Thread(instructionIndex: instructions.startIndex + 1, inputIndex: startIndex ?? input.startIndex)
return launch(input: input, thread: thread)
.map { Parser.Match($0, instructions: instructions) }
}

@usableFromInline
func launch(input: Input, thread: Thread) -> Thread? {
var stack = ContiguousArray<Thread>()[...]
stack.append(thread)
stack.append(
Thread(instructionIndex: instructions.startIndex + 1, inputIndex: startIndex ?? input.startIndex))
var captures = Captures()

while var thread = stack.popLast() {
assert(!thread.isReturnAddress, "Stack unexpectedly contains .returnAddress after fail")
captures.removeSuffix(from: thread.capturesEndIndex)
defer { // Fail, when `break loop` is called.
stack.removeSuffix(where: { $0.isReturnAddress })
}
Expand Down Expand Up @@ -125,20 +126,18 @@ extension VMEngine {
thread.instructionIndex += 1
case let .jump(distance):
thread.instructionIndex += distance
case let .captureStart(_, offset):
let index = input.index(thread.inputIndex, offsetBy: offset)
thread.captures.append((index: index, instruction: thread.instructionIndex))
thread.instructionIndex += 1
case let .captureEnd(offset):
case let .captureStart(_, offset),
let .captureEnd(offset):
let index = input.index(thread.inputIndex, offsetBy: offset)
thread.captures.append((index: index, instruction: thread.instructionIndex))
captures.append((index: index, instruction: thread.instructionIndex))
thread.instructionIndex += 1
case let .choice(offset, atIndex):
var newThread = Thread(startAt: thread.instructionIndex + offset, withDataFrom: thread)
if atIndex != 0, !input.formIndexSafely(&newThread.inputIndex, offsetBy: atIndex) {
// we must always add to the stack here, so send it to an instruction that is always `.fail`
newThread.instructionIndex = instructions.startIndex
}
newThread.capturesEndIndex = captures.endIndex
stack.append(newThread)
thread.instructionIndex += 1
case .choiceEnd:
Expand All @@ -156,7 +155,6 @@ extension VMEngine {
var returnAddress = thread
returnAddress.instructionIndex += 1
returnAddress.isReturnAddress = true
returnAddress.captures.removeAll()
stack.append(returnAddress)
thread.instructionIndex += offset
case .return:
Expand All @@ -166,7 +164,7 @@ extension VMEngine {
case .fail:
break loop
case .match:
return thread
return Parser.Match(thread, instructions: instructions, captures: captures)
case .openCall:
fatalError("`.openCall` should be removed by Grammar.")
case .skip:
Expand Down
Loading