//===----------------------------------------------------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// /// Customizes the result of `_reflect(x)`, where `x` is a conforming /// type. public protocol _Reflectable { // The runtime has inappropriate knowledge of this protocol and how its // witness tables are laid out. Changing this protocol requires a // corresponding change to Reflection.cpp. /// Returns a mirror that reflects `self`. @warn_unused_result func _getMirror() -> _Mirror } /// A unique identifier for a class instance or metatype. /// /// In Swift, only class instances and metatypes have unique identities. There /// is no notion of identity for structs, enums, functions, or tuples. public struct ObjectIdentifier : Hashable, Comparable { internal let _value: Builtin.RawPointer // FIXME: Better hashing algorithm /// The hash value. /// /// **Axiom:** `x == y` implies `x.hashValue == y.hashValue`. /// /// - Note: The hash value is not guaranteed to be stable across /// different invocations of the same program. Do not persist the /// hash value across program runs. public var hashValue: Int { return Int(Builtin.ptrtoint_Word(_value)) } /// Construct an instance that uniquely identifies the class instance `x`. public init(_ x: AnyObject) { self._value = Builtin.bridgeToRawPointer(x) } /// Construct an instance that uniquely identifies the metatype `x`. public init(_ x: Any.Type) { self._value = unsafeBitCast(x, to: Builtin.RawPointer.self) } } @warn_unused_result public func <(lhs: ObjectIdentifier, rhs: ObjectIdentifier) -> Bool { return UInt(lhs) < UInt(rhs) } @warn_unused_result public func ==(x: ObjectIdentifier, y: ObjectIdentifier) -> Bool { return Bool(Builtin.cmp_eq_RawPointer(x._value, y._value)) } extension UInt { /// Create a `UInt` that captures the full value of `objectID`. public init(_ objectID: ObjectIdentifier) { self.init(Builtin.ptrtoint_Word(objectID._value)) } } extension Int { /// Create an `Int` that captures the full value of `objectID`. public init(_ objectID: ObjectIdentifier) { self.init(bitPattern: UInt(objectID)) } } /// How children of this value should be presented in the IDE. public enum _MirrorDisposition { /// As a struct. case `struct` /// As a class. case `class` /// As an enum. case `enum` /// As a tuple. case tuple /// As a miscellaneous aggregate with a fixed set of children. case aggregate /// As a container that is accessed by index. case indexContainer /// As a container that is accessed by key. case keyContainer /// As a container that represents membership of its values. case membershipContainer /// As a miscellaneous container with a variable number of children. case container /// An Optional which can have either zero or one children. case optional /// An Objective-C object imported in Swift. case objCObject } /// The type returned by `_reflect(x)`; supplies an API for runtime /// reflection on `x`. public protocol _Mirror { /// The instance being reflected. var value: Any { get } /// Identical to `value.dynamicType`. var valueType: Any.Type { get } /// A unique identifier for `value` if it is a class instance; `nil` /// otherwise. var objectIdentifier: ObjectIdentifier? { get } /// The count of `value`'s logical children. var count: Int { get } /// Get a name and mirror for the `i`th logical child. subscript(i: Int) -> (String, _Mirror) { get } /// A string description of `value`. var summary: String { get } /// A rich representation of `value` for an IDE, or `nil` if none is supplied. var quickLookObject: PlaygroundQuickLook? { get } /// How `value` should be presented in an IDE. var disposition: _MirrorDisposition { get } } /// An entry point that can be called from C++ code to get the summary string /// for an arbitrary object. The memory pointed to by "out" is initialized with /// the summary string. @warn_unused_result @_silgen_name("swift_getSummary") public // COMPILER_INTRINSIC func _getSummary(out: UnsafeMutablePointer, x: T) { out.initialize(with: String(reflecting: x)) } /// Produce a mirror for any value. If the value's type conforms to /// `_Reflectable`, invoke its `_getMirror()` method; otherwise, fall back /// to an implementation in the runtime that structurally reflects values /// of any type. @warn_unused_result @_silgen_name("swift_reflectAny") public func _reflect(x: T) -> _Mirror /// Dump an object's contents using its mirror to the specified output stream. public func dump( value: T, to target: inout TargetStream, name: String? = nil, indent: Int = 0, maxDepth: Int = .max, maxItems: Int = .max ) -> T { var maxItemCounter = maxItems var visitedItems = [ObjectIdentifier : Int]() target._lock() defer { target._unlock() } _dump_unlocked( value, to: &target, name: name, indent: indent, maxDepth: maxDepth, maxItemCounter: &maxItemCounter, visitedItems: &visitedItems) return value } /// Dump an object's contents using its mirror to standard output. public func dump( value: T, name: String? = nil, indent: Int = 0, maxDepth: Int = .max, maxItems: Int = .max ) -> T { var stdoutStream = _Stdout() return dump( value, to: &stdoutStream, name: name, indent: indent, maxDepth: maxDepth, maxItems: maxItems) } /// Dump an object's contents. User code should use dump(). internal func _dump_unlocked( value: Any, to target: inout TargetStream, name: String?, indent: Int, maxDepth: Int, maxItemCounter: inout Int, visitedItems: inout [ObjectIdentifier : Int] ) { guard maxItemCounter > 0 else { return } maxItemCounter -= 1 for _ in 0.. 0 else { return } if let superclassMirror = mirror.superclassMirror { _dumpSuperclass_unlocked( mirror: superclassMirror, to: &target, indent: indent + 2, maxDepth: maxDepth - 1, maxItemCounter: &maxItemCounter, visitedItems: &visitedItems) } var currentIndex = mirror.children.startIndex for i in 0.. 0 { target.write(" more") } if remainder == 1 { target.write(" child)\n") } else { target.write(" children)\n") } return } let (name, child) = mirror.children[currentIndex] currentIndex = currentIndex.successor() _dump_unlocked( child, to: &target, name: name, indent: indent + 2, maxDepth: maxDepth - 1, maxItemCounter: &maxItemCounter, visitedItems: &visitedItems) } } /// Dump information about an object's superclass, given a mirror reflecting /// that superclass. internal func _dumpSuperclass_unlocked( mirror mirror: Mirror, to target: inout TargetStream, indent: Int, maxDepth: Int, maxItemCounter: inout Int, visitedItems: inout [ObjectIdentifier : Int] ) { guard maxItemCounter > 0 else { return } maxItemCounter -= 1 for _ in 0.. 0 else { return } if let superclassMirror = mirror.superclassMirror { _dumpSuperclass_unlocked( mirror: superclassMirror, to: &target, indent: indent + 2, maxDepth: maxDepth - 1, maxItemCounter: &maxItemCounter, visitedItems: &visitedItems) } var currentIndex = mirror.children.startIndex for i in 0.. 0 { target.write(" more") } if remainder == 1 { target.write(" child)\n") } else { target.write(" children)\n") } return } let (name, child) = mirror.children[currentIndex] currentIndex = currentIndex.successor() _dump_unlocked( child, to: &target, name: name, indent: indent + 2, maxDepth: maxDepth - 1, maxItemCounter: &maxItemCounter, visitedItems: &visitedItems) } } // -- Implementation details for the runtime's _Mirror implementation @_silgen_name("swift_MagicMirrorData_summary") func _swift_MagicMirrorData_summaryImpl( metadata: Any.Type, _ result: UnsafeMutablePointer ) public struct _MagicMirrorData { let owner: Builtin.NativeObject let ptr: Builtin.RawPointer let metadata: Any.Type var value: Any { @_silgen_name("swift_MagicMirrorData_value")get } var valueType: Any.Type { @_silgen_name("swift_MagicMirrorData_valueType")get } public var objcValue: Any { @_silgen_name("swift_MagicMirrorData_objcValue")get } public var objcValueType: Any.Type { @_silgen_name("swift_MagicMirrorData_objcValueType")get } var summary: String { let (_, result) = _withUninitializedString { _swift_MagicMirrorData_summaryImpl(self.metadata, $0) } return result } public func _loadValue() -> T { return Builtin.load(ptr) as T } } struct _OpaqueMirror : _Mirror { let data: _MagicMirrorData var value: Any { return data.value } var valueType: Any.Type { return data.valueType } var objectIdentifier: ObjectIdentifier? { return nil } var count: Int { return 0 } subscript(i: Int) -> (String, _Mirror) { _preconditionFailure("no children") } var summary: String { return data.summary } var quickLookObject: PlaygroundQuickLook? { return nil } var disposition: _MirrorDisposition { return .aggregate } } internal struct _TupleMirror : _Mirror { let data: _MagicMirrorData var value: Any { return data.value } var valueType: Any.Type { return data.valueType } var objectIdentifier: ObjectIdentifier? { return nil } var count: Int { @_silgen_name("swift_TupleMirror_count")get } subscript(i: Int) -> (String, _Mirror) { return _subscript_get(i) } @_silgen_name("swift_TupleMirror_subscript") func _subscript_get(i: Int) -> (T, _Mirror) var summary: String { return "(\(count) elements)" } var quickLookObject: PlaygroundQuickLook? { return nil } var disposition: _MirrorDisposition { return .tuple } } struct _StructMirror : _Mirror { let data: _MagicMirrorData var value: Any { return data.value } var valueType: Any.Type { return data.valueType } var objectIdentifier: ObjectIdentifier? { return nil } var count: Int { @_silgen_name("swift_StructMirror_count")get } subscript(i: Int) -> (String, _Mirror) { return _subscript_get(i) } @_silgen_name("swift_StructMirror_subscript") func _subscript_get(i: Int) -> (T, _Mirror) var summary: String { return _typeName(valueType) } var quickLookObject: PlaygroundQuickLook? { return nil } var disposition: _MirrorDisposition { return .`struct` } } struct _EnumMirror : _Mirror { let data: _MagicMirrorData var value: Any { return data.value } var valueType: Any.Type { return data.valueType } var objectIdentifier: ObjectIdentifier? { return nil } var count: Int { @_silgen_name("swift_EnumMirror_count")get } var caseName: UnsafePointer { @_silgen_name("swift_EnumMirror_caseName")get } subscript(i: Int) -> (String, _Mirror) { return _subscript_get(i) } @_silgen_name("swift_EnumMirror_subscript") func _subscript_get(i: Int) -> (T, _Mirror) var summary: String { let maybeCaseName = String(validatingUTF8: self.caseName) let typeName = _typeName(valueType) if let caseName = maybeCaseName { return typeName + "." + caseName } return typeName } var quickLookObject: PlaygroundQuickLook? { return nil } var disposition: _MirrorDisposition { return .`enum` } } @warn_unused_result @_silgen_name("swift_ClassMirror_count") func _getClassCount(_: _MagicMirrorData) -> Int // Like the other swift_*Mirror_subscript functions declared here and // elsewhere, this is implemented in the runtime. The Swift CC would // normally require the String to be returned directly and the _Mirror // indirectly. However, Clang isn't currently capable of doing that // reliably because the size of String exceeds the normal direct-return // ABI rules on most platforms. Therefore, we make this function generic, // which has the disadvantage of passing the String type metadata as an // extra argument, but does force the string to be returned indirectly. @warn_unused_result @_silgen_name("swift_ClassMirror_subscript") func _getClassChild(_: Int, _: _MagicMirrorData) -> (T, _Mirror) #if _runtime(_ObjC) @warn_unused_result @_silgen_name("swift_ClassMirror_quickLookObject") public func _getClassPlaygroundQuickLook( data: _MagicMirrorData ) -> PlaygroundQuickLook? #endif struct _ClassMirror : _Mirror { let data: _MagicMirrorData var value: Any { return data.value } var valueType: Any.Type { return data.valueType } var objectIdentifier: ObjectIdentifier? { return data._loadValue() as ObjectIdentifier } var count: Int { return _getClassCount(data) } subscript(i: Int) -> (String, _Mirror) { return _getClassChild(i, data) } var summary: String { return _typeName(valueType) } var quickLookObject: PlaygroundQuickLook? { #if _runtime(_ObjC) return _getClassPlaygroundQuickLook(data) #else return nil #endif } var disposition: _MirrorDisposition { return .`class` } } struct _ClassSuperMirror : _Mirror { let data: _MagicMirrorData var value: Any { return data.value } var valueType: Any.Type { return data.valueType } // Suppress the value identifier for super mirrors. var objectIdentifier: ObjectIdentifier? { return nil } var count: Int { return _getClassCount(data) } subscript(i: Int) -> (String, _Mirror) { return _getClassChild(i, data) } var summary: String { return _typeName(data.metadata) } var quickLookObject: PlaygroundQuickLook? { return nil } var disposition: _MirrorDisposition { return .`class` } } struct _MetatypeMirror : _Mirror { let data: _MagicMirrorData var value: Any { return data.value } var valueType: Any.Type { return data.valueType } var objectIdentifier: ObjectIdentifier? { return data._loadValue() as ObjectIdentifier } var count: Int { return 0 } subscript(i: Int) -> (String, _Mirror) { _preconditionFailure("no children") } var summary: String { return _typeName(data._loadValue() as Any.Type) } var quickLookObject: PlaygroundQuickLook? { return nil } // Special disposition for types? var disposition: _MirrorDisposition { return .aggregate } } extension ObjectIdentifier { @available(*, unavailable, message="use the 'UInt(_:)' initializer") public var uintValue: UInt { fatalError("unavailable function can't be called") } }