func emitConcatenation()

in Sources/VariadicsGenerator/VariadicsGenerator.swift [208:275]


  func emitConcatenation(permutation: Permutation) {
    let arity = permutation.arity

    func emitGenericParameters(withConstraints: Bool) {
      outputForEach(0..<arity, separator: ", ") {
        var base = "T\($0)"
        if withConstraints {
          base += ": \(patternProtocolName)"
        }
        return base
      }
    }

    // Emit concatenation type declarations.
    //   public struct Concatenation{n}_{perm}<...>: RegexProtocol {
    //     public typealias Match = ...
    //     public let regex: Regex<Match>
    //     public init(...) { ... }
    //   }
    let typeName =
      "\(concatenationStructTypeBaseName)\(arity)_\(permutation.identifier)"
    output("public struct \(typeName)<\n  ")
    emitGenericParameters(withConstraints: true)
    output("\n>: \(patternProtocolName)")
    if permutation.hasCaptureless {
      output(" where ")
      outputForEach(permutation.capturelessIndices, separator: ", ") {
        "T\($0).\(matchAssociatedTypeName).\(captureAssociatedTypeName): \(emptyProtocolName)"
      }
    }
    output(" {\n")
    let captureIndices = permutation.captureIndices
    output("  public typealias \(matchAssociatedTypeName) = ")
    let captureElements = captureIndices
      .map { "T\($0).\(matchAssociatedTypeName).\(captureAssociatedTypeName)" }
    if captureElements.isEmpty {
      output(baseMatchTypeName)
    } else {
      let count = captureElements.count + 1
      output("Tuple\(count)<\(baseMatchTypeName), \(captureElements.joined(separator: ", "))>")
    }
    output("\n")
    output("  public let \(patternProtocolRequirementName): \(PatternTypeBaseName)<\(matchAssociatedTypeName)>\n")
    output("  init(")
    outputForEach(0..<arity, separator: ", ") { "_ x\($0): T\($0)" }
    output(") {\n")
    output("    \(patternProtocolRequirementName) = .init(ast: concat(\n      ")
    outputForEach(
      0..<arity, separator: ", ", lineTerminator: ""
    ) { i in
      "x\(i).\(patternProtocolRequirementName).ast.root"
    }
    output("))\n")
    output("  }\n}\n\n")

    // Emit concatenation builders.
    output("extension \(patternBuilderTypeName) {\n")
    output("  public static func buildBlock<")
    emitGenericParameters(withConstraints: true)
    output(">(\n    ")
    outputForEach(0..<arity, separator: ", ") { "_ x\($0): T\($0)" }
    output("\n  ) -> \(typeName)<")
    emitGenericParameters(withConstraints: false)
    output("> {\n")
    output("    \(typeName)(")
    outputForEach(0..<arity, separator: ", ") { "x\($0)" }
    output(")\n  }\n}\n\n")
  }