Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Do not merge] [stdlib] IncompleteRange prototype #3737

Closed
wants to merge 17 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions stdlib/public/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ set(SWIFTLIB_ESSENTIAL
Print.swift
RandomAccessCollection.swift
Range.swift.gyb
RangeExpression.swift.gyb
RangeReplaceableCollection.swift.gyb
Reflection.swift
Repeat.swift
Expand Down
95 changes: 0 additions & 95 deletions stdlib/public/core/CollectionAlgorithms.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -469,101 +469,6 @@ ${orderingExplanation}
}
}

% for Self in 'Indexable', 'MutableIndexable':
%{

subscriptCommentPre = """\
/// Accesses a contiguous subrange of the collection's elements.
///
/// The accessed slice uses the same indices for the same elements as the
/// original collection. Always use the slice's `startIndex` property
/// instead of assuming that its indices start at a particular value.
///
/// This example demonstrates getting a slice of an array of strings, finding
/// the index of one of the strings in the slice, and then using that index
/// in the original array.
///
/// let streets = ["Adams", "Bryant", "Channing", "Douglas", "Evarts"]
/// let streetsSlice = streets[2 ..< streets.endIndex]
/// print(streetsSlice)
/// // Prints "["Channing", "Douglas", "Evarts"]"
///
/// let index = streetsSlice.index(of: "Evarts") // 4"""

if 'Mutable' in Self:
subscriptCommentMid = """\
/// streets[index!] = "Eustace"
/// print(streets[index!])
/// // Prints "Eustace\""""
else:
subscriptCommentMid = """\
/// print(streets[index!])
/// // Prints "Evarts\""""

subscriptCommentPost = """\
///
/// - Parameter bounds: A range of the collection's indices. The bounds of
/// the range must be valid indices of the collection."""
}%
// WORKAROUND rdar://25214066 - should be on Collection
extension ${Self} {
${subscriptCommentPre}
${subscriptCommentMid}
${subscriptCommentPost}
public subscript(bounds: ClosedRange<Index>) -> SubSequence {
get {
return self[
Range(
uncheckedBounds: (
lower: bounds.lowerBound,
upper: index(after: bounds.upperBound)))
]
}
% if 'Mutable' in Self:
set {
self[
Range(
uncheckedBounds: (
lower: bounds.lowerBound,
upper: index(after: bounds.upperBound)))
] = newValue
}
% end
}
}

// WORKAROUND rdar://25214066 - should be on Collection
extension ${Self} where Index : Strideable, Index.Stride : SignedInteger {
${subscriptCommentPre}
${subscriptCommentMid}
${subscriptCommentPost}
public subscript(bounds: CountableRange<Index>) -> SubSequence {
get {
return self[Range(bounds)]
}
% if 'Mutable' in Self:
set {
self[Range(bounds)] = newValue
}
% end
}

${subscriptCommentPre}
${subscriptCommentMid}
${subscriptCommentPost}
public subscript(bounds: CountableClosedRange<Index>) -> SubSequence {
get {
return self[ClosedRange(bounds)]
}
% if 'Mutable' in Self:
set {
self[ClosedRange(bounds)] = newValue
}
% end
}
}
% end

//===--- Unavailable stuff ------------------------------------------------===//

