Files
swift-mirror/SwiftCompilerSources/Sources/SIL/Utilities/SequenceUtilities.swift

171 lines
5.7 KiB
Swift

//===--- SequenceUtilities.swift ------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
import Basic
/// Types conforming to `HasName` will be displayed by their name (instead of the
/// full object) in collection descriptions.
///
/// This is useful to make collections, e.g. of BasicBlocks or Functions, readable.
public protocol HasShortDescription {
var shortDescription: String { get }
}
private struct CustomMirrorChild : CustomStringConvertible, NoReflectionChildren {
public var description: String
public init(description: String) { self.description = description }
}
/// Makes a Sequence's `description` and `customMirror` formatted like Array, e.g. [a, b, c].
public protocol FormattedLikeArray : Sequence, CustomStringConvertible, CustomReflectable {
}
extension FormattedLikeArray {
/// Display a Sequence in an array like format, e.g. [a, b, c]
public var description: String {
"[" + map {
if let named = $0 as? HasShortDescription {
return named.shortDescription
}
return String(describing: $0)
}.joined(separator: ", ") + "]"
}
/// The mirror which adds the children of a Sequence, similar to `Array`.
public var customMirror: Mirror {
// If the one-line description is not too large, print that instead of the
// children in separate lines.
if description.count <= 80 {
return Mirror(self, children: [])
}
let c: [Mirror.Child] = map {
let val: Any
if let named = $0 as? HasShortDescription {
val = CustomMirrorChild(description: named.shortDescription)
} else {
val = $0
}
return (label: nil, value: val)
}
return Mirror(self, children: c, displayStyle: .collection)
}
}
/// A Sequence which is not consuming and therefore behaves like a Collection.
///
/// Many sequences in SIL and the optimizer should be collections but cannot
/// because their Index cannot conform to Comparable. Those sequences conform
/// to CollectionLikeSequence.
///
/// For convenience it also inherits from FormattedLikeArray.
public protocol CollectionLikeSequence : FormattedLikeArray {
}
public extension Sequence {
var isEmpty: Bool { !contains(where: { _ in true }) }
var singleElement: Element? {
var singleElement: Element? = nil
for e in self {
if singleElement != nil {
return nil
}
singleElement = e
}
return singleElement
}
var first: Element? { first(where: { _ in true }) }
}
// Also make the lazy sequences a CollectionLikeSequence if the underlying sequence is one.
extension LazySequence : /*@retroactive*/ SIL.CollectionLikeSequence,
/*@retroactive*/ SIL.FormattedLikeArray,
/*@retroactive*/ Swift.CustomStringConvertible,
/*@retroactive*/ Swift.CustomReflectable
where Base: CollectionLikeSequence {}
extension FlattenSequence : /*@retroactive*/ SIL.CollectionLikeSequence,
/*@retroactive*/ SIL.FormattedLikeArray,
/*@retroactive*/ Swift.CustomStringConvertible,
/*@retroactive*/ Swift.CustomReflectable
where Base: CollectionLikeSequence {}
extension LazyMapSequence : /*@retroactive*/ SIL.CollectionLikeSequence,
/*@retroactive*/ SIL.FormattedLikeArray,
/*@retroactive*/ Swift.CustomStringConvertible,
/*@retroactive*/ Swift.CustomReflectable
where Base: CollectionLikeSequence {}
extension LazyFilterSequence : /*@retroactive*/ SIL.CollectionLikeSequence,
/*@retroactive*/ SIL.FormattedLikeArray,
/*@retroactive*/ Swift.CustomStringConvertible,
/*@retroactive*/ Swift.CustomReflectable
where Base: CollectionLikeSequence {}
//===----------------------------------------------------------------------===//
// Single-Element Inline Array
//===----------------------------------------------------------------------===//
public struct SingleInlineArray<Element>: RandomAccessCollection, FormattedLikeArray {
public var singleElement: Element?
private var multipleElements: [Element] = []
public init() {}
public init(element: Element) {
singleElement = element
}
public var startIndex: Int { 0 }
public var endIndex: Int {
singleElement == nil ? 0 : multipleElements.count + 1
}
public subscript(_ index: Int) -> Element {
_read {
if index == 0 {
yield singleElement!
} else {
yield multipleElements[index - 1]
}
}
_modify {
if index == 0 {
yield &singleElement!
} else {
yield &multipleElements[index - 1]
}
}
}
public mutating func append(_ element: __owned Element) {
push(element)
}
public mutating func append<S: Sequence>(contentsOf newElements: __owned S) where S.Element == Element {
for element in newElements {
push(element)
}
}
public mutating func push(_ element: __owned Element) {
guard singleElement != nil else {
singleElement = element
return
}
multipleElements.append(element)
}
}