Files
swift-mirror/stdlib/public/core/Interval.swift.gyb
Dmitri Hrybenko 82122f9362 stdlib: fixit-based migrations for generic parameter renames
rdar://21538940

Swift SVN r29756
2015-06-27 04:06:27 +00:00

214 lines
6.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
/// Return `rhs` clamped to `self`. The bounds of the result, even
/// if it is empty, are always within the bounds of `self`.
func clamp(intervalToClamp: Self) -> Self
/// `true` iff `self` 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'
%{
selfDocComment = """
/// A half-open `IntervalType`, which contains its `start` but not its
/// `end`. Can represent an empty interval.""" if Kind == 'HalfOpen' else """
/// A closed `IntervalType`, which contains both its `start` and its
/// `end`. Cannot represent an empty interval."""
selfDocComment += """
///
/// - parameter Bound: The type of the endpoints."""
}%
${selfDocComment}
public struct ${Self}<Bound : Comparable>
: IntervalType, Equatable, CustomStringConvertible, CustomDebugStringConvertible, _Reflectable {
@available(*, unavailable, renamed="Bound")
public typealias T = Bound
/// 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: Bound, _ end: Bound) {
_precondition(end >= start, "Invalid ${Self} bounds (end < start)")
_start = start
_end = end
}
/// The `Interval`'s lower bound.
///
/// Invariant: `start` <= `end`.
public var start: Bound {
return _start
}
/// The `Interval`'s upper bound.
///
/// Invariant: `start` <= `end`.
public var end: Bound {
return _end
}
/// A textual representation of `self`.
public var description: String {
return "\(start)${rangeOperator}\(end)"
}
/// A textual representation of `self`, suitable for debugging.
public var debugDescription: String {
return "${Self}(\(String(reflecting: start))${rangeOperator}\(String(reflecting: end)))"
}
/// Returns `true` iff the `Interval` contains `x`.
public func contains(x: Bound) -> Bool {
return x >= start && x ${upperBoundCompare} end
}
/// Returns `intervalToClamp` clamped to `self`.
///
/// The bounds of the result, even if it is empty, are always limited to the bounds of
/// `self`.
public func clamp(intervalToClamp: ${Self}) -> ${Self} {
return ${Self}(
self.start > intervalToClamp.start ? self.start
: self.end < intervalToClamp.start ? self.end
: intervalToClamp.start,
self.end < intervalToClamp.end ? self.end
: self.start > intervalToClamp.end ? self.start
: intervalToClamp.end
)
}
/// Returns a mirror that reflects `self`.
public func getMirror() -> MirrorType {
return _IntervalMirror(self)
}
internal var _start: Bound
internal var _end: Bound
}
/// Two `${Self}`s are equal if their `start` and `end` are equal.
public func == <Bound : Comparable> (
lhs: ${Self}<Bound>, rhs: ${Self}<Bound>
) -> 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 ..< <Bound : Comparable>(
start: Bound, end: Bound
) -> HalfOpenInterval<Bound> {
return HalfOpenInterval(start, end)
}
/// Returns a closed interval from `start` through `end`.
public func ... <Bound : Comparable>(
start: Bound, end: Bound
) -> ClosedInterval<Bound> {
return ClosedInterval(start, end)
}
/// Returns `true` iff `pattern` contains `value`.
public func ~= <I: IntervalType>(pattern: I, value: I.Bound) -> Bool {
return pattern.contains(value)
}
// Reflection support
%import gyb
%TBoilerplate = gyb.parseTemplate("../common/MirrorBoilerplate.gyb")
%Boilerplate = gyb.executeTemplate(TBoilerplate,\
% introspecteeType='T',\
% disposition='Struct')
internal struct _IntervalMirror<
T : protocol<IntervalType, CustomStringConvertible>
> : MirrorType {
${Boilerplate}
internal var count: Int { return 2 }
internal subscript(i: Int) -> (String, MirrorType) {
switch i {
case 0: return ("start", reflect(_value.start))
case 1: return ("end", reflect(_value.end))
default: _preconditionFailure("MirrorType access out of bounds")
}
}
internal var summary: String { return _value.description }
internal var quickLookObject: QuickLookObject? { return .Some(.Text(summary)) }
}