mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
This allows 0.0..<10.3 and 0.1...4.4 to work properly in pattern matching. Fixes <rdar://problem/12016900> (#Seed 4: add a "contains" method to the range types) by making "contains" available on Interval Addresses <rdar://problem/16254937> (#Seed 4: Ranges with negative strides are broken) by making the formation of an invalid Interval a runtime error. Fixes <rdar://problem/16304317> (Range<T> has limited awesomeness: it is restricted to types that conform to ForwardIndex) Fixes <rdar://problem/16736924> (#Seed 4: Enable range inclusion pattern matching for all types that conform to Equatable and Comparable) Addresses <rdar://problem/16846325> (#Seed 4: Introduce index range) by distinguishing Range (which operates on indices) from Interval Fixes <rdar://problem/17051263> (Pattern-matching a Double range with an infinite endpoint triggers an assertion failure) Fixes <rdar://problem/17051271> (#Seed 4: Pattern-matching Double ranges excludes fractional values) Addresses <rdar://problem/17171420> (Separate types for closed and half-open ranges) Swift SVN r19900
140 lines
4.0 KiB
Swift
140 lines
4.0 KiB
Swift
//===--- Interval.swift.gyb ----------------------------------*- swift -*--===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See http://swift.org/LICENSE.txt for license information
|
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// An interval over a `Comparable` type.
|
|
public protocol IntervalType {
|
|
/// The type of the `Interval`\ 's endpoints
|
|
typealias Bound : Comparable
|
|
|
|
/// Returns `true` iff the interval contains `value`
|
|
func contains(value: Bound) -> Bool
|
|
|
|
/// True iff the `Interval` is empty
|
|
var isEmpty: Bool {get}
|
|
|
|
/// The `Interval`\ 's lower bound. Invariant: `start` <= `end`
|
|
var start: Bound {get}
|
|
/// The `Interval`\ 's upper bound. Invariant: `start` <= `end`
|
|
var end: Bound {get}
|
|
}
|
|
|
|
% for Kind, rangeOperator, upperBoundCompare in [
|
|
% ('HalfOpen', '..<', '<'),
|
|
% ('Closed', '...', '<=')
|
|
% ]:
|
|
% Self = Kind + 'Interval'
|
|
|
|
% if Kind == 'HalfOpen':
|
|
/// A half-open `IntervalType`, which contains its `start` but not its
|
|
/// `end`. Can represent an empty interval.
|
|
% else:
|
|
/// A closed `IntervalType`, which contains both its `start` and its
|
|
/// `end`. Cannot represent an empty interval.
|
|
% end
|
|
public struct ${Self}<T: Comparable>
|
|
: IntervalType, Equatable, Printable, DebugPrintable {
|
|
|
|
public typealias Bound = T
|
|
|
|
|
|
/// Construct a copy of `x`
|
|
public init(_ x: ${Self}) {
|
|
// This initializer exists only so that we can have a descriptive
|
|
// debugDescription that actually constructs the right type.
|
|
self = x
|
|
}
|
|
|
|
/// Construct an interval with the given bounds. Requires: `start`
|
|
/// <= `end`.
|
|
public init(_ start: T, _ end: T) {
|
|
_precondition(end >= start, "Invalid ${Self} bounds (end < start)")
|
|
_start = start
|
|
_end = end
|
|
}
|
|
|
|
/// The `Interval`\ 's lower bound. Invariant: `start` <= `end`
|
|
public var start: T {
|
|
return _start
|
|
}
|
|
|
|
/// The `Interval`\ 's upper bound. Invariant: `start` <= `end`
|
|
public var end: T {
|
|
return _end
|
|
}
|
|
|
|
/// The `Interval`\ 's printed representation
|
|
public var description: String {
|
|
return "\(start)${rangeOperator}\(end)"
|
|
}
|
|
|
|
/// The `Interval`\ "s verbose printed representation
|
|
public var debugDescription: String {
|
|
return "${Self}(\(start)${rangeOperator}\(end))"
|
|
}
|
|
|
|
/// Returns `true` iff the `Interval` contains `x`
|
|
public func contains(x: Bound) -> Bool {
|
|
return x >= start && x ${upperBoundCompare} end
|
|
}
|
|
|
|
var _start: T
|
|
var _end: T
|
|
}
|
|
|
|
/// Two `${Self}`\ s are equal if their `start` and `end` are
|
|
/// equal
|
|
public func == <T: Comparable> (
|
|
lhs: ${Self}<T>, rhs: ${Self}<T>
|
|
) -> Bool {
|
|
return lhs.start == rhs.start && lhs.end == rhs.end
|
|
}
|
|
%end
|
|
|
|
extension HalfOpenInterval {
|
|
/// `true` iff the `Interval` is empty.
|
|
public var isEmpty: Bool {
|
|
return end <= start
|
|
}
|
|
}
|
|
|
|
extension ClosedInterval {
|
|
/// `true` iff the `Interval` is empty. In the case of
|
|
/// `ClosedInterval`, always returns `false`
|
|
public var isEmpty: Bool {
|
|
return false
|
|
}
|
|
}
|
|
|
|
// FIXME: current language limitations don't allow this as a method in
|
|
// the protocol.
|
|
/// Returns `true` if `lhs` and `rhs` have a non-empty intersection
|
|
public func overlaps<
|
|
I0: IntervalType, I1: IntervalType where I0.Bound == I1.Bound
|
|
>(lhs: I0, rhs: I1) -> Bool {
|
|
return lhs.contains(rhs.start) || rhs.contains(lhs.start)
|
|
}
|
|
|
|
/// Returns a half-open interval from `start` to `end`
|
|
public func ..< <T: Comparable>(start: T, end: T) -> HalfOpenInterval<T> {
|
|
return HalfOpenInterval(start, end)
|
|
}
|
|
|
|
/// Returns a closed interval from `start` through `end`
|
|
public func ... <T: Comparable>(start: T, end: T) -> ClosedInterval<T> {
|
|
return ClosedInterval(start, end)
|
|
}
|
|
|
|
/// eturns `true` iff `pattern` contains `value`
|
|
public func ~= <I: IntervalType>(pattern: I, value: I.Bound) -> Bool {
|
|
return pattern.contains(value)
|
|
}
|