|
1 | 1 | # Regex Type and Overview
|
2 | 2 |
|
3 |
| -- Authors: [Michael Ilseman](https://github.com/milseman) |
| 3 | +* Proposal: [SE-0350](0350-regex-type-overview.md) |
| 4 | +* Authors: [Michael Ilseman](https://github.com/milseman) |
| 5 | +* Review Manager: [Ben Cohen](https://github.com/airspeedswift) |
| 6 | +* Status: **Active Review (4 - 28 April 2022)** |
| 7 | +* Implementation: https://github.com/apple/swift-experimental-string-processing |
| 8 | + * Available in nightly toolchain snapshots with `import _StringProcessing` |
4 | 9 |
|
5 | 10 | ## Introduction
|
6 | 11 |
|
@@ -207,7 +212,7 @@ func processEntry(_ line: String) -> Transaction? {
|
207 | 212 | // amount: Substring
|
208 | 213 | // )>
|
209 | 214 |
|
210 |
| - guard let match = regex.matchWhole(line), |
| 215 | + guard let match = regex.wholeMatch(line), |
211 | 216 | let kind = Transaction.Kind(match.kind),
|
212 | 217 | let date = try? Date(String(match.date), strategy: dateParser),
|
213 | 218 | let amount = try? Decimal(String(match.amount), format: decimalParser)
|
@@ -384,21 +389,25 @@ extension Regex.Match {
|
384 | 389 | // Run-time compilation interfaces
|
385 | 390 | extension Regex {
|
386 | 391 | /// Parse and compile `pattern`, resulting in a strongly-typed capture list.
|
387 |
| - public init(compiling pattern: String, as: Output.Type = Output.self) throws |
| 392 | + public init(_ pattern: String, as: Output.Type = Output.self) throws |
388 | 393 | }
|
389 | 394 | extension Regex where Output == AnyRegexOutput {
|
390 | 395 | /// Parse and compile `pattern`, resulting in an existentially-typed capture list.
|
391 |
| - public init(compiling pattern: String) throws |
| 396 | + public init(_ pattern: String) throws |
392 | 397 | }
|
393 | 398 | ```
|
394 | 399 |
|
| 400 | +### Cancellation |
| 401 | + |
| 402 | +Regex is somewhat different from existing standard library operations in that regex processing can be a long-running task. |
| 403 | +For this reason regex algorithms may check if the parent task has been cancelled and end execution. |
| 404 | + |
395 | 405 | ### On severability and related proposals
|
396 | 406 |
|
397 | 407 | The proposal split presented is meant to aid focused discussion, while acknowledging that each is interconnected. The boundaries between them are not completely cut-and-dry and could be refined as they enter proposal phase.
|
398 | 408 |
|
399 | 409 | Accepting this proposal in no way implies that all related proposals must be accepted. They are severable and each should stand on their own merit.
|
400 | 410 |
|
401 |
| - |
402 | 411 | ## Source compatibility
|
403 | 412 |
|
404 | 413 | Everything in this proposal is additive. Regex delimiters may have their own source compatibility impact, which is discussed in that proposal.
|
@@ -488,6 +497,16 @@ The generic parameter `Output` is proposed to contain both the whole match (the
|
488 | 497 |
|
489 | 498 | The biggest issue with this alternative design is that the numbering of `Captures` elements misaligns with the numbering of captures in textual regexes, where backreference `\0` refers to the entire match and captures start at `\1`. This design would sacrifice familarity and have the pitfall of introducing off-by-one errors.
|
490 | 499 |
|
| 500 | +### Encoding `Regex`es into the type system |
| 501 | + |
| 502 | +During the initial review period the following comment was made: |
| 503 | + |
| 504 | +> I think the goal should be that, at least for regex literals (and hopefully for the DSL to some extent), one day we might not even need a bytecode or interpreter. I think the ideal case is if each literal was its own function or type that gets generated and optimised as if you wrote it in Swift. |
| 505 | +
|
| 506 | +This is an approach that has been tried a few times in a few different languages (including by a few members of the Swift Standard Library and Core teams), and while it can produce attractive microbenchmarks, it has almost always proved to be a bad idea at the macro scale. In particular, even if we set aside witness tables and other associated swift generics overhead, optimizing a fixed pipeline for each pattern you want to match causes significant codesize expansion when there are multiple patterns in use, as compared to a more flexible byte code interpreter. A bytecode interpreter makes better use of instruction caches and memory, and can also benefit from micro architectural resources that are shared across different patterns. There is a tradeoff w.r.t. branch prediction resources, where separately compiled patterns may have more decisive branch history data, but a shared bytecode engine has much more data to use; this tradeoff tends to fall on the side of a bytecode engine, but it does not always do so. |
| 507 | + |
| 508 | +It should also be noted that nothing prevents AOT or JIT compiling of the bytecode if we believe it will be advantageous, but compiling or interpreting arbitrary Swift code at runtime is rather more unattractive, since both the type system and language are undecidable. Even absent this rationale, we would probably not encode regex programs directly into the type system simply because it is unnecessarily complex. |
| 509 | + |
491 | 510 | ### Future work: static optimization and compilation
|
492 | 511 |
|
493 | 512 | Swift's support for static compilation is still developing, and future work here is leveraging that to compile regex when profitable. Many regex describe simple [DFAs](https://en.wikipedia.org/wiki/Deterministic_finite_automaton) and can be statically compiled into very efficient programs. Full static compilation needs to be balanced with code size concerns, as a matching-specific bytecode is typically far smaller than a corresponding program (especially since the bytecode interpreter is shared).
|
@@ -551,4 +570,4 @@ Regexes are often used for tokenization and tokens can be represented with Swift
|
551 | 570 |
|
552 | 571 | -->
|
553 | 572 |
|
554 |
| -[pitches]: https://github.com/apple/swift-experimental-string-processing/blob/main/Documentation/Evolution/ProposalOverview.md |
| 573 | +[pitches]: https://github.com/apple/swift-experimental-string-processing/blob/main/Documentation/Evolution/ProposalOverview.md |
0 commit comments