//===--- 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} : 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 == ( lhs: ${Self}, rhs: ${Self} ) -> 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 ..< ( start: Bound, end: Bound ) -> HalfOpenInterval { return HalfOpenInterval(start, end) } /// Returns a closed interval from `start` through `end`. public func ... ( start: Bound, end: Bound ) -> ClosedInterval { return ClosedInterval(start, end) } /// Returns `true` iff `pattern` contains `value`. public func ~= (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 > : 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)) } }