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
43 changes: 21 additions & 22 deletions Public/js/views/debugger_highlighter.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,35 +21,35 @@ export default class DebuggerHighlighter {

for (const trace of traces) {
const className = "debuggermatch";
const location = Editor.calcRangePos(
this.editor,
trace.location.start,
trace.location.end - trace.location.start
);
marks.push(
doc.markText(location.startPos, location.endPos, {
className: className,
})
);

if (trace.location.start === trace.location.end) {

if (trace.location.start !== trace.location.end) {
const location = Editor.calcRangePos(
this.editor,
trace.location.start,
trace.location.end - trace.location.start
);

marks.push(
doc.markText(location.startPos, location.endPos, {
className: className,
})
);
} else {
const pos = doc.posFromIndex(trace.location.start);

const widget = document.createElement("span");
widget.className = className;

widget.style.position = "absolute";
widget.style.zIndex = "10";

widget.style.height = `${defaultTextHeight * 1.5}px`;
widget.style.width = "1px";
widget.style.zIndex = "10";

this.editor.addWidget(pos, widget);

const coords = editor.charCoords(pos, "local");
widget.style.left = `${coords.left}px`;
widget.style.top = `${coords.top + 2}px`;

editor.getWrapperElement().appendChild(widget);

this.widgets.push(widget);
}
}
Expand All @@ -60,17 +60,16 @@ export default class DebuggerHighlighter {
const widget = document.createElement("span");
widget.className = "debuggerbacktrack";

widget.style.position = "absolute";
widget.style.zIndex = "10";
widget.style.height = `${defaultTextHeight * 1.5}px`;
widget.style.width = `${editor.defaultCharWidth()}px`;
widget.style.zIndex = "10";

this.editor.addWidget(pos, widget);

const coords = editor.charCoords(pos, "local");
widget.style.left = `${coords.left}px`;
widget.style.top = `${coords.top + 2}px`;

editor.getWrapperElement().appendChild(widget);

this.widgets.push(widget);
}
});
Expand All @@ -85,7 +84,7 @@ export default class DebuggerHighlighter {
marks.length = 0;

for (const widget of this.widgets) {
widget.remove();
widget.parentNode.removeChild(widget);
}
this.widgets.length = 0;
});
Expand Down
2 changes: 2 additions & 0 deletions Public/js/views/test_highlighter.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ export default class TestHighlighter extends EventDispatcher {
addLeftAnchor(location, attributes = {}) {
const widget = document.createElement("span");
widget.className = "match-left";

widget.style.height = `${this.textHeight * 1.5}px`;
widget.style.width = "1px";
widget.style.zIndex = "10";
Expand All @@ -113,6 +114,7 @@ export default class TestHighlighter extends EventDispatcher {
addRightAnchor(location, attributes = {}) {
const widget = document.createElement("span");
widget.className = "match-right";

widget.style.height = `${this.textHeight * 1.5}px`;
widget.style.width = "1px";
widget.style.zIndex = "10";
Expand Down
4 changes: 1 addition & 3 deletions Sources/App/Debugger/Context.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ import Foundation

extension Debugger {
class Context {
static let shared = Context()

var instructions: [String] = []
var programCounter = 0

Expand All @@ -18,7 +16,7 @@ extension Debugger {
var resets = 0
var backtracks = 0

private init(stepCount: Int = 0, breakPoint: Int? = nil) {
init(stepCount: Int = 0, breakPoint: Int? = nil) {
self.stepCount = stepCount
self.breakPoint = breakPoint
}
Expand Down
7 changes: 4 additions & 3 deletions Sources/App/Debugger/Debugger.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Foundation
@testable @_spi(RegexBenchmark) import _StringProcessing

struct Debugger {
func run(pattern: String, text: String, matchingOptions: [String] = []) throws {
func run(pattern: String, text: String, matchingOptions: [String] = [], context: Debugger.Context) throws {
let ast = try _RegexParser.parse(pattern, .traditional)

var sequence = [AST.MatchingOption]()
Expand Down Expand Up @@ -32,7 +32,7 @@ struct Debugger {

let program = try compile(ast, options: options)

Debugger.Context.shared.instructions = program.instructions.map {
context.instructions = program.instructions.map {
$0.description
}

Expand All @@ -49,7 +49,8 @@ struct Debugger {
do {
_ = try Executor<AnyRegexOutput>._firstMatch(
program,
using: &cpu
using: &cpu,
context: context
)
} catch {}
}
Expand Down
41 changes: 26 additions & 15 deletions Sources/App/Debugger/Executor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,42 @@ enum Executor<Output> {
_ program: MEProgram,
_ input: String,
subjectBounds: Range<String.Index>,
searchBounds: Range<String.Index>
searchBounds: Range<String.Index>,
context: Debugger.Context
) throws -> Regex<Output>.Match? {
try Executor._run(
program,
input,
subjectBounds: subjectBounds,
searchBounds: searchBounds,
mode: .partialFromFront)
mode: .partialFromFront,
context: context
)
}

static func wholeMatch(
_ program: MEProgram,
_ input: String,
subjectBounds: Range<String.Index>,
searchBounds: Range<String.Index>
searchBounds: Range<String.Index>,
context: Debugger.Context
) throws -> Regex<Output>.Match? {
try Executor._run(
program,
input,
subjectBounds: subjectBounds,
searchBounds: searchBounds,
mode: .wholeString)
mode: .wholeString,
context: context
)
}

static func firstMatch(
_ program: MEProgram,
_ input: String,
subjectBounds: Range<String.Index>,
searchBounds: Range<String.Index>
searchBounds: Range<String.Index>,
context: Debugger.Context
) throws -> Regex<Output>.Match? {
var cpu = Processor(
program: program,
Expand All @@ -45,19 +52,22 @@ enum Executor<Output> {
)
return try Executor._firstMatch(
program,
using: &cpu)
using: &cpu,
context: context
)
}

static func _firstMatch(
_ program: MEProgram,
using cpu: inout Processor
using cpu: inout Processor,
context: Debugger.Context
) throws -> Regex<Output>.Match? {
let isGraphemeSemantic = program.initialOptions.semanticLevel == .graphemeCluster

var low = cpu.searchBounds.lowerBound
let high = cpu.searchBounds.upperBound
while true {
if let m = try Executor._run(program, &cpu) {
if let m = try Executor._run(program, &cpu, context) {
return m
}
// Fast-path for start-anchored regex
Expand All @@ -84,24 +94,26 @@ extension Executor {
_ input: String,
subjectBounds: Range<String.Index>,
searchBounds: Range<String.Index>,
mode: MatchMode
mode: MatchMode,
context: Debugger.Context
) throws -> Regex<Output>.Match? {
var cpu = Processor(
program: program,
input: input,
subjectBounds: subjectBounds,
searchBounds: searchBounds,
matchMode: mode)
return try _run(program, &cpu)
return try _run(program, &cpu, context)
}

static func _run(
_ program: MEProgram,
_ cpu: inout Processor
_ cpu: inout Processor,
_ context: Debugger.Context
) throws -> Regex<Output>.Match? {
let startPosition = cpu.currentPosition
Debugger.Context.shared.start = startPosition.utf16Offset(in: cpu.input)
guard let endIdx = try cpu.run() else {
context.start = startPosition.utf16Offset(in: cpu.input)
guard let endIdx = try cpu.run(context) else {
return nil
}
let range = startPosition..<endIdx
Expand All @@ -113,7 +125,7 @@ extension Executor {
}}

extension Processor {
fileprivate mutating func run() throws -> Input.Index? {
fileprivate mutating func run(_ context: Debugger.Context) throws -> Input.Index? {
if self.state == .fail {
if let e = failureReason {
throw e
Expand All @@ -122,7 +134,6 @@ extension Processor {
}
assert(isReset())
while true {
let context = Debugger.Context.shared
context.programCounter = controller.pc.rawValue

switch self.state {
Expand Down
6 changes: 3 additions & 3 deletions Sources/App/routes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -127,16 +127,16 @@ func routes(_ app: Application) throws {
}

func debug(pattern: String, text: String, matchOptions: [String], step: String?) throws -> ResultResponse {
let context = Debugger.Context()

func run(pattern: String, text: String, matchingOptions: [String] = [], until step: Int? = nil) throws {
let context = Debugger.Context.shared
context.reset()
context.breakPoint = step

let debugger = Debugger()
try debugger.run(pattern: pattern, text: text, matchingOptions: matchingOptions)
try debugger.run(pattern: pattern, text: text, matchingOptions: matchingOptions, context: context)
}

let context = Debugger.Context.shared
let breakPoint: Int?
if let step {
breakPoint = Int(step)
Expand Down