252 lines
9.1 KiB
Swift

//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2022-2023 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
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
@available(FoundationPredicate 0.1, *)
extension PredicateExpressions {
public struct SequenceContains<
LHS : PredicateExpression,
RHS : PredicateExpression
> : PredicateExpression
where
LHS.Output : Sequence,
LHS.Output.Element : Equatable,
RHS.Output == LHS.Output.Element
{
public typealias Output = Bool
public let sequence: LHS
public let element: RHS
public init(sequence: LHS, element: RHS) {
self.sequence = sequence
self.element = element
}
public func evaluate(_ bindings: PredicateBindings) throws -> Bool {
let a = try sequence.evaluate(bindings)
let b = try element.evaluate(bindings)
return a.contains(b)
}
}
public struct SequenceContainsWhere<
LHS : PredicateExpression,
RHS : PredicateExpression
> : PredicateExpression
where
LHS.Output : Sequence,
RHS.Output == Bool
{
public typealias Element = LHS.Output.Element
public typealias Output = Bool
public let sequence: LHS
public let test: RHS
public let variable: Variable<Element>
public init(_ sequence: LHS, builder: (Variable<Element>) -> RHS) {
self.variable = Variable()
self.sequence = sequence
self.test = builder(variable)
}
public func evaluate(_ bindings: PredicateBindings) throws -> Output {
var mutableBindings = bindings
return try sequence.evaluate(bindings).contains {
mutableBindings[variable] = $0
return try test.evaluate(mutableBindings)
}
}
}
public struct SequenceAllSatisfy<
LHS : PredicateExpression,
RHS : PredicateExpression
> : PredicateExpression
where
LHS.Output : Sequence,
RHS.Output == Bool
{
public typealias Element = LHS.Output.Element
public typealias Output = Bool
public let sequence: LHS
public let test: RHS
public let variable: Variable<Element>
public init(_ sequence: LHS, builder: (Variable<Element>) -> RHS) {
self.variable = Variable()
self.sequence = sequence
self.test = builder(variable)
}
public func evaluate(_ bindings: PredicateBindings) throws -> Output {
var mutableBindings = bindings
return try sequence.evaluate(bindings).allSatisfy {
mutableBindings[variable] = $0
return try test.evaluate(mutableBindings)
}
}
}
public struct SequenceStartsWith<
Base : PredicateExpression,
Prefix : PredicateExpression
> : PredicateExpression
where
Base.Output : Sequence,
Prefix.Output : Sequence,
Base.Output.Element == Prefix.Output.Element,
Base.Output.Element : Equatable
{
public typealias Output = Bool
public let base: Base
public let prefix: Prefix
public init(base: Base, prefix: Prefix) {
self.base = base
self.prefix = prefix
}
public func evaluate(_ bindings: PredicateBindings) throws -> Bool {
try base.evaluate(bindings).starts(with: try prefix.evaluate(bindings))
}
}
@_disfavoredOverload
public static func build_contains<LHS, RHS>(_ lhs: LHS, _ rhs: RHS) -> SequenceContains<LHS, RHS> {
SequenceContains(sequence: lhs, element: rhs)
}
public static func build_contains<LHS, RHS>(_ lhs: LHS, where builder: (Variable<LHS.Output.Element>) -> RHS) -> SequenceContainsWhere<LHS, RHS> {
SequenceContainsWhere(lhs, builder: builder)
}
public static func build_allSatisfy<LHS, RHS>(_ lhs: LHS, _ builder: (Variable<LHS.Output.Element>) -> RHS) -> SequenceAllSatisfy<LHS, RHS> {
SequenceAllSatisfy(lhs, builder: builder)
}
public static func build_starts<Base, Prefix>(_ base: Base, with prefix: Prefix) -> SequenceStartsWith<Base, Prefix> {
SequenceStartsWith(base: base, prefix: prefix)
}
}
@available(FoundationPredicate 0.3, *)
extension PredicateExpressions.SequenceContains : CustomStringConvertible {
public var description: String {
"SequenceContains(sequence: \(sequence), element: \(element))"
}
}
@available(FoundationPredicate 0.3, *)
extension PredicateExpressions.SequenceContainsWhere : CustomStringConvertible {
public var description: String {
"SequenceContainsWhere(sequence: \(sequence), variable: \(variable), test: \(test))"
}
}
@available(FoundationPredicate 0.3, *)
extension PredicateExpressions.SequenceAllSatisfy : CustomStringConvertible {
public var description: String {
"SequenceAllSatisfy(sequence: \(sequence), variable: \(variable), test: \(test))"
}
}
@available(FoundationPredicate 0.1, *)
extension PredicateExpressions.SequenceContains : StandardPredicateExpression where LHS : StandardPredicateExpression, RHS : StandardPredicateExpression {}
@available(FoundationPredicate 0.1, *)
extension PredicateExpressions.SequenceContainsWhere : StandardPredicateExpression where LHS : StandardPredicateExpression, RHS : StandardPredicateExpression {}
@available(FoundationPredicate 0.1, *)
extension PredicateExpressions.SequenceAllSatisfy : StandardPredicateExpression where LHS : StandardPredicateExpression, RHS : StandardPredicateExpression {}
@available(FoundationPredicate 0.1, *)
extension PredicateExpressions.SequenceStartsWith : StandardPredicateExpression where Base : StandardPredicateExpression, Prefix : StandardPredicateExpression {}
@available(FoundationPredicate 0.1, *)
extension PredicateExpressions.SequenceContains : Codable where LHS : Codable, RHS : Codable {
public func encode(to encoder: Encoder) throws {
var container = encoder.unkeyedContainer()
try container.encode(sequence)
try container.encode(element)
}
public init(from decoder: Decoder) throws {
var container = try decoder.unkeyedContainer()
sequence = try container.decode(LHS.self)
element = try container.decode(RHS.self)
}
}
@available(FoundationPredicate 0.1, *)
extension PredicateExpressions.SequenceContainsWhere : Codable where LHS : Codable, RHS : Codable {
public func encode(to encoder: Encoder) throws {
var container = encoder.unkeyedContainer()
try container.encode(sequence)
try container.encode(test)
try container.encode(variable)
}
public init(from decoder: Decoder) throws {
var container = try decoder.unkeyedContainer()
sequence = try container.decode(LHS.self)
test = try container.decode(RHS.self)
variable = try container.decode(PredicateExpressions.Variable<Element>.self)
}
}
@available(FoundationPredicate 0.1, *)
extension PredicateExpressions.SequenceAllSatisfy : Codable where LHS : Codable, RHS : Codable {
public func encode(to encoder: Encoder) throws {
var container = encoder.unkeyedContainer()
try container.encode(sequence)
try container.encode(test)
try container.encode(variable)
}
public init(from decoder: Decoder) throws {
var container = try decoder.unkeyedContainer()
sequence = try container.decode(LHS.self)
test = try container.decode(RHS.self)
variable = try container.decode(PredicateExpressions.Variable<Element>.self)
}
}
@available(FoundationPredicate 0.1, *)
extension PredicateExpressions.SequenceStartsWith : Codable where Base : Codable, Prefix : Codable {
public func encode(to encoder: Encoder) throws {
var container = encoder.unkeyedContainer()
try container.encode(base)
try container.encode(prefix)
}
public init(from decoder: Decoder) throws {
var container = try decoder.unkeyedContainer()
self.base = try container.decode(Base.self)
self.prefix = try container.decode(Prefix.self)
}
}
@available(FoundationPredicate 0.1, *)
extension PredicateExpressions.SequenceContains : Sendable where LHS : Sendable, RHS : Sendable {}
@available(FoundationPredicate 0.1, *)
extension PredicateExpressions.SequenceContainsWhere : Sendable where LHS : Sendable, RHS : Sendable {}
@available(FoundationPredicate 0.1, *)
extension PredicateExpressions.SequenceAllSatisfy : Sendable where LHS : Sendable, RHS : Sendable {}
@available(FoundationPredicate 0.1, *)
extension PredicateExpressions.SequenceStartsWith : Sendable where Base : Sendable, Prefix : Sendable {}