Last active
April 21, 2023 17:14
-
-
Save erica/06d7e44f4f834757dc36 to your computer and use it in GitHub Desktop.
Exploring
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// explore.swift | |
// CmdLineTest | |
// | |
// Created by Erica Sadun on 6/25/14. | |
// Copyright (c) 2014 Erica Sadun. All rights reserved. | |
// | |
import Foundation | |
func QLString(x : QuickLookObject) -> String { | |
switch x { | |
case .Text(let s) : return "Text: " + s | |
case .Int(let i) : return "Int: " + "\(i)" | |
case .UInt(let u) : return "UInt: " + "\(u)" | |
case .Float(let f) : return "Float: " + "\(f)" | |
case .Image(let img) : return "Image: " + "[image]" | |
case .Sound(let snd) : return "Sound: " + "[sound]" | |
case .Color(let color) : return "Color: " + "\(color)" | |
case .BezierPath(let path) : return "Bezier: " + "[bezier]" | |
case .AttributedString(let s) : return "Attributed String: " + "\(s)" | |
case .Rectangle(let x, let y, let w, let h) : return "Rect: " + "[\(x), \(y), \(w), \(h)]" | |
case .Point(let x, let y) : return "Point: " + "(\(x), \(y))" | |
case .Size(let w, let h) : return "Size: " + "\(w), \(h)" | |
case .Logical(let v) : return v ? "Bool: " + "true" : "false" | |
case .Range(let a, let b) : return "Range: " + "\(a)..<\(b)" | |
case .View(let v) : return "View: " + "\(v)" | |
case .Sprite(let s) : return "Sprite: " + "[sprite]" | |
case .URL(let u) : return "URL: " + "\(u)" | |
default: return "<Unknown>" | |
} | |
} | |
func DispositionString(disposition : MirrorDisposition) -> String { | |
switch disposition { | |
case .Aggregate: return "Aggregate" | |
case .Class: return "Class" | |
case .Container: return "Container" | |
case .Enum: return "Enum" | |
case .IndexContainer : return "Index Container (Array)" | |
case .KeyContainer : return "Key Container (Dict)" | |
case .MembershipContainer : return "Membership Container" | |
case .Optional : return "Optional" | |
case .Struct: return "Struct" | |
case .Tuple: return "Tuple" | |
case .ObjCObject: return "ObjC Object" | |
} | |
} | |
func DispositionString(item : Any) -> String { | |
return DispositionString(reflect(item).disposition) | |
} | |
// Adapted from https://gist.github.com/mprudhom/69ec96f3d95c3d080e6a | |
// No where near complete. See https://www.mikeash.com/pyblog/friday-qa-2014-08-15-swift-name-mangling.html | |
func TypeDemangler(mangled: String) -> String { | |
if (!mangled.hasPrefix("_T")) {return mangled} | |
let scanner = NSScanner(string: mangled) | |
if (!scanner.scanString("_TtC", intoString: nil) && | |
!scanner.scanString("_TtV", intoString: nil)) { | |
return mangled | |
} | |
var demangled = "" | |
var len : Int = 0 | |
while (!scanner.atEnd && scanner.scanInteger(&len)) { | |
let range = Range(start:advance(mangled.startIndex, scanner.scanLocation), end: advance(mangled.startIndex, scanner.scanLocation + len)) | |
let part = mangled.substringWithRange(range) | |
if (countElements(demangled) > 0) { | |
demangled += "." | |
} | |
demangled += part | |
scanner.scanLocation += len | |
} | |
return demangled | |
} | |
extension NSObject { | |
class func demangledClassName() -> String { | |
return TypeDemangler(NSStringFromClass(self.dynamicType) as String) | |
} | |
} | |
func typestring(x : Any) -> String { | |
if let obj = x as? NSObject { | |
return TypeDemangler(NSStringFromClass(obj.dynamicType) as String) | |
} | |
// Value types | |
switch x { | |
// case let test as Array: return "Array" | |
// case let test as AssertString : return "AssertString" | |
// case let test as AutoreleasingUnsafeMutablePointer: return "AutoreleasingUnsafeMutablePointer" | |
// case let test as BidirectionalReverseView: return "" | |
case let test as Bool: return "Bool" | |
// case let test as CFunctionPointer: return "CFunctionPointer" | |
case let test as COpaquePointer : return "COpaquePointer" | |
case let test as CVaListPointer : return "CVaListPointer" | |
// case let test as ClosedInterval: return "ClosedInterval" | |
// case let test as CollectionOfOne: return "CollectionOfOne" | |
// case let test as ContiguousArray: return "ContiguousArray" | |
// case let test as Dictionary: return "Dictionary" | |
// case let test as DictionaryGenerator: return "DictionaryGenerator" | |
// case let test as DictionaryIndex: return "DictionaryIndex" | |
case let test as Double: return "Double" | |
// case let test as EmptyCollection: return "EmptyCollection" | |
// case let test as EmptyGenerator: return "EmptyGenerator" | |
// case let test as EnumerateGenerator: return "EnumerateGenerator" | |
// case let test as FilterCollectionView: return "FilterCollectionView" | |
// case let test as FilterCollectionViewIndex: return "FilterCollectionViewIndex" | |
// case let test as FilterGenerator: return "FilterGenerator" | |
// case let test as FilterSequenceView: return "FilterSequenceView" | |
case let test as Float : return "Float" | |
// case let test as Float80 : return "Float80" | |
// case let test as GeneratorOf: return "GeneratorOf" | |
// case let test as GeneratorOfOne: return "GeneratorOfOne" | |
// case let test as GeneratorSequence: return "GeneratorSequence" | |
// case let test as HalfOpenInterval: return "HalfOpenInterval" | |
// case let test as HeapBuffer: return "HeapBuffer" | |
// case let test as IndexingGenerator: return "IndexingGenerator" | |
case let test as Int : return "Int" | |
case let test as Int16 : return "Int16" | |
case let test as Int32 : return "Int32" | |
case let test as Int64 : return "Int64" | |
case let test as Int8 : return "Int8" | |
// case let test as LazyBidirectionalCollection: return "LazyBidirectionalCollection" | |
// case let test as LazyForwardCollection: return "LazyForwardCollection" | |
// case let test as LazyRandomAccessCollection: return "LazyRandomAccessCollection" | |
// case let test as LazySequence: return "LazySequence" | |
// case let test as MapCollectionView: return "MapCollectionView" | |
// case let test as MapSequenceGenerator: return "MapSequenceGenerator" | |
// case let test as MapSequenceView: return "MapSequenceView" | |
case let test as ObjectIdentifier : return "ObjectIdentifier" | |
// case let test as OnHeap: return "OnHeap" | |
// case let test as PermutationGenerator: return "PermutationGenerator" | |
// case let test as RandomAccessReverseView: return "RandomAccessReverseView" | |
// case let test as Range: return "Range" | |
// case let test as RangeGenerator: return "RangeGenerator" | |
case let test as RawByte : return "RawByte" | |
// case let test as Repeat: return "Repeat" | |
// case let test as ReverseBidirectionalIndex: return "ReverseBidirectionalIndex" | |
// case let test as ReverseRandomAccessIndex: return "ReverseRandomAccessIndex" | |
// case let test as SequenceOf: return "SequenceOf" | |
// case let test as SinkOf: return "SinkOf" | |
// case let test as Slice: return "Slice" | |
case let test as StaticString : return "StaticString" | |
// case let test as StrideThrough: return "StrideThrough" | |
// case let test as StrideThroughGenerator: return "StrideThroughGenerator" | |
// case let test as StrideTo: return "StrideTo" | |
// case let test as StrideToGenerator: return "StrideToGenerator" | |
case let test as String : return "String" | |
case let test as String.Index: return "String.Index" | |
case let test as String.UTF8View: return "String.UTF8View" | |
case let test as String.UnicodeScalarView: return "String.UnicodeScalarView" | |
case let test as String.UTF16View: return "String.UTF16View" | |
case let test as UInt : return "UInt" | |
case let test as UInt16 : return "UInt16" | |
case let test as UInt32 : return "UInt32" | |
case let test as UInt64 : return "UInt64" | |
case let test as UInt8 : return "UInt8" | |
case let test as UTF16 : return "UTF16" | |
case let test as UTF32 : return "UTF32" | |
case let test as UTF8 : return "UTF8" | |
case let test as UnicodeScalar : return "UnicodeScalar" | |
// case let test as Unmanaged: return "Unmanaged" | |
// case let test as UnsafeBufferPointer: return "UnsafeBufferPointer" | |
// case let test as UnsafeBufferPointerGenerator: return "UnsafeBufferPointerGenerator" | |
// case let test as UnsafeMutableBufferPointer: return "UnsafeMutableBufferPointer" | |
// case let test as UnsafeMutablePointer: return "UnsafeMutablePointer" | |
// case let test as UnsafePointer: return "UnsafePointer" | |
// case let test as Zip2: return "Zip2" | |
// case let test as ZipGenerator2: return "ZipGenerator2" | |
default: break | |
} | |
switch x { | |
case let test as [Double]: return "[Double]" | |
case let test as [Int]: return "[Int]" | |
case let test as [Bool]: return "[Bool]" | |
case let test as [String]: return "[String]" | |
default: break | |
} | |
return _stdlib_demangleName(_stdlib_getTypeName(x)) | |
} | |
func TupleDisposition(mirror : MirrorType) -> String { | |
if (mirror.disposition != .Tuple) {return ""} | |
var array = [String]() | |
for reference in 0..<mirror.count { | |
let (name, referenceMirror) = mirror[reference] | |
array += [typestring(referenceMirror.value)] | |
} | |
return array.reduce(""){"\($0),\($1)"} | |
// return NSArray(array:array).componentsJoinedByString(", ") as String | |
} | |
func ExploreItem(mirror : MirrorType, _ indent:Int = 0) { | |
var indentString = ""; indentString.extend(Repeat(count: indent * 4, repeatedValue:" " as Character)) | |
let rs = "" | |
var ts = typestring(mirror.value) | |
if (mirror.disposition == .Tuple) { | |
ts = TupleDisposition(mirror) | |
} | |
print("\(indentString)Item: "); dump(mirror.value) | |
if let qlobject = mirror.quickLookObject { | |
let qlstring = QLString(qlobject) | |
println("\(indentString)QuickLook: \(qlstring)\(rs)") | |
} | |
println("\(indentString)Disposition: \(DispositionString(mirror.disposition)) [\(ts)]\(rs)") | |
if let identifier = mirror.objectIdentifier { | |
println("\(indentString)Identifier: \(mirror.objectIdentifier)\(rs)") | |
} | |
println("\(indentString)ValueType: \(mirror.valueType)\(rs)") | |
println("\(indentString)Value: \(mirror.value)\(rs)") | |
println("\(indentString)Summary: \(mirror.summary)\(rs)") | |
if (mirror.count == 0) {return} | |
println("\(indentString)Subreferences: \(mirror.count) children\(rs)") | |
// All the rest is broken in beat 4, 5 | |
// dump(mirror) // broken in beta 4, 5 for multi-kids | |
for reference in 0..<mirror.count { | |
let (name, subreference) = mirror[reference] | |
println("\(indentString)Element Name: \(name)\(rs)") | |
ExploreItem(subreference, indent + 4) | |
} | |
} | |
func ExploreItem<T>(item : T) { | |
println("---------------------") | |
println("Exploring \(item)") | |
println("---------------------") | |
ExploreItem(reflect(item), 0) | |
} | |
postfix operator <*> {} | |
postfix func <*> (item : Any) { | |
ExploreItem(item) | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
func _stdlib_getTypeName<T>(value: T) -> String
returns the mangled name for a value. You could passx
to that intypestring()
instead of returning"<Unknown>"
.