Skip to content

Overhaul quantification fast-path #689

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Aug 21, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
wip: small refactoring
  • Loading branch information
milseman committed Aug 21, 2023
commit 3cb56d602bc7b0cc13fba46306bd927ba9a7839b
17 changes: 14 additions & 3 deletions Sources/_StringProcessing/Engine/Backtracking.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ extension Processor {
struct SavePoint {
var pc: InstructionAddress
var pos: Position?

// Quantifiers may store a range of positions to restore to
var rangeStart: Position?
var rangeEnd: Position?
Expand Down Expand Up @@ -49,25 +50,35 @@ extension Processor {
return (pc, pos, stackEnd, captureEnds, intRegisters, posRegisters)
}

var rangeIsEmpty: Bool { rangeEnd == nil }
// Whether this save point is quantified, meaning it has a range of
// possible positions to explore.
var isQuantified: Bool {
if rangeEnd == nil {
assert(rangeStart == nil)
return false
}
assert(rangeStart != nil)
return true
}

mutating func updateRange(newEnd: Input.Index) {
if rangeStart == nil {
assert(rangeEnd == nil)
rangeStart = newEnd
}
rangeEnd = newEnd
}

/// Move the next range position into pos, and removing it from the range
mutating func takePositionFromRange(_ input: Input) {
assert(!rangeIsEmpty)
assert(isQuantified)
pos = rangeEnd!
shrinkRange(input)
}

/// Shrink the range of the save point by one index, essentially dropping the last index
mutating func shrinkRange(_ input: Input) {
assert(!rangeIsEmpty)
assert(isQuantified)
if rangeEnd == rangeStart {
// The range is now empty
rangeStart = nil
Expand Down
10 changes: 5 additions & 5 deletions Sources/_StringProcessing/Engine/MEQuantify.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ extension Processor {
}
let next = _doQuantifyMatch(payload)
guard let idx = next else {
if !savePoint.rangeIsEmpty {
if savePoint.isQuantified {
// The last save point has saved the current, non-matching position,
// so it's unneeded.
savePoint.shrinkRange(input)
Expand All @@ -80,7 +80,7 @@ extension Processor {
return false
}

if !savePoint.rangeIsEmpty {
if savePoint.isQuantified {
savePoints.append(savePoint)
}
return true
Expand All @@ -104,7 +104,7 @@ extension Processor {

// The last save point has saved the current position, so it's unneeded
savePoint.shrinkRange(input)
if !savePoint.rangeIsEmpty {
if savePoint.isQuantified {
savePoints.append(savePoint)
}
return true
Expand All @@ -125,13 +125,13 @@ extension Processor {
savePoint.updateRange(newEnd: currentPosition)
}

if savePoint.rangeIsEmpty {
if !savePoint.isQuantified {
signalFailure()
return false
}
// The last save point has saved the current position, so it's unneeded
savePoint.shrinkRange(input)
if !savePoint.rangeIsEmpty {
if savePoint.isQuantified {
savePoints.append(savePoint)
}
return true
Expand Down
13 changes: 6 additions & 7 deletions Sources/_StringProcessing/Engine/Processor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -335,15 +335,14 @@ extension Processor {
)

let idx = savePoints.index(before: savePoints.endIndex)
// If we have a quantifier save point, move the next range position into pos
if !savePoints[idx].rangeIsEmpty {

// If we have a quantifier save point, move the next range position into
// pos instead of removing it
if savePoints[idx].isQuantified {
savePoints[idx].takePositionFromRange(input)
}
// If we have a normal save point or an empty quantifier save point, remove it
if savePoints[idx].rangeIsEmpty {
(pc, pos, stackEnd, capEnds, intRegisters, posRegisters) = savePoints.removeLast().destructure
} else {
(pc, pos, stackEnd, capEnds, intRegisters, posRegisters) = savePoints[idx].destructure
} else {
(pc, pos, stackEnd, capEnds, intRegisters, posRegisters) = savePoints.removeLast().destructure
}

assert(stackEnd.rawValue <= callStack.count)
Expand Down
2 changes: 1 addition & 1 deletion Sources/_StringProcessing/Engine/Tracing.swift
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ extension Processor.SavePoint {
if let p = self.pos {
posStr = "\(input.distance(from: input.startIndex, to: p))"
} else {
if rangeIsEmpty {
if !isQuantified {
posStr = "<none>"
} else {
let startStr = "\(input.distance(from: input.startIndex, to: rangeStart!))"
Expand Down