stdlib: change underestimateCount() into a method

rdar://19895265

Swift SVN r27346
This commit is contained in:
Dmitri Hrybenko
2015-04-16 05:05:17 +00:00
parent c7c25ad298
commit c48d6aa0ab
10 changed files with 225 additions and 110 deletions

View File

@@ -2187,17 +2187,15 @@ public struct MinimalSequence<T> : SequenceType {
return MinimalGenerator(_sharedState)
}
public func _prext_underestimateCount() -> Int {
return underestimatedCount
}
public var underestimatedCount: Int
internal let _sharedState: _MinimalGeneratorSharedState<T>
}
public func ~> <T> (
s: MinimalSequence<T>, _: (_UnderestimateCount, ())
) -> Int {
return s.underestimatedCount
}
//===----------------------------------------------------------------------===//
// MinimalForwardIndex
//===----------------------------------------------------------------------===//
@@ -2359,17 +2357,15 @@ public struct ${Self}<T> : CollectionType {
return _elements[i.position]
}
public func _prext_underestimateCount() -> Int {
return underestimatedCount
}
public var underestimatedCount: Int
internal let _elements: [T]
}
public func ~> <T> (
c: ${Self}<T>, _: (_UnderestimateCount, ())
) -> Int {
return c.underestimatedCount
}
%end
//===----------------------------------------------------------------------===//
@@ -2411,6 +2407,10 @@ public struct ${Self}<T> : RangeReplaceableCollectionType {
return MinimalGenerator(elements)
}
public func _prext_underestimateCount() -> Int {
return underestimatedCount
}
public var startIndex: ${Index} {
return ${Index}(
position: 0,
@@ -2485,12 +2485,6 @@ public struct ${Self}<T> : RangeReplaceableCollectionType {
public var elements: [T]
}
public func ~> <T> (
c: ${Self}<T>, _: (_UnderestimateCount, ())
) -> Int {
return c.underestimatedCount
}
%end
// ${'Local Variables'}:

View File

@@ -66,10 +66,17 @@ public protocol _CollectionType : _SequenceType {
subscript(_i: Index) -> _Element {get}
}
public protocol _CollectionDefaultsType : _CollectionType {
}
public protocol _CollectionDefaultsType
: _CollectionType, _SequenceElementInvariantDefaultsType {}
extension _CollectionDefaultsType {
/// Return a value less than or equal to the number of elements in
/// `self`, **nondestructively**.
///
/// Complexity: O(N)
final public func _prext_underestimateCount() -> Int {
return numericCast(count(self))
}
}
/// A multi-pass *sequence* with addressable positions.
@@ -99,12 +106,6 @@ public protocol CollectionType
func ~> (_:Self, _:(_Count, ())) -> Index.Distance
}
// Default implementation of underestimateCount for *collections*. Do not
// use this operator directly; call `underestimateCount(s)` instead
public func ~> <T : _CollectionType>(x:T,_:(_UnderestimateCount,())) -> Int {
return numericCast(x~>_count())
}
// A fast implementation for when you are backed by a contiguous array.
public func ~> <T : protocol<_Sequence_Type, _ArrayType>>(
source: T, ptr: (_InitializeTo, UnsafeMutablePointer<T.Generator.Element>)) {

View File

@@ -61,24 +61,6 @@ public protocol GeneratorType {
public protocol _SequenceType {
}
/// This protocol is an implementation detail of `SequenceType`; do
/// not use it directly.
///
/// Its requirements are inherited by `SequenceType` and thus must
/// be satisfied by types conforming to that protocol.
public protocol _Sequence_Type : _SequenceType, _SequenceDefaultsType {
/// A type whose instances can produce the elements of this
/// sequence, in order.
typealias Generator : GeneratorType
/// Return a *generator* over the elements of this *sequence*. The
/// *generator*\ 's next element is the first element of the
/// sequence.
///
/// Complexity: O(1)
func generate() -> Generator
}
public protocol _SequenceDefaultsType {
/// A type that provides the *sequence*\ 's iteration interface and
/// encapsulates its iteration state.
@@ -95,7 +77,45 @@ public protocol _SequenceDefaultsType {
extension _SequenceDefaultsType {
}
extension _SequenceDefaultsType {
public protocol _SequenceElementInvariantDefaultsType {
// This protocol is an anchor point for default implementations for
// SequenceType that don't depend on sequence contents.
}
extension _SequenceElementInvariantDefaultsType {
/// Return a value less than or equal to the number of elements in
/// `self`, **nondestructively**.
///
/// Complexity: O(N)
final public func _prext_underestimateCount() -> Int {
return 0
}
}
/// This protocol is an implementation detail of `SequenceType`; do
/// not use it directly.
///
/// Its requirements are inherited by `SequenceType` and thus must
/// be satisfied by types conforming to that protocol.
public protocol _Sequence_Type
: _SequenceType, _SequenceDefaultsType, _SequenceElementInvariantDefaultsType {
/// A type whose instances can produce the elements of this
/// sequence, in order.
typealias Generator : GeneratorType
/// Return a *generator* over the elements of this *sequence*. The
/// *generator*\ 's next element is the first element of the
/// sequence.
///
/// Complexity: O(1)
func generate() -> Generator
/// Return a value less than or equal to the number of elements in
/// `self`, **nondestructively**.
///
/// Complexity: O(N)
func _prext_underestimateCount() -> Int
}
/// A type that can be iterated with a `for`\ ...\ `in` loop.
@@ -114,12 +134,6 @@ public protocol SequenceType : _Sequence_Type {
/// Complexity: O(1)
func generate() -> Generator
/// Return a value less than or equal to the number of elements in
/// self, **nondestructively**.
///
/// Complexity: O(N)
func ~> (_:Self,_:(_UnderestimateCount,())) -> Int
/// If `self` is multi-pass (i.e., a `CollectionType`), invoke the function
/// on `self` and return its result. Otherwise, return `nil`.
func ~> <R>(_: Self, _: (_PreprocessingPass, ((Self)->R))) -> R?
@@ -141,26 +155,12 @@ public func _copyToNativeArrayBuffer<Args>(args: Args)
return (_CopyToNativeArrayBuffer(), args)
}
// Operation tags for underestimateCount. See Index.swift for an
// explanation of operation tags.
public struct _UnderestimateCount {}
internal func _underestimateCount<Args>(args: Args)
-> (_UnderestimateCount, Args)
{
return (_UnderestimateCount(), args)
}
// Default implementation of underestimateCount for Sequences. Do not
// use this operator directly; call underestimateCount(s) instead
public func ~> <T : _SequenceType>(s: T,_:(_UnderestimateCount, ())) -> Int {
return 0
}
/// Return an underestimate of the number of elements in the given
/// sequence, without consuming the sequence. For Sequences that are
/// actually Collections, this will return count(x)
public func underestimateCount<T : SequenceType>(x: T) -> Int {
return x~>_underestimateCount()
// FIXME(prext): remove this function when protocol extensions land.
return x._prext_underestimateCount()
}
public struct _InitializeTo {}

View File

@@ -533,7 +533,7 @@ public func ~> <
source: S, _: (_CopyToNativeArrayBuffer,())
) -> _ContiguousArrayBuffer<S.Generator.Element>
{
let initialCapacity = source~>_underestimateCount()
let initialCapacity = source._prext_underestimateCount()
var result = _ContiguousArrayBuffer<S.Generator.Element>(
count: 0, minimumCapacity: initialCapacity)

View File

@@ -214,10 +214,10 @@ public struct AnySequence<T> : SequenceType {
}
% for Kind in ['Sequence'] + [t + 'Collection' for t in traversals]:
public func ~> <Element>(
source: Any${Kind}<Element>, _: (_UnderestimateCount, ())
) -> Int {
return source._box._underestimateCount()
extension Any${Kind} {
public func _prext_underestimateCount() -> Int {
return _box._underestimateCount()
}
}
public func ~> <Element>(

View File

@@ -80,13 +80,11 @@ public struct ${Self}<S : CollectionType ${whereClause}> : CollectionType {
return Array(_base)
}
var _base: S
}
public func _prext_underestimateCount() -> Int {
return underestimateCount(_base)
}
public func ~> <S : CollectionType ${whereClause}> (
s: ${Self}<S>, _: (_UnderestimateCount, ())
) -> Int {
return underestimateCount(s._base)
var _base: S
}
/// Augment `s` with lazy methods such as `map`, `filter`, etc.

View File

@@ -32,13 +32,11 @@ public struct LazySequence<S : SequenceType> : SequenceType {
return Array(_base)
}
var _base: S
}
public func _prext_underestimateCount() -> Int {
return underestimateCount(_base)
}
public func ~> <S : SequenceType> (
s: LazySequence<S>, _: (_UnderestimateCount, ())
) -> Int {
return underestimateCount(s._base)
var _base: S
}
/// Augment `s` with lazy methods such as `map`, `filter`, etc.

View File

@@ -55,16 +55,14 @@ public struct MapSequenceView<Base : SequenceType, T> : SequenceType {
_base: _base.generate(), _transform: _transform)
}
public func _prext_underestimateCount() -> Int {
return underestimateCount(_base)
}
var _base: Base
var _transform: (Base.Generator.Element)->T
}
public func ~> <Base : SequenceType, T> (
s: MapSequenceView<Base, T>, _: (_UnderestimateCount, ())
) -> Int {
return underestimateCount(s._base)
}
/// Return an `Array` containing the results of mapping `transform`
/// over `source`.
public func map<S : SequenceType, T>(
@@ -121,16 +119,14 @@ public struct MapCollectionView<Base : CollectionType, T> : CollectionType {
return MapSequenceGenerator(_base: _base.generate(), _transform: _transform)
}
public func _prext_underestimateCount() -> Int {
return underestimateCount(_base)
}
var _base: Base
var _transform: (Base.Generator.Element)->T
}
public func ~> <Base: CollectionType, T> (
s: MapCollectionView<Base, T>, _: (_UnderestimateCount, ())
) -> Int {
return underestimateCount(s._base)
}
/// Return an `Array` containing the results of mapping `transform`
/// over `source`.
public func map<C : CollectionType, T>(

View File

@@ -598,7 +598,7 @@ extension _StringCore : ExtensibleCollectionType {
}
}
let growth = s~>_underestimateCount()
let growth = s._prext_underestimateCount()
var g = s.generate()
if _fastPath(growth > 0) {

View File

@@ -356,7 +356,7 @@ Algorithm.test("map/CollectionType") {
expectType([Int16].self, &result)
expectEqual([], result)
expectLE(c.underestimatedCount, result.capacity)
expectGE(2 * result.count, result.capacity) {
expectGE(result.count + 3, result.capacity) {
"map() should use the precise element count"
}
}
@@ -365,16 +365,7 @@ Algorithm.test("map/CollectionType") {
[ 0, 30, 10, 90 ], underestimatedCount: .Value(0))
let result = map(c) { $0 + 1 }
expectEqual([ 1, 31, 11, 91 ], result)
expectGE(2 * result.count, result.capacity) {
"map() should use the precise element count"
}
}
if true {
let c = MinimalForwardCollection(
[ 0, 30, 10, 90 ], underestimatedCount: .Overestimate)
let result = map(c) { $0 + 1 }
expectEqual([ 1, 31, 11, 91 ], result)
expectGE(2 * result.count, result.capacity) {
expectGE(result.count + 3, result.capacity) {
"map() should use the precise element count"
}
}
@@ -1817,7 +1808,7 @@ SequenceTypeAlgorithms.test("map/CollectionType") {
expectEqual(0, LifetimeTracked.instances)
for test in mapTests {
for underestimateCountBehavior in [
UnderestimateCountBehavior.Overestimate,
UnderestimateCountBehavior.Precise,
UnderestimateCountBehavior.Value(0)
] {
let s = MinimalForwardCollection<OpaqueValue<Int>>(
@@ -1840,7 +1831,7 @@ SequenceTypeAlgorithms.test("map/CollectionType") {
expectEqual(test.sequence.count, timesClosureWasCalled) {
"map() should be eager and should only call its predicate once per element"
}
expectGE(2 * result.count, result.capacity) {
expectGE(result.count + 3, result.capacity) {
"map() should use the precise element count"
}
}
@@ -2119,6 +2110,143 @@ SequenceTypeAlgorithms.test("zip") {
}
}
//===----------------------------------------------------------------------===//
// underestimateCount()
//===----------------------------------------------------------------------===//
func callGenericUnderestimatedCount<S : SequenceType>(s: S) -> Int {
return s._prext_underestimateCount()
}
struct SequenceWithDefaultUnderestimateCount : SequenceType {
init() {}
func generate() -> MinimalSequence<OpaqueValue<Int>>.Generator {
expectUnreachable()
return MinimalSequence(
[ 1, 2, 3 ]._prext_map { OpaqueValue($0) }
).generate()
}
}
SequenceTypeAlgorithms.test("underestimateCount/SequenceType/DefaultImplementation") {
let s = SequenceWithDefaultUnderestimateCount()
expectEqual(0, callGenericUnderestimatedCount(s))
}
struct SequenceWithCustomUnderestimateCount : SequenceType {
init(underestimatedCount: Int) {
self._underestimatedCount = underestimatedCount
}
func generate() -> MinimalSequence<OpaqueValue<Int>>.Generator {
expectUnreachable()
return MinimalSequence(
[ 0xffff, 0xffff, 0xffff ]._prext_map { OpaqueValue($0) }
).generate()
}
func _prext_underestimateCount() -> Int {
return _underestimatedCount
}
let _underestimatedCount: Int
}
SequenceTypeAlgorithms.test("underestimateCount/SequenceType/CustomImplementation") {
if true {
let s = SequenceWithCustomUnderestimateCount(underestimatedCount: 5)
expectEqual(5, callGenericUnderestimatedCount(s))
}
if true {
let s = SequenceWithCustomUnderestimateCount(underestimatedCount: 42)
expectEqual(42, callGenericUnderestimatedCount(s))
}
}
struct CollectionWithDefaultUnderestimateCount : CollectionType {
init(count: Int) {
self._count = count
}
func generate() -> MinimalGenerator<OpaqueValue<Int>> {
expectUnreachable()
return MinimalGenerator([])
}
var startIndex: MinimalForwardIndex {
return MinimalForwardIndex(position: 0, startIndex: 0, endIndex: _count)
}
var endIndex: MinimalForwardIndex {
return MinimalForwardIndex(
position: _count, startIndex: 0, endIndex: _count)
}
subscript(i: MinimalForwardIndex) -> OpaqueValue<Int> {
expectUnreachable()
return OpaqueValue(0xffff)
}
var _count: Int
}
SequenceTypeAlgorithms.test("underestimateCount/CollectionType/DefaultImplementation") {
if true {
let s = CollectionWithDefaultUnderestimateCount(count: 0)
expectEqual(0, callGenericUnderestimatedCount(s))
}
if true {
let s = CollectionWithDefaultUnderestimateCount(count: 5)
expectEqual(5, callGenericUnderestimatedCount(s))
}
}
struct CollectionWithCustomUnderestimateCount : CollectionType {
init(underestimatedCount: Int) {
self._underestimatedCount = underestimatedCount
}
func generate() -> MinimalGenerator<OpaqueValue<Int>> {
expectUnreachable()
return MinimalGenerator([])
}
var startIndex: MinimalForwardIndex {
expectUnreachable()
return MinimalForwardIndex(position: 0, startIndex: 0, endIndex: 0xffff)
}
var endIndex: MinimalForwardIndex {
expectUnreachable()
return MinimalForwardIndex(
position: 0xffff, startIndex: 0, endIndex: 0xffff)
}
subscript(i: MinimalForwardIndex) -> OpaqueValue<Int> {
expectUnreachable()
return OpaqueValue(0xffff)
}
func _prext_underestimateCount() -> Int {
return _underestimatedCount
}
let _underestimatedCount: Int
}
SequenceTypeAlgorithms.test("underestimateCount/CollectionType/CustomImplementation") {
if true {
let s = CollectionWithCustomUnderestimateCount(underestimatedCount: 0)
expectEqual(0, callGenericUnderestimatedCount(s))
}
if true {
let s = CollectionWithCustomUnderestimateCount(underestimatedCount: 5)
expectEqual(5, callGenericUnderestimatedCount(s))
}
}
//===----------------------------------------------------------------------===//
// isEmpty
//===----------------------------------------------------------------------===//