Skip to content

Commit 80f0044

Browse files
authored
Merge pull request #4623 from apple/stdlib-split-reflectable.swift
stdlib: move non-legacy parts of Reflection.swift into separate files
2 parents 7479810 + cee0d7a commit 80f0044

File tree

5 files changed

+352
-323
lines changed

5 files changed

+352
-323
lines changed

stdlib/public/core/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ set(SWIFTLIB_ESSENTIAL
4545
CTypes.swift
4646
DebuggerSupport.swift
4747
DropWhile.swift.gyb
48+
Dump.swift
4849
EmptyCollection.swift
4950
Equatable.swift
5051
ErrorType.swift
@@ -84,6 +85,7 @@ set(SWIFTLIB_ESSENTIAL
8485
MutableCollection.swift
8586
NewtypeWrapper.swift.gyb
8687
ObjCMirrors.swift
88+
ObjectIdentifier.swift
8789
Optional.swift
8890
OptionSet.swift
8991
OutputStream.swift
@@ -94,7 +96,7 @@ set(SWIFTLIB_ESSENTIAL
9496
RandomAccessCollection.swift
9597
Range.swift.gyb
9698
RangeReplaceableCollection.swift.gyb
97-
Reflection.swift
99+
ReflectionLegacy.swift
98100
Repeat.swift
99101
REPL.swift
100102
Reverse.swift

stdlib/public/core/Dump.swift

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
/// Dumps an object's contents using its mirror to the specified output stream.
14+
@discardableResult
15+
public func dump<T, TargetStream : TextOutputStream>(
16+
_ value: T,
17+
to target: inout TargetStream,
18+
name: String? = nil,
19+
indent: Int = 0,
20+
maxDepth: Int = .max,
21+
maxItems: Int = .max
22+
) -> T {
23+
var maxItemCounter = maxItems
24+
var visitedItems = [ObjectIdentifier : Int]()
25+
target._lock()
26+
defer { target._unlock() }
27+
_dump_unlocked(
28+
value,
29+
to: &target,
30+
name: name,
31+
indent: indent,
32+
maxDepth: maxDepth,
33+
maxItemCounter: &maxItemCounter,
34+
visitedItems: &visitedItems)
35+
return value
36+
}
37+
38+
/// Dumps an object's contents using its mirror to standard output.
39+
@discardableResult
40+
public func dump<T>(
41+
_ value: T,
42+
name: String? = nil,
43+
indent: Int = 0,
44+
maxDepth: Int = .max,
45+
maxItems: Int = .max
46+
) -> T {
47+
var stdoutStream = _Stdout()
48+
return dump(
49+
value,
50+
to: &stdoutStream,
51+
name: name,
52+
indent: indent,
53+
maxDepth: maxDepth,
54+
maxItems: maxItems)
55+
}
56+
57+
/// Dump an object's contents. User code should use dump().
58+
internal func _dump_unlocked<TargetStream : TextOutputStream>(
59+
_ value: Any,
60+
to target: inout TargetStream,
61+
name: String?,
62+
indent: Int,
63+
maxDepth: Int,
64+
maxItemCounter: inout Int,
65+
visitedItems: inout [ObjectIdentifier : Int]
66+
) {
67+
guard maxItemCounter > 0 else { return }
68+
maxItemCounter -= 1
69+
70+
for _ in 0..<indent { target.write(" ") }
71+
72+
let mirror = Mirror(reflecting: value)
73+
let count = mirror.children.count
74+
let bullet = count == 0 ? "-"
75+
: maxDepth <= 0 ? "" : ""
76+
target.write(bullet)
77+
target.write(" ")
78+
79+
if let nam = name {
80+
target.write(nam)
81+
target.write(": ")
82+
}
83+
// This takes the place of the old mirror API's 'summary' property
84+
_dumpPrint_unlocked(value, mirror, &target)
85+
86+
let id: ObjectIdentifier?
87+
if type(of: value) is AnyObject.Type {
88+
// Object is a class (but not an ObjC-bridged struct)
89+
id = ObjectIdentifier(_unsafeDowncastToAnyObject(fromAny: value))
90+
} else if let metatypeInstance = value as? Any.Type {
91+
// Object is a metatype
92+
id = ObjectIdentifier(metatypeInstance)
93+
} else {
94+
id = nil
95+
}
96+
if let theId = id {
97+
if let previous = visitedItems[theId] {
98+
target.write(" #")
99+
_print_unlocked(previous, &target)
100+
target.write("\n")
101+
return
102+
}
103+
let identifier = visitedItems.count
104+
visitedItems[theId] = identifier
105+
target.write(" #")
106+
_print_unlocked(identifier, &target)
107+
}
108+
109+
target.write("\n")
110+
111+
guard maxDepth > 0 else { return }
112+
113+
if let superclassMirror = mirror.superclassMirror {
114+
_dumpSuperclass_unlocked(
115+
mirror: superclassMirror,
116+
to: &target,
117+
indent: indent + 2,
118+
maxDepth: maxDepth - 1,
119+
maxItemCounter: &maxItemCounter,
120+
visitedItems: &visitedItems)
121+
}
122+
123+
var currentIndex = mirror.children.startIndex
124+
for i in 0..<count {
125+
if maxItemCounter <= 0 {
126+
for _ in 0..<(indent+4) {
127+
_print_unlocked(" ", &target)
128+
}
129+
let remainder = count - i
130+
target.write("(")
131+
_print_unlocked(remainder, &target)
132+
if i > 0 { target.write(" more") }
133+
if remainder == 1 {
134+
target.write(" child)\n")
135+
} else {
136+
target.write(" children)\n")
137+
}
138+
return
139+
}
140+
141+
let (name, child) = mirror.children[currentIndex]
142+
mirror.children.formIndex(after: &currentIndex)
143+
_dump_unlocked(
144+
child,
145+
to: &target,
146+
name: name,
147+
indent: indent + 2,
148+
maxDepth: maxDepth - 1,
149+
maxItemCounter: &maxItemCounter,
150+
visitedItems: &visitedItems)
151+
}
152+
}
153+
154+
/// Dump information about an object's superclass, given a mirror reflecting
155+
/// that superclass.
156+
internal func _dumpSuperclass_unlocked<TargetStream : TextOutputStream>(
157+
mirror: Mirror,
158+
to target: inout TargetStream,
159+
indent: Int,
160+
maxDepth: Int,
161+
maxItemCounter: inout Int,
162+
visitedItems: inout [ObjectIdentifier : Int]
163+
) {
164+
guard maxItemCounter > 0 else { return }
165+
maxItemCounter -= 1
166+
167+
for _ in 0..<indent { target.write(" ") }
168+
169+
let count = mirror.children.count
170+
let bullet = count == 0 ? "-"
171+
: maxDepth <= 0 ? "" : ""
172+
target.write(bullet)
173+
target.write(" super: ")
174+
_debugPrint_unlocked(mirror.subjectType, &target)
175+
target.write("\n")
176+
177+
guard maxDepth > 0 else { return }
178+
179+
if let superclassMirror = mirror.superclassMirror {
180+
_dumpSuperclass_unlocked(
181+
mirror: superclassMirror,
182+
to: &target,
183+
indent: indent + 2,
184+
maxDepth: maxDepth - 1,
185+
maxItemCounter: &maxItemCounter,
186+
visitedItems: &visitedItems)
187+
}
188+
189+
var currentIndex = mirror.children.startIndex
190+
for i in 0..<count {
191+
if maxItemCounter <= 0 {
192+
for _ in 0..<(indent+4) {
193+
target.write(" ")
194+
}
195+
let remainder = count - i
196+
target.write("(")
197+
_print_unlocked(remainder, &target)
198+
if i > 0 { target.write(" more") }
199+
if remainder == 1 {
200+
target.write(" child)\n")
201+
} else {
202+
target.write(" children)\n")
203+
}
204+
return
205+
}
206+
207+
let (name, child) = mirror.children[currentIndex]
208+
mirror.children.formIndex(after: &currentIndex)
209+
_dump_unlocked(
210+
child,
211+
to: &target,
212+
name: name,
213+
indent: indent + 2,
214+
maxDepth: maxDepth - 1,
215+
maxItemCounter: &maxItemCounter,
216+
visitedItems: &visitedItems)
217+
}
218+
}
219+

stdlib/public/core/GroupInfo.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,12 @@
9595
"MemoryLayout.swift"
9696
],
9797
"Reflection": [
98-
"Mirrors.swift",
98+
"Dump.swift",
9999
"Mirror.swift",
100-
"Reflection.swift",
101-
"ObjCMirrors.swift"
100+
"Mirrors.swift",
101+
"ObjCMirrors.swift",
102+
"ObjectIdentifier.swift",
103+
"ReflectionLegacy.swift"
102104
],
103105
"Math": [
104106
"SetAlgebra.swift",
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
/// A unique identifier for a class instance or metatype.
14+
///
15+
/// In Swift, only class instances and metatypes have unique identities. There
16+
/// is no notion of identity for structs, enums, functions, or tuples.
17+
public struct ObjectIdentifier : Hashable {
18+
internal let _value: Builtin.RawPointer
19+
20+
// FIXME: Better hashing algorithm
21+
/// The identifier's hash value.
22+
///
23+
/// The hash value is not guaranteed to be stable across different
24+
/// invocations of the same program. Do not persist the hash value across
25+
/// program runs.
26+
///
27+
/// - SeeAlso: `Hashable`
28+
public var hashValue: Int {
29+
return Int(Builtin.ptrtoint_Word(_value))
30+
}
31+
32+
/// Creates an instance that uniquely identifies the given class instance.
33+
///
34+
/// The following example creates an example class `A` and compares instances
35+
/// of the class using their object identifiers and the identical-to
36+
/// operator (`===`):
37+
///
38+
/// class IntegerRef {
39+
/// let value: Int
40+
/// init(_ value: Int) {
41+
/// self.value = value
42+
/// }
43+
/// }
44+
///
45+
/// let x = IntegerRef(10)
46+
/// let y = x
47+
///
48+
/// print(ObjectIdentifier(x) == ObjectIdentifier(y))
49+
/// // Prints "true"
50+
/// print(x === y)
51+
/// // Prints "true"
52+
///
53+
/// let z = IntegerRef(10)
54+
/// print(ObjectIdentifier(x) == ObjectIdentifier(z))
55+
/// // Prints "false"
56+
/// print(x === z)
57+
/// // Prints "false"
58+
///
59+
/// - Parameter x: An instance of a class.
60+
public init(_ x: AnyObject) {
61+
self._value = Builtin.bridgeToRawPointer(x)
62+
}
63+
64+
/// Creates an instance that uniquely identifies the given metatype.
65+
///
66+
/// - Parameter: A metatype.
67+
public init(_ x: Any.Type) {
68+
self._value = unsafeBitCast(x, to: Builtin.RawPointer.self)
69+
}
70+
}
71+
72+
extension ObjectIdentifier : CustomDebugStringConvertible {
73+
/// A textual representation of the identifier, suitable for debugging.
74+
public var debugDescription: String {
75+
return "ObjectIdentifier(\(_rawPointerToString(_value)))"
76+
}
77+
}
78+
79+
extension ObjectIdentifier : Comparable {
80+
public static func < (lhs: ObjectIdentifier, rhs: ObjectIdentifier) -> Bool {
81+
return UInt(bitPattern: lhs) < UInt(bitPattern: rhs)
82+
}
83+
84+
public static func == (x: ObjectIdentifier, y: ObjectIdentifier) -> Bool {
85+
return Bool(Builtin.cmp_eq_RawPointer(x._value, y._value))
86+
}
87+
}
88+
89+
extension UInt {
90+
/// Creates an integer that captures the full value of the given object
91+
/// identifier.
92+
public init(bitPattern objectID: ObjectIdentifier) {
93+
self.init(Builtin.ptrtoint_Word(objectID._value))
94+
}
95+
}
96+
97+
extension Int {
98+
/// Creates an integer that captures the full value of the given object
99+
/// identifier.
100+
public init(bitPattern objectID: ObjectIdentifier) {
101+
self.init(bitPattern: UInt(bitPattern: objectID))
102+
}
103+
}
104+
105+
extension ObjectIdentifier {
106+
@available(*, unavailable, message: "use the 'UInt(_:)' initializer")
107+
public var uintValue: UInt {
108+
Builtin.unreachable()
109+
}
110+
}
111+
112+
extension UInt {
113+
@available(*, unavailable, renamed: "init(bitPattern:)")
114+
public init(_ objectID: ObjectIdentifier) {
115+
Builtin.unreachable()
116+
}
117+
}
118+
119+
extension Int {
120+
@available(*, unavailable, renamed: "init(bitPattern:)")
121+
public init(_ objectID: ObjectIdentifier) {
122+
Builtin.unreachable()
123+
}
124+
}
125+

0 commit comments

Comments
 (0)