1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
|
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2021-2022 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
//
//===----------------------------------------------------------------------===//
@testable import _StringProcessing
extension PEG.VM {
struct Code {
var functions: Array<Function>
var start: Function { functions[0] }
// TODO: Capture metadata
func lookup(_ f: FunctionId) -> Function {
functions[f.rawValue]
}
}
}
extension PEG.VM.Code {
enum Instruction {
case nop
case comment(String)
// Advance the InIndex by a fixed amount of positions
case consume(Int)
// Advance the InIndex by a dynamic amount of positions
//case advance(Register) should we have non-bool registers?
// TODO: Matching vs asserting...
// Match and consume
case element(Element)
case set((Element) -> Bool)
case any
// Control flow
case branch(to: LabelId)
case condBranch(condition: BoolRegister, to: LabelId)
case label(LabelId) // TODO: separate out
// Function calls
case call(FunctionId)
case ret
// Backtracking (TODO: should this be explicit slots or implicit stack?)
case save(restoringAt: LabelId)
// case restore
case commit(continuingAt: LabelId)
// Capture
case startCapture
case endCapture
// TODO: Consider captures an PC/SP pair, requires ability to
// save / retrieve SPs and a commit-capture instruction.
// Terminate
case accept
case fail
case abort
}
}
extension PEG.VM.Code {
struct Function {
let name: String
var instructions: InstructionList<Instruction>
init(name: String) {
self.name = name
self.instructions = [.comment(name)]
}
// Label location metadata
// TODO: Array permitting uninitialized values
var labels: Dictionary<LabelId, InstructionAddress> = [:]
// TODO: Do we want to represent capture metadata?
func lookup(_ p: InstructionAddress) -> Instruction { instructions[p] }
func lookup(_ l: LabelId) -> InstructionAddress { labels[l]! }
mutating func add(_ inst: Instruction) {
if case .label = inst {
assertionFailure("Compilation error: label instruction")
}
instructions.append(inst)
}
mutating func addLabel(_ id: LabelId) {
labels[id] = InstructionAddress(instructions.count)
instructions.append(.label(id))
}
}
}
extension PEG.VM.Code.Instruction: CustomStringConvertible {
var description: String {
switch self {
case .nop: return "<nop>"
case .consume(let i): return "<eat \(i)>"
case .element(let e): return "<match '\(e)'>"
case .set(let s): return "<predicate \(String(describing: s))>"
case .any: return "<any>"
case .branch(let to): return "<branch to: \(to)>"
case .condBranch(let condition, let to):
return "<cond br \(condition) to: \(to)>"
case .label(let l): return "<label \(l)>"
case .call(let f): return "<call \(f)>"
case .ret: return "<ret>"
case .save(let restoringAt): return "<save restoringAt: \(restoringAt)>"
case .commit(let continuingAt): return "<commit continuingAt: \(continuingAt)>"
case .startCapture: return "<startCapture>"
case .endCapture: return "<endCapture>"
case .accept: return "<accept>"
case .fail: return "<fail>"
case .abort: return "<abort>"
case .comment(let s): return "/* \(s) */"
}
}
}
extension PEG.VM.Code.Function: CustomStringConvertible {
var description: String {
instructions.indices.reduce("Instructions:\n") { result, idx in
result + "\(instructions.formatInstruction(idx, atCurrent: false, depth: 3))\n"
}
}
}
extension PEG.VM.Code.Instruction {
var label: LabelId? {
switch self {
case .branch(let l): return l
case .condBranch(_, let l): return l
case .save(let l): return l
case .commit(let l): return l
case .label(let l): return l
default: return nil
}
}
}
extension PEG.VM.Code: CustomStringConvertible {
var description: String {
"\(functions)"
}
}
|