extension MutableCollection where Self : RandomAccessCollection {
Expand Down
1 change: 1 addition & 0 deletions stdlib/public/core/GroupInfo.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"Sort.swift",
"Range.swift",
"ClosedRange.swift",
"RangeExpression.swift",
"CollectionOfOne.swift",
"HeapBuffer.swift",
"Sequence.swift",
Expand Down
4 changes: 4 additions & 0 deletions stdlib/public/core/Policy.swift
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,8 @@ public func ~= <T : Equatable>(a: T, b: T) -> Bool {
// Standard postfix operators.
postfix operator ++ {}
postfix operator -- {}
postfix operator ..< {}
postfix operator ... {}

// Optional<T> unwrapping operator is built into the compiler as a part of
// postfix expression grammar.
Expand All @@ -570,6 +572,8 @@ prefix operator ! {}
prefix operator ~ {}
prefix operator + {}
prefix operator - {}
prefix operator ..< {}
prefix operator ... {}

// Standard infix operators.

Expand Down
87 changes: 87 additions & 0 deletions stdlib/public/core/Range.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -587,6 +587,93 @@ public func ..< <Bound>(
return CountableRange(uncheckedBounds: (lower: minimum, upper: maximum))
}

% for (Closed, Op) in [('', '..<'), ('Closed', '...')]:
/// A `${Closed}Range` which may not have all of its bounds specified.
/// The `Incomplete${Closed}Range` can be completed by providing a
/// `${Closed}Range` or `Countable${Closed}Range` from which it can retrieve
/// default upper and lower bounds.
@_fixed_layout
public struct Incomplete${Closed}Range<
Bound : Comparable
> {
/// The lowest value within the range.
/// If `nil`, completing the range will adopt the default value's
/// `lowerBound`.
public let lowerBound: Bound?
% if Closed == 'Closed':
/// The highest value within the range.
% else:
/// The value just above the highest value within the range.
% end
/// If `nil`, completing the range will adopt the default value's
/// `upperBound`.
public let upperBound: Bound?

internal init(_bounds bounds: (lower: Bound?, upper: Bound?)) {
lowerBound = bounds.lower
upperBound = bounds.upper
}
}

% for Countable in ['', 'Countable']:
extension Incomplete${Closed}Range
% if Countable == 'Countable':
where
// WORKAROUND rdar://25214598 - should be just Bound : Strideable
Bound : _Strideable & Comparable,
Bound.Stride : SignedInteger {
% else:
{
% end
% for Unchecked in ['', 'Unchecked']:
/// Returns a `${Countable}${Closed}Range` with the same `upperBound`
/// and `lowerBound` as the current instance. `nil` bounds are
/// filled in from `defaultBounds`.
///
/// This method does not check whether `lowerBound` and `upperBound`
/// lie within `defaultBounds`.
% if Unchecked == 'Unchecked':
/// Nor does it check whether the resulting `lowerBound` is below
/// its `upperBound`.
% end
@_transparent
public func completed(by${Unchecked} defaultBounds: ${Countable}${Closed}Range<Bound>) -> ${Countable}${Closed}Range<Bound> {
let lower = lowerBound ?? defaultBounds.lowerBound
let upper = upperBound ?? defaultBounds.upperBound
% if Unchecked == 'Unchecked':
return .init(uncheckedBounds: (lower: lower, upper: upper))
% else:
return lower ${Op} upper
% end
}
% end
}
% end

/// Constructs an `Incomplete${Closed}Range` with the provided upper
/// bound and an unknown lower bound.
@_transparent
public prefix func ${Op} <Bound: Comparable>(upperBound: Bound) -> Incomplete${Closed}Range<Bound> {
return .init(_bounds: (lower: nil, upper: upperBound))
}

/// Constructs an `Incomplete${Closed}Range` with the provided lower
/// bound and an unknown upper bound.
@_transparent
public postfix func ${Op} <Bound: Comparable>(lowerBound: Bound) -> Incomplete${Closed}Range<Bound> {
return .init(_bounds: (lower: lowerBound, upper: nil))
}

/// Constructs an `Incomplete${Closed}Range` with the provided upper
/// and lower bounds. Either or both may be `nil`, in which case the
/// bound will be provided when the `Incomplete${Closed}Range` is
/// completed.
@_transparent
public func ${Op} <Bound: Comparable>(lowerBound: Bound?, upperBound: Bound?) -> Incomplete${Closed}Range<Bound> {
return .init(_bounds: (lower: lowerBound, upper: upperBound))
}
% end

// swift-3-indexing-model: this is not really a proper rename
@available(*, unavailable, renamed: "IndexingIterator")
public struct RangeGenerator<Bound> {}
Expand Down
Loading