//===--- 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' % 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} : IntervalType, Equatable, Printable, DebugPrintable, Reflectable { /// The type of the `Interval`\ 's endpoints 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 } /// 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}(\(toDebugString(start))${rangeOperator}\(toDebugString(end)))" } /// Returns `true` iff the `Interval` contains `x` public func contains(x: Bound) -> Bool { return x >= start && x ${upperBoundCompare} end } /// Return `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) } var _start: T var _end: T } /// 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: T, end: T) -> HalfOpenInterval { return HalfOpenInterval(start, end) } /// Returns a closed interval from `start` through `end` public func ... (start: T, end: T) -> 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') struct _IntervalMirror>: MirrorType { ${Boilerplate} var count: Int { return 2 } 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") } } var summary: String { return _value.description } var quickLookObject: QuickLookObject? { return .Some(.Text(summary)) } }