1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
|
//===--- 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)
}
}
/// RandomAccessCollection which bridges to some C++ array.
///
/// It fixes the default reflection for bridged random access collections, which usually have a
/// `bridged` stored property.
/// Conforming to this protocol displays the "real" children not just `bridged`.
public protocol BridgedRandomAccessCollection : RandomAccessCollection, CustomReflectable {
}
extension BridgedRandomAccessCollection {
public var customMirror: Mirror {
Mirror(self, children: self.map { (label: nil, value: $0 as Any) })
}
}
/// 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 CollectionLikeSequence {
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
}
}
// Also make the lazy sequences a CollectionLikeSequence if the underlying sequence is one.
extension LazySequence : CollectionLikeSequence,
FormattedLikeArray, CustomStringConvertible, CustomReflectable
where Base: CollectionLikeSequence {}
extension FlattenSequence : CollectionLikeSequence,
FormattedLikeArray, CustomStringConvertible, CustomReflectable
where Base: CollectionLikeSequence {}
extension LazyMapSequence : CollectionLikeSequence,
FormattedLikeArray, CustomStringConvertible, CustomReflectable
where Base: CollectionLikeSequence {}
extension LazyFilterSequence : CollectionLikeSequence,
FormattedLikeArray, CustomStringConvertible, CustomReflectable
where Base: CollectionLikeSequence {}
//===----------------------------------------------------------------------===//
// Single-Element Inline Array
//===----------------------------------------------------------------------===//
public struct SingleInlineArray<Element>: RandomAccessCollection, FormattedLikeArray {
private 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)
}
}
|