protocol _Collection { typealias IndexType : ForwardIndex func startIndex() -> IndexType func endIndex() -> IndexType // The declaration of Element and _subscript here is a trick used to // break a cyclic conformance/deduction that Swift can't handle. We // need something other than a Collection.StreamType.Element that can // be used as ContainedStream's Element. Here we arrange for the // Collection itself to have an Element type that's deducible from // its __getitem__ function. Ideally we'd like to constrain this // Element to be the same as Collection.StreamType.Element (see // below), but we have no way of expressing it today. typealias _Element func __getitem__(i: IndexType) -> _Element } protocol Collection : _Collection, Sequence { func __getitem__(i: IndexType) -> StreamType.Element } /// \brief A stream type that could serve for a Collection given that /// it already had an IndexType. Because of /// we've had to factor _Collection out of Collection to make it useful struct ContainedStream : Stream { init(seq: C) { self._elements = seq self._position = seq.startIndex() } func generate() -> ContainedStream { return self } @mutating func next() -> C._Element? { return _position == _elements.endIndex() ? .None : .Some(_elements.__getitem__(_position++)) } var _elements: C var _position: C.IndexType } func indices< Seq : Collection>(seq: Seq) -> Range { return Range(seq.startIndex(), seq.endIndex()) } struct IndexedStream< Seq: Collection, Indices: Sequence where Seq.IndexType == Indices.StreamType.Element // FIXME: Commenting out "Stream," below causes all kinds of deserialization crashes > : Stream, Sequence, MultiPassStream { var seq : Seq var indices : Indices.StreamType typealias Element = Seq.StreamType.Element @mutating func next() -> Element? { var result = indices.next() return result ? seq.__getitem__(result!) : .None } // Every Stream is also a single-pass Sequence typealias StreamType = IndexedStream func generate() -> StreamType { return self } init(seq: Seq, indices: Indices) { self.seq = seq self.indices = indices.generate() } } /* /// \brief Adapt an Collection into an Sequence struct CollectionSequence : Sequence { var seq : Seq typealias StreamType = ForwardCollectionStream func generate() -> StreamType { return StreamType(self.seq) } init(seq: Seq) { self.seq = seq } } struct ReverseCollection< Seq: Collection where Seq.IndexType: BidirectionalIndex > : Collection { var seq : Seq typealias StreamType = CollectionStream func generate() -> StreamType { return StreamType(self.seq) } init(seq: Seq) { self.seq = seq } } func elements< Seq: Collection>(seq: Seq) -> CollectionSequence { return CollectionSequence(seq) } func reverse< Seq: Collection where Seq.IndexType: BidirectionalIndex >(seq: Seq) -> ReverseCollectionSequence { return ReverseCollectionSequence(seq) } func reverse< Seq: Collection where Seq.IndexType: BidirectionalIndex >(e: CollectionSequence) -> ReverseCollectionSequence { return ReverseCollectionSequence(e.seq) } func reverse< Seq: Collection where Seq.IndexType: BidirectionalIndex >(e: ReverseCollectionSequence) -> CollectionSequence { return CollectionSequence(e.seq) } */ /// \brief A wrapper for a BidirectionalIndex that reverses its /// direction of traversal struct ReverseIndex : BidirectionalIndex { var _base: I func succ() -> ReverseIndex { return ReverseIndex(_base.pred()) } func pred() -> ReverseIndex { return ReverseIndex(_base.succ()) } } func == (lhs: ReverseIndex, rhs: ReverseIndex) -> Bool { return lhs._base == rhs._base } struct Reverse : Collection { typealias IndexType = ReverseIndex typealias StreamType = ContainedStream func generate() -> ContainedStream { return ContainedStream(self) } func startIndex() -> IndexType { return ReverseIndex(_base.endIndex()) } func endIndex() -> IndexType { return ReverseIndex(_base.startIndex()) } func __getitem__(i: IndexType) -> T.StreamType.Element { return _base.__getitem__(i._base.pred()) } var _base: T } protocol Sliceable: Collection { func __slice__(start: IndexType, finish: IndexType) -> Self } func dropFirst(seq: Seq) -> Seq { return seq.__slice__(seq.startIndex().succ(), seq.endIndex()) } func dropLast< Seq: Sliceable where Seq.IndexType: BidirectionalIndex >(seq: Seq) -> Seq { return seq.__slice__(seq.startIndex(), seq.endIndex().pred()) } protocol ForwardIndex : Equatable { func succ() -> Self } @prefix @assignment @transparent func ++ (x: @inout T) -> T { x = x.succ() return x } @postfix @assignment @transparent func ++ (x: @inout T) -> T { var ret = x x = x.succ() return ret } protocol BidirectionalIndex : ForwardIndex { func pred() -> Self } @prefix @assignment @transparent func -- (x: @inout T) -> T { x = x.pred() return x } @postfix @assignment @transparent func -- (x: @inout T) -> T { var ret = x x = x.pred() return ret } protocol RandomAccessIndex : BidirectionalIndex, NumericOperations { typealias DistanceType type func sub(lhs: Self, rhs: Self) -> (DistanceType, Bool) type func sub(lhs: Self, rhs: DistanceType) -> (Self, Bool) type func add(lhs: Self, rhs: DistanceType) -> (Self, Bool) // FIXME: Disabled pending (Default // implementations in protocols) func <(lhs: Self, rhs: Self) -> Bool /* { return (lhs.sub(rhs)).isNegative() } */ } @transparent func - (x: T, y: T) -> T.DistanceType { var tmp : (T.DistanceType, Bool) = T.sub(x, y) alwaysTrap(tmp.1 == false) return tmp.0 } @transparent func &- (x: T, y: T) -> T.DistanceType { return T.sub(x, y).0 } @transparent func - (x: T, y: T.DistanceType) -> T { var tmp = T.sub(x, y) alwaysTrap(tmp.1 == false) return tmp.0 } @transparent func &- (x: T, y: T.DistanceType) -> T { return T.sub(x, y).0 } @infix @assignment @transparent func += (lhs: @inout T, rhs: T.DistanceType) { var tmp = T.add(lhs, rhs) alwaysTrap(tmp.1 == false) lhs = tmp.0 } @infix @assignment @transparent func -= < T: RandomAccessIndex where T.DistanceType: SignedNumber > (lhs: @inout T, rhs: T.DistanceType) { var tmp = T.add(lhs, -rhs) alwaysTrap(tmp.1 == false) lhs = tmp.0 } @transparent func + (lhs: T, rhs: T.DistanceType) -> T { var tmp = T.add(lhs, rhs) alwaysTrap(tmp.1 == false) return tmp.0 } @transparent func + (lhs: T.DistanceType, rhs: T) -> T { var tmp = T.add(rhs, lhs) alwaysTrap(tmp.1 == false) return tmp.0 } @transparent func &+ (lhs: T, rhs: T) -> T { return T.add(lhs, rhs).0 } @transparent func &+ (lhs: T, rhs: T.DistanceType) -> T { return T.add(lhs, rhs).0 } @transparent func &+ (lhs: T.DistanceType, rhs: T) -> T { return T.add(rhs, lhs).0 } @transparent func - ( lhs: T, rhs: T.DistanceType) -> T { var tmp = T.add(lhs, -rhs) alwaysTrap(tmp.1 == false) return tmp.0 } @transparent func &- ( lhs: T, rhs: T.DistanceType) -> T { return T.add(lhs, -rhs).0 }