Files
swift-mirror/stdlib/public/core/Flatten.swift.gyb
Dave Abrahams 6be395d638 [stdlib] Documentation touch-ups for flatten
Swift SVN r30471
2015-07-21 22:35:39 +00:00

250 lines
7.6 KiB
Plaintext

//===--- Flatten.swift.gyb ------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
/// A flattened view of a base generator-of-sequences.
///
/// The elements generated are the concatenation of those in each
/// sequence generated by the base generator.
///
/// - Note: this is the `GeneratorType` used by `FlattenSequence`,
/// `FlattenCollection`, and `BidirectionalFlattenCollection`.
public struct _prext_FlattenGenerator<
Base : GeneratorType where Base.Element : SequenceType
> : GeneratorType, SequenceType {
/// Construct around a generator for the `base` sequence.
public init(_ base: Base) {
self._base = base
}
/// Advance to the next element and return it, or `nil` if no next
/// element exists.
///
/// - Requires: `next()` has not been applied to a copy of `self`
/// since the copy was made, and no preceding call to `self.next()`
/// has returned `nil`.
public mutating func next() -> Base.Element.Generator.Element? {
repeat {
if _fastPath(_inner != nil) {
let ret = _inner!.next()
if _fastPath(ret != nil) {
return ret
}
}
let s = _base.next()
if _slowPath(s == nil) {
return nil
}
_inner = s!.generate()
}
while true
}
internal var _base: Base
internal var _inner: Base.Element.Generator? = nil
}
/// A flattened view of a base sequence-of-sequences.
///
/// The elements of this view are a concatenation of the elements of
/// each sequence in the base.
public struct _prext_FlattenSequence<
Base : SequenceType where Base.Generator.Element : SequenceType
> : SequenceType {
/// Creates a concatenation of the elements of the elements of `base`.
///
/// - Complexity: O(1)
public init(_ base: Base) {
self._base = base
}
/// Return a *generator* over the elements of this *sequence*.
///
/// - Complexity: O(1).
public func generate() -> _prext_FlattenGenerator<Base.Generator> {
return _prext_FlattenGenerator(_base.generate())
}
internal var _base: Base
}
extension SequenceType where Generator.Element : SequenceType {
/// A concatenation of the elements of `self`.
public var _prext_flatten: _prext_FlattenSequence<Self> {
return _prext_FlattenSequence(self)
}
}
extension _prext_LazySequenceType
where Elements.Generator.Element == Generator.Element,
Generator.Element : SequenceType {
/// A concatenation of the elements of `self`.
public var _prext_flatten: _prext_LazySequence<
_prext_FlattenSequence<Elements>
> {
return _prext_FlattenSequence(elements)._prext_lazy
}
}
% for traversal in ('Forward', 'Bidirectional'):
% t = '' if traversal == 'Forward' else traversal
% Collection = '_prext_Flatten%sCollection' % t
% constraints = 'Base.Generator.Element : CollectionType'
% if traversal == 'Bidirectional':
% constraints += ''' , Base.Index : BidirectionalIndexType,
% Base.Generator.Element.Index : BidirectionalIndexType'''
% Index = Collection + 'Index'
public struct ${Index}<
Base: CollectionType where ${constraints}
> : ${traversal}IndexType {
/// Returns the next consecutive value after `self`.
///
/// - Requires: the next value is representable.
public func successor() -> ${Index} {
let nextInner = _inner!.successor()
if _fastPath(nextInner != _base[_outer].endIndex) {
return ${Index}(_base, _outer, nextInner)
}
let tailIndices = _outer.successor()..<_base.endIndex
if let nextOuter = tailIndices.indexOf({ !_base[$0].isEmpty }) {
return ${Index}(
_base, nextOuter, _base[nextOuter].startIndex)
}
return ${Index}(_base, _base.endIndex, nil)
}
% if traversal == 'Bidirectional':
/// Returns the previous consecutive value before `self`.
///
/// - Requires: The previous value is representable.
public func predecessor() -> ${Index} {
var outer = _outer
var inner = _inner
while inner == nil || inner! == _base[outer].startIndex {
inner = _base[--outer].endIndex
}
return ${Index}(_base, outer, inner!.predecessor())
}
% end
/// Construct the `startIndex` for a flattened view of `base`.
internal init(_startIndexOfFlattened base: Base) {
if let outer = base.indexOf({ !$0.isEmpty }) {
self._base = base
self._outer = outer
self._inner = base[outer].startIndex
}
else {
self = ${Index}(_endIndexOfFlattened: base)
}
}
/// Construct the `endIndex` for a flattened view of `base`.
internal init(_endIndexOfFlattened _base: Base) {
self._base = _base
self._outer = _base.endIndex
self._inner = nil
}
internal init(
_ _base: Base,
_ outer: Base.Index,
_ inner: Base.Generator.Element.Index?) {
self._base = _base
self._outer = outer
self._inner = inner
}
internal let _base: Base
internal let _outer: Base.Index
internal let _inner: Base.Generator.Element.Index?
}
public func == <Base> (lhs: ${Index}<Base>, rhs: ${Index}<Base>) -> Bool {
return lhs._outer == rhs._outer && lhs._inner == rhs._inner
}
/// A flattened view of a base collection-of-collections.
///
/// The elements of this view are a concatenation of the elements of
/// each collection in the base.
public struct ${Collection}<
Base: CollectionType where ${constraints}
> : CollectionType {
/// A type that represents a valid position in the collection.
///
/// Valid indices consist of the position of every element and a
/// "past the end" position that's not valid for use as a subscript.
public typealias Index = ${Index}<Base>
/// Creates a flattened view of `base`.
public init(_ base: Base) {
self._base = base
}
/// Return a *generator* over the elements of this *sequence*.
///
/// - Complexity: O(1).
public func generate() -> _prext_FlattenGenerator<Base.Generator> {
return _prext_FlattenGenerator(_base.generate())
}
/// The position of the first element in a non-empty collection.
///
/// In an empty collection, `startIndex == endIndex`.
public var startIndex: Index {
return ${Index}(_startIndexOfFlattened: _base)
}
/// The collection's "past the end" position.
///
/// `endIndex` is not a valid argument to `subscript`, and is always
/// reachable from `startIndex` by zero or more applications of
/// `successor()`.
public var endIndex: Index {
return ${Index}(_endIndexOfFlattened: _base)
}
/// Access the element at `position`.
///
/// - Requires: `position` is a valid position in `self` and
/// `position != endIndex`.
public subscript(
position: Index
) -> Base.Generator.Element.Generator.Element {
return _base[position._outer][position._inner!]
}
internal var _base: Base
}
extension CollectionType where ${constraints.replace('Base.', '')} {
/// A concatenation of the elements of `self`.
public var _prext_flatten: ${Collection}<Self> {
return ${Collection}(self)
}
}
extension _prext_LazyCollectionType
where ${constraints.replace('Base.', '')},
${constraints.replace('Base.', 'Elements.')},
Generator.Element == Elements.Generator.Element {
/// A concatenation of the elements of `self`.
public var _prext_flatten: _prext_LazyCollection<${Collection}<Elements>> {
return ${Collection}(elements)._prext_lazy
}
}
% end