Skip to content

Instantly share code, notes, and snippets.

@erica
Last active April 21, 2023 17:14
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save erica/06d7e44f4f834757dc36 to your computer and use it in GitHub Desktop.
Save erica/06d7e44f4f834757dc36 to your computer and use it in GitHub Desktop.
Exploring
//
// 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)
}
@lilyball
Copy link

func _stdlib_getTypeName<T>(value: T) -> String returns the mangled name for a value. You could pass x to that in typestring() instead of returning "<Unknown>".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment