Skip to content

Commit 53d1ce2

Browse files
committed
Create Prototypes target for our prototypes
1 parent e417253 commit 53d1ce2

File tree

18 files changed

+285
-18
lines changed

18 files changed

+285
-18
lines changed

Package.swift

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ let package = Package(
1111
name: "_StringProcessing",
1212
targets: ["_StringProcessing"]),
1313
.library(
14-
name: "PEG",
15-
targets: ["PEG"]),
14+
name: "Prototypes",
15+
targets: ["Prototypes"]),
1616
.library(
1717
name: "_MatchingEngine",
1818
targets: ["_MatchingEngine"]),
@@ -45,20 +45,17 @@ let package = Package(
4545
name: "RegexDSLTests",
4646
dependencies: ["_StringProcessing"]),
4747
.target(
48-
name: "PEG",
48+
name: "Prototypes",
4949
dependencies: ["_MatchingEngine"]),
5050
.testTarget(
5151
name: "PEGTests",
52-
dependencies: ["PEG"]),
53-
.target(
54-
name: "PTCaRet",
55-
dependencies: ["_MatchingEngine"]),
52+
dependencies: ["Prototypes"]),
5653
.testTarget(
5754
name: "PTCaRetTests",
58-
dependencies: ["PTCaRet"]),
55+
dependencies: ["Prototypes"]),
5956
.target(
6057
name: "Algorithms",
61-
dependencies: ["_StringProcessing", "PEG"]),
58+
dependencies: ["_StringProcessing", "Prototypes"]),
6259
.testTarget(
6360
name: "AlgorithmsTests",
6461
dependencies: ["Algorithms"]),
@@ -73,12 +70,10 @@ let package = Package(
7370
// MARK: Exercises
7471
.target(
7572
name: "Exercises",
76-
dependencies: ["_MatchingEngine", "PEG", "PTCaRet", "_StringProcessing"]),
73+
dependencies: ["_MatchingEngine", "Prototypes", "_StringProcessing"]),
7774
.testTarget(
7875
name: "ExercisesTests",
7976
dependencies: ["Exercises"]),
80-
81-
8277
]
8378
)
8479

Sources/Exercises/Participants/PEGParticipant.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ struct PEGParticipant: Participant {
22
static var name: String { "PEG" }
33
}
44

