1- // swift run VariadicsGenerator --max-arity 7 > Sources/RegexDSL/Concatenation.swift
1+ // swift run VariadicsGenerator --max-arity 7 > Sources/_StringProcessing/ RegexDSL/Concatenation.swift
22
33import ArgumentParser
44
55struct Permutation {
66 let arity : Int
77 // 1 -> no extra constraint
8- // 0 -> where T.Capture : NoCaptureProtocol
8+ // 0 -> where T.Match : NoCaptureProtocol
99 let bits : Int64
1010
1111 func isCaptureless( at index: Int ) -> Bool {
@@ -77,8 +77,6 @@ func outputForEach<C: Collection>(
7777 if let lt = lineTerminator {
7878 let indent = needsSep ? " " : " "
7979 output ( " \( lt) \n \( indent) " )
80- } else if needsSep {
81- output ( " " )
8280 }
8381 }
8482}
@@ -87,12 +85,13 @@ typealias Counter = Int64
8785let patternProtocolName = " RegexProtocol "
8886let concatenationStructTypeBaseName = " Concatenate "
8987let capturingGroupTypeBaseName = " CapturingGroup "
88+ let matchAssociatedTypeName = " Match "
9089let captureAssociatedTypeName = " Capture "
9190let patternBuilderTypeName = " RegexBuilder "
9291let patternProtocolRequirementName = " regex "
9392let PatternTypeBaseName = " Regex "
94- let emptyProtocolName = " EmptyProtocol "
95- let emptyStructName = " Empty "
93+ let emptyProtocolName = " EmptyCaptureProtocol "
94+ let baseMatchTypeName = " Substring "
9695
9796@main
9897struct VariadicsGenerator : ParsableCommand {
@@ -112,8 +111,13 @@ struct VariadicsGenerator: ParsableCommand {
112111
113112 import _MatchingEngine
114113
114+
115115 """ )
116116
117+ for arity in 2 ... maxArity+ 1 {
118+ emitTupleStruct ( arity: arity)
119+ }
120+
117121 for arity in minArity... maxArity {
118122 for permutation in Permutations ( arity: arity) {
119123 emitConcatenation ( permutation: permutation)
@@ -124,42 +128,121 @@ struct VariadicsGenerator: ParsableCommand {
124128 output ( " // END AUTO-GENERATED CONTENT " )
125129 }
126130
131+ func emitTupleStruct( arity: Int ) {
132+ output ( """
133+ @frozen @dynamicMemberLookup
134+ public struct Tuple \( arity) <
135+ """ )
136+ outputForEach ( 0 ..< arity, separator: " , " ) {
137+ " _ \( $0) "
138+ }
139+ output ( " > { " )
140+ // `public typealias Tuple = (_0, ...)`
141+ output ( " \n public typealias Tuple = ( " )
142+ outputForEach ( 0 ..< arity, separator: " , " ) { " _ \( $0) " }
143+ output ( " ) " )
144+ // `public var tuple: Tuple`
145+ output ( " \n public var tuple: Tuple \n " )
146+ // `subscript(dynamicMember:)`
147+ output ( """
148+ public subscript<T>(dynamicMember keyPath: WritableKeyPath<Tuple, T>) -> T {
149+ get { tuple[keyPath: keyPath] }
150+ _modify { yield &tuple[keyPath: keyPath] }
151+ }
152+ """ )
153+ output ( " \n } \n " )
154+ output ( " extension Tuple \( arity) : \( emptyProtocolName) where " )
155+ outputForEach ( 1 ..< arity, separator: " , " ) {
156+ " _ \( $0) : \( emptyProtocolName) "
157+ }
158+ output ( " {} \n " )
159+ output ( " extension Tuple \( arity) : MatchProtocol { \n " )
160+ output ( " public typealias Capture = " )
161+ if arity == 2 {
162+ output ( " _1 " )
163+ } else {
164+ output ( " Tuple \( arity- 1 ) < " )
165+ outputForEach ( 1 ..< arity, separator: " , " ) {
166+ " _ \( $0) "
167+ }
168+ output ( " > " )
169+ }
170+ output ( " \n public init(_ tuple: Tuple) { self.tuple = tuple } " )
171+ // `public init(_0: _0, ...) { ... }`
172+ output ( " \n public init( " )
173+ outputForEach ( 0 ..< arity, separator: " , " ) {
174+ " _ _ \( $0) : _ \( $0) "
175+ }
176+ output ( " ) { \n " )
177+ output ( " self.init(( " )
178+ outputForEach ( 0 ..< arity, separator: " , " ) { " _ \( $0) " }
179+ output ( " )) \n " )
180+ output ( " } " )
181+ output ( " \n } \n " )
182+ // Equatable
183+ output ( " extension Tuple \( arity) : Equatable where " )
184+ outputForEach ( 0 ..< arity, separator: " , " ) {
185+ " _ \( $0) : Equatable "
186+ }
187+ output ( " { \n " )
188+ output ( " public static func == (lhs: Self, rhs: Self) -> Bool { \n " )
189+ output ( " " )
190+ outputForEach ( 0 ..< arity, separator: " && " ) {
191+ " lhs.tuple. \( $0) == rhs.tuple. \( $0) "
192+ }
193+ output ( " \n } \n " )
194+ output ( " } \n " )
195+ }
196+
127197 func emitConcatenation( permutation: Permutation ) {
128198 let arity = permutation. arity
199+
200+ func emitGenericParameters( withConstraints: Bool ) {
201+ outputForEach ( 0 ..< arity, separator: " , " ) {
202+ var base = " T \( $0) "
203+ if withConstraints {
204+ base += " : \( patternProtocolName) "
205+ }
206+ return base
207+ }
208+ }
209+
129210 // Emit concatenation type declarations.
130211 // public struct Concatenation{n}_{perm}<...>: RegexProtocol {
131- // public typealias Capture = ...
132- // public let regex: Regex
212+ // public typealias Match = ...
213+ // public let regex: Regex<Match>
133214 // public init(...) { ... }
134215 // }
135- let typeName = " \( concatenationStructTypeBaseName) \( arity) _ \( permutation. identifier) "
216+ let typeName =
217+ " \( concatenationStructTypeBaseName) \( arity) _ \( permutation. identifier) "
136218 output ( " public struct \( typeName) < \n " )
137- outputForEach ( 0 ..< arity , separator : " , " ) { " T \( $0 ) : \( patternProtocolName ) " }
219+ emitGenericParameters ( withConstraints : true )
138220 output ( " \n >: \( patternProtocolName) " )
139221 if permutation. hasCaptureless {
140222 output ( " where " )
141- outputForEach ( permutation. capturelessIndices, separator: " , " ) {
142- " T \( $0) . \( captureAssociatedTypeName) : \( emptyProtocolName) "
223+ outputForEach ( permutation. capturelessIndices, separator: " , " ) {
224+ " T \( $0) . \( matchAssociatedTypeName ) . \( captureAssociatedTypeName) : \( emptyProtocolName) "
143225 }
144226 }
145227 output ( " { \n " )
146228 let captureIndices = permutation. captureIndices
147- output ( " public typealias \( captureAssociatedTypeName ) = " )
229+ output ( " public typealias \( matchAssociatedTypeName ) = " )
148230 let captureElements = captureIndices
149- . map { " T \( $0) . \( captureAssociatedTypeName) " }
231+ . map { " T \( $0) . \( matchAssociatedTypeName ) . \( captureAssociatedTypeName) " }
150232 if captureElements. isEmpty {
151- output ( emptyStructName )
233+ output ( baseMatchTypeName )
152234 } else {
153- output ( " ( \( captureElements. joined ( separator: " , " ) ) ) " )
235+ let count = captureElements. count + 1
236+ output ( " Tuple \( count) < \( baseMatchTypeName) , \( captureElements. joined ( separator: " , " ) ) > " )
154237 }
155238 output ( " \n " )
156- output ( " public let \( patternProtocolRequirementName) : \( PatternTypeBaseName) < \( captureAssociatedTypeName ) > \n " )
239+ output ( " public let \( patternProtocolRequirementName) : \( PatternTypeBaseName) < \( matchAssociatedTypeName ) > \n " )
157240 output ( " init( " )
158- outputForEach ( 0 ..< arity, separator: " , " ) { " _ x \( $0) : T \( $0) " }
241+ outputForEach ( 0 ..< arity, separator: " , " ) { " _ x \( $0) : T \( $0) " }
159242 output ( " ) { \n " )
160243 output ( " \( patternProtocolRequirementName) = .init(ast: concat( \n " )
161244 outputForEach (
162- 0 ..< arity, separator: " , " , lineTerminator: " "
245+ 0 ..< arity, separator: " , " , lineTerminator: " "
163246 ) { i in
164247 " x \( i) . \( patternProtocolRequirementName) .ast "
165248 }
@@ -169,14 +252,14 @@ struct VariadicsGenerator: ParsableCommand {
169252 // Emit concatenation builders.
170253 output ( " extension \( patternBuilderTypeName) { \n " )
171254 output ( " public static func buildBlock< " )
172- outputForEach ( 0 ..< arity , separator : " , " ) { " T \( $0 ) " }
255+ emitGenericParameters ( withConstraints : true )
173256 output ( " >( \n " )
174- outputForEach ( 0 ..< arity, separator: " , " ) { " _ x \( $0) : T \( $0) " }
257+ outputForEach ( 0 ..< arity, separator: " , " ) { " _ x \( $0) : T \( $0) " }
175258 output ( " \n ) -> \( typeName) < " )
176- outputForEach ( 0 ..< arity , separator : " , " ) { " T \( $0 ) " }
259+ emitGenericParameters ( withConstraints : false )
177260 output ( " > { \n " )
178261 output ( " \( typeName) ( " )
179- outputForEach ( 0 ..< arity, separator: " , " ) { " x \( $0) " }
262+ outputForEach ( 0 ..< arity, separator: " , " ) { " x \( $0) " }
180263 output ( " ) \n } \n } \n \n " )
181264 }
182265}
0 commit comments