5-
import PEG
5+
import Prototypes
66
private func graphemeBreakPropertyData(forLine line: String) -> GraphemeBreakEntry? {
77
typealias Pattern = PEG<Character>.Pattern
88

Sources/Combinators/Combinators.swift renamed to Sources/Prototypes/Combinators/Combinators.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ extension Combinators.BindElement.BindPosition.BindError {
3333
public struct Parser<T: Hashable> {
3434
let apply: (Position) throws -> ParseResult<T>
3535

36-
public init(_ f: @escaping (Position) throws -> ParseResult<T>) {
36+
init(_ f: @escaping (Position) throws -> ParseResult<T>) {
3737
self.apply = f
3838
}
3939
}
@@ -88,8 +88,8 @@ extension
8888

8989
// Combinators
9090
extension Combinators.BindElement.BindPosition.BindError.Parser {
91-
typealias Parser = Combinators.BindElement<Element>.BindPosition<Position>.BindError<Err>.Parser
92-
typealias ParseResult = Combinators.BindElement<Element>.BindPosition<Position>.BindError<Err>.ParseResult
91+
public typealias Parser = Combinators.BindElement<Element>.BindPosition<Position>.BindError<Err>.Parser
92+
public typealias ParseResult = Combinators.BindElement<Element>.BindPosition<Position>.BindError<Err>.ParseResult
9393

9494
// Backtracking alternation
9595
public func or(_ rhs: Self) -> Self {
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
// MARK: - Element Consumer
2+
3+
/// An alternate formation of consumers: Don't bind collection type as we're just
4+
/// consuming elements by classification or literal sequencing.
5+
protocol ElementConsumer {
6+
associatedtype Element
7+
func consume<C: Collection>(
8+
_ c: C, in: Range<C.Index>
9+
) -> C.Index? where C.Element == Element
10+
}
11+
12+
protocol CharacterConsumer: ElementConsumer
13+
where Element == Character { }
14+
15+
protocol ScalarConsumer: ElementConsumer
16+
where Element == Unicode.Scalar { }
17+
18+
protocol UTF8Consumer: ElementConsumer
19+
where Element == UInt8 { }
20+
21+
protocol UTF16Consumer: ElementConsumer
22+
where Element == UInt16 { }
23+
24+
// struct ...LiteralSequence: ...Consumer { ... }
25+
26+
// MARK: - Element Classes
27+
28+
protocol ElementClass: ElementConsumer {
29+
func contains(_ e: Element) -> Bool
30+
}
31+
extension ElementClass {
32+
func consume<C: Collection>(
33+
_ c: C, in range: Range<C.Index>
34+
) -> C.Index? where C.Element == Element {
35+
// FIXME: empty ranges, etc...
36+
let lower = range.lowerBound
37+
return contains(c[lower]) ? c.index(after: lower) : nil
38+
}
39+
}
40+
41+
protocol ScalarClass: ElementClass, ScalarConsumer {}
42+
protocol CharacterClass: ElementClass, CharacterConsumer {}
43+
44+
// MARK: Granularity adapters
45+
46+
/// Any higher-granularity consumer can be a lower-granularity
47+
/// consumer by just consuming at its higher-granularity
48+
struct _CharacterToScalar <
49+
Characters: CharacterConsumer
50+
>: ScalarConsumer {
51+
var characters: Characters
52+
53+
func consume<C: Collection>(
54+
_ c: C, in range: Range<C.Index>
55+
) -> C.Index? where C.Element == Unicode.Scalar {
56+
let str = String(c)
57+
let r = c.convertByOffset(range, in: str)
58+
guard let idx = characters.consume(str, in: r) else {
59+
return nil
60+
}
61+
62+
return str.convertByOffset(idx, in: c)
63+
}
64+
}
65+
// ...
66+
67+
/// Any lower-granularity consumer can be a higher
68+
/// granularity consumer by checking if the result falls on a
69+
/// boundary.
70+
struct _ScalarToCharacter <
71+
Scalars: ScalarConsumer
72+
>: CharacterConsumer {
73+
var scalars: Scalars
74+
75+
func _consume(
76+
_ str: String, in range: Range<String.Index>
77+
) -> String.Index? {
78+
guard let idx = scalars.consume(str.unicodeScalars, in: range),
79+
str.isOnGraphemeClusterBoundary(idx)
80+
else {
81+
return nil
82+
}
83+
return idx
84+
}
85+
86+
func consume<C: Collection>(
87+
_ c: C, in range: Range<C.Index>
88+
) -> C.Index? where C.Element == Character {
89+
let str = String(c)
90+
let r = c.convertByOffset(range, in: str)
91+
92+
guard let idx = _consume(str, in: r) else {
93+
return nil
94+
}
95+
return str.convertByOffset(idx, in: c)
96+
}
97+
}
98+
99+
/// Any lower-granularity class can be a higher-granularity
100+
/// class if we choose a semantic-extension style
101+
struct _FirstScalarCharacters<
102+
Scalars: ScalarClass
103+
>: CharacterClass {
104+
var scalars: Scalars
105+
func contains(_ c: Character) -> Bool {
106+
scalars.contains(c.unicodeScalars.first!)
107+
}
108+
}
109+
struct _SingleScalarCharacters<
110+
Scalars: ScalarClass
111+
>: CharacterClass {
112+
var scalars: Scalars
113+
func contains(_ c: Character) -> Bool {
114+
let scs = c.unicodeScalars
115+
return scs.count == 1 && scalars.contains(scs.first!)
116+
}
117+
// NOTE: This would be equivalent to _ScalarToCharacter
118+
// for any scalar consumer that consumes only one scalar
119+
// at a time.
120+
}
121+
struct _AllScalarCharacters<
122+
Scalars: ScalarClass
123+
>: CharacterClass {
124+
var scalars: Scalars
125+
func contains(_ c: Character) -> Bool {
126+
c.unicodeScalars.allSatisfy(scalars.contains)
127+
}
128+
}
129+
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
// MARK: - Pitched Compiler/library interface
2+
3+
/// Conform to this to support regex literals
4+
protocol ExpressibleByRegexLiteral {
5+
associatedtype Builder: RegexLiteralBuilderProtocol
6+
init(builder: Builder)
7+
}
8+
9+
/// Builder conforms to this for compiler-library API
10+
protocol RegexLiteralBuilderProtocol {
11+
/// Opaquely identify something built
12+
associatedtype ASTNodeId = UInt
13+
14+
/// NOTE: This will likely not be a requirement but could be ad-hoc name lookup
15+
mutating func buildCharacterClass_d() -> ASTNodeId
16+
17+
/// Any post-processing or partial compilation
18+
///
19+
/// NOTE: we might want to make this `throws`, capable of communicating
20+
/// compilation failure if conformer is constant evaluable.
21+
mutating func finalize()
22+
}
23+
24+
/*
25+
26+
TODO: We will probably want defaulting mechanisms, such as:
27+
28+
* Ability for a conformer to take a meta-character as
29+
just an escaped character
30+
* Ability for a conformer to use function decls for feature
31+
set communication alone, and have default impl build just
32+
echo the string for an engine
33+
34+
*/
35+
36+
// MARK: - Semantic levels
37+
38+
/// Dynamic notion of a specified semantics level for a regex
39+
enum SemanticsLevel {
40+
case graphemeCluster
41+
case scalar
42+
case posix // different than ASCII?
43+
// ... code units ...
44+
}
45+
46+
/// Conformers can be ran as a regex / pattern
47+
protocol RegexProtocol {
48+
var level: SemanticsLevel? { get }
49+
}
50+
51+
/// Provide the option to encode semantic level statically
52+
protocol RegexLiteralProtocol: ExpressibleByRegexLiteral {
53+
associatedtype ScalarSemanticRegex: RegexProtocol
54+
associatedtype GraphemeSemanticRegex: RegexProtocol
55+
associatedtype POSIXSemanticRegex: RegexProtocol
56+
associatedtype UnspecifiedSemanticRegex: RegexProtocol = RegexLiteral
57+
58+
var scalarSemantic: ScalarSemanticRegex { get }
59+
var graphemeSemantic: GraphemeSemanticRegex { get }
60+
var posixSemantic: POSIXSemanticRegex { get }
61+
}
62+
63+
// MARK: - Statically encoded semantic level
64+
65+
/// A regex that has statically bound its semantic level
66+
struct StaticSemanticRegexLiteral: RegexLiteralProtocol {
67+
/*
68+
If we had values in type-parameter position, this would be
69+
far easier and more straight-forward to model.
70+
71+
RegexLiteral<SemanticsLevel? = nil>
72+
73+
*/
74+
75+
/// A regex that has statically bound its semantic level
76+
struct ScalarSemanticRegex: RegexProtocol {
77+
var level: SemanticsLevel? { .scalar }
78+
}
79+
struct GraphemeSemanticRegex: RegexProtocol {
80+
var level: SemanticsLevel? { .graphemeCluster }
81+
}
82+
struct POSIXSemanticRegex: RegexProtocol {
83+
var level: SemanticsLevel? { .posix }
84+
}
85+
struct UnspecifiedSemanticRegex: RegexProtocol {
86+
var level: SemanticsLevel? { nil }
87+
}
88+
89+
var scalarSemantic: ScalarSemanticRegex { x() }
90+
var graphemeSemantic: GraphemeSemanticRegex { x() }
91+
var posixSemantic: POSIXSemanticRegex { x() }
92+
93+
init(builder: RegexLiteralBuilder) { }
94+
95+
typealias Builder = RegexLiteralBuilder
96+
}
97+
98+
// MARK: - stdlib conformer
99+
100+
/// Stdlib's conformer
101+
struct RegexLiteralBuilder: RegexLiteralBuilderProtocol {
102+
/// Compiler converts literal into a series of calls to this kind of method
103+
mutating func buildCharacterClass_d() -> ASTNodeId { x() }
104+
105+
/// We're done, so partially-compile or otherwise finalize
106+
mutating func finalize() { }
107+
}
108+
109+
110+
/// The produced value for a regex literal. Might end up being same type as
111+
/// `Regex` or `Pattern`, but for now useful to model independently.
112+
struct RegexLiteral: ExpressibleByRegexLiteral {
113+
typealias Builder = RegexLiteralBuilder
114+
115+
/// An explicitly specified semantics level
116+
var level: SemanticsLevel? = nil
117+
118+
init(builder: Builder) {
119+
// TODO: should this be throwing, constant evaluable, or
120+
// some other way to issue diagnostics?
121+
}
122+
}
123+
124+
extension RegexLiteral: RegexProtocol, RegexLiteralProtocol {
125+
/// A regex that has finally bound its semantic level (dynamically)
126+
struct BoundSemantic: RegexProtocol {
127+
var _level: SemanticsLevel // Bound semantic level
128+
var level: SemanticsLevel? { _level }
129+
}
130+
private func sem(_ level: SemanticsLevel) -> BoundSemantic {
131+
x()
132+
}
133+
134+
var scalarSemantic: BoundSemantic { sem(.scalar) }
135+
var graphemeSemantic: BoundSemantic { sem(.graphemeCluster) }
136+
var posixSemantic: BoundSemantic { sem(.posix) }
137+
138+
}
139+
140+
141+
// ---
142+
143+
internal func x() -> Never { fatalError() }

Tests/PEGTests/PEGTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import XCTest
2-
@testable import PEG
2+
@testable import Prototypes
33
import _MatchingEngine
44

55
// Make examples more sane. Need builder

Tests/PTCaRetTests/PTCaRetTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import XCTest
2-
@testable import PTCaRet
2+
@testable import Prototypes
33
import _MatchingEngine
44

55
enum Event: UInt64, Hashable {

0 commit comments

Comments
 (0)