├── .github
└── FUNDING.yml
├── Runtime.xcodeproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
└── project.pbxproj
├── Runtime
├── Platform.swift
├── Property.swift
├── Protocol.swift
├── DebugDescriptions.swift
├── Ivar.swift
├── Object.swift
├── OrderedSet.swift
├── Method.swift
├── Struct.swift
├── Runtime.swift
├── RootObject.swift
├── ClassBuilder.swift
├── Types.swift
├── Class.swift
└── Pointer.swift
├── RuntimeTests
├── Info.plist
├── Person.swift
└── RuntimeTests.swift
├── .gitignore
└── README.md
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: [NSExceptional]
4 |
--------------------------------------------------------------------------------
/Runtime.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Runtime/Platform.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Platform.swift
3 | // Runtime
4 | //
5 | // Created by Tanner on 10/18/17.
6 | // Copyright © 2017 Tanner Bennett. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | struct Platform {
12 | static let is64Bit = MemoryLayout.size == MemoryLayout.size
13 | }
14 |
--------------------------------------------------------------------------------
/Runtime/Property.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Property.swift
3 | // Runtime
4 | //
5 | // Created by Tanner on 10/18/17.
6 | // Copyright © 2017 Tanner Bennett. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public struct Property: Hashable, Equatable {
12 | public let name: String
13 | public let getter: Method
14 | public let setter: Method!
15 |
16 | public var type: Type {
17 | return self.getter.returnType
18 | }
19 |
20 | public var hashValue: Int {
21 | return self.name.hashValue
22 | }
23 |
24 | public static func ==(lhs: Property, rhs: Property) -> Bool {
25 | return lhs.name == rhs.name
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/RuntimeTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | .DS_Store
3 | build/
4 | *.pbxuser
5 | !default.pbxuser
6 | *.mode1v3
7 | !default.mode1v3
8 | *.mode2v3
9 | !default.mode2v3
10 | *.perspectivev3
11 | !default.perspectivev3
12 | !default.xcworkspace
13 | xcuserdata
14 | profile
15 | *.moved-aside
16 | DerivedData
17 | .idea/
18 |
19 | *.xcbkptlist
20 | *.xccheckout
21 | *.hmap
22 | *.ipa
23 |
24 | *.swp
25 | *.lock
26 | *.xcuserstate
27 |
28 | Luna.xcworkspace/xcuserdata/tantan.xcuserdatad/UserInterfaceState.xcuserstate
29 |
30 | .AppleDouble
31 | .LSOverride
32 |
33 | # Icon must end with two \r
34 | Icon
35 |
36 | # Thumbnails
37 | ._*
38 |
39 | # Files that might appear on external disk
40 | .Spotlight-V100
41 | .Trashes
42 |
43 | # Directories potentially created on remote AFP share
44 | .AppleDB
45 | .AppleDesktop
46 | Network Trash Folder
47 | Temporary Items
48 | .apdisk
--------------------------------------------------------------------------------
/Runtime/Protocol.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Protocol.swift
3 | // Runtime
4 | //
5 | // Created by Tanner on 10/18/17.
6 | // Copyright © 2017 Tanner Bennett. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public class Protocol: Hashable {
12 | public let name: String
13 | public let methods: [Method]
14 |
15 | public init(name: String, methods: [Method]) {
16 | self.name = name
17 | self.methods = methods
18 | }
19 |
20 | public var hashValue: Int {
21 | return self.name.hashValue
22 | }
23 |
24 | public static func ==(lhs: Protocol, rhs: Protocol) -> Bool {
25 | return lhs.name == rhs.name
26 | }
27 | }
28 |
29 | public extension Protocol {
30 | static var protocolList: [Protocol] = []
31 |
32 | public static func named(_ name: String) -> Protocol! {
33 | return Protocol.protocolList.filter { $0.name == name }.first
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Runtime/DebugDescriptions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DebugDescriptions.swift
3 | // Runtime
4 | //
5 | // Created by Tanner on 10/21/17.
6 | // Copyright © 2017 Tanner Bennett. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | extension Class: CustomDebugStringConvertible, CustomStringConvertible, CustomPlaygroundQuickLookable {
12 | public var customPlaygroundQuickLook: PlaygroundQuickLook {
13 | return .text(self.name)
14 | }
15 |
16 | public var description: String {
17 | return self.name
18 | }
19 |
20 | public var debugDescription: String {
21 | var me = self
22 | return """
23 | {
24 | isa: \(self.isa?.name ?? "nil"),
25 | superclass: \(self.superclass?.name ?? "nil"),
26 | methods: \(self.methods.count),
27 | properties: \(self.properties.count),
28 | protocols: \(self.protocols.count),
29 | }
30 | """
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Runtime/Ivar.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Ivar.swift
3 | // Runtime
4 | //
5 | // Created by Tanner on 10/18/17.
6 | // Copyright © 2017 Tanner Bennett. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public struct Ivar: Hashable {
12 | public typealias Stub = (name: String, type: Type)
13 |
14 | public let name: String
15 | public let type: Type
16 | public let offset: Int
17 |
18 | public var hashValue: Int {
19 | return self.name.hashValue
20 | }
21 |
22 | public static func ==(lhs: Ivar, rhs: Ivar) -> Bool {
23 | return lhs.name == rhs.name
24 | }
25 | }
26 |
27 | extension Ivar {
28 | static func make(from stubs: [Stub], _ offset: Int) -> [Ivar] {
29 | var offsett = offset
30 | return stubs.map { stub -> Ivar in
31 | defer { offsett += stub.type.size }
32 | return Ivar(name: stub.name, type: stub.type, offset: offsett)
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Runtime/Object.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Object.swift
3 | // Runtime
4 | //
5 | // Created by Tanner on 10/18/17.
6 | // Copyright © 2017 Tanner Bennett. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public struct Object {
12 | var isa: Class!
13 |
14 | public var getClass: Class {
15 | return self.isa
16 | }
17 |
18 | public func respondsTo(_ selector: SEL) -> Bool {
19 | return self.isa.getMethodIMP(selector) != nil
20 | }
21 | }
22 |
23 | extension Pointer: CustomStringConvertible, CustomDebugStringConvertible {
24 | public var debugDescription: String { return self.description }
25 | public var description: String {
26 | if Pointee.self is Object.Type {
27 | let this: id = ~self
28 | if this|.respondsTo("description") {
29 | return msgSend(this, "description")
30 | } else {
31 | return "<\(this|.getClass) \(self.raw.debugDescription)>"
32 | }
33 | }
34 |
35 | return self.raw.debugDescription
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Runtime/OrderedSet.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OrderedSet.swift
3 | // Runtime
4 | //
5 | // Created by Tanner on 10/23/17.
6 | // Copyright © 2017 Tanner Bennett. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | class OrderedSet: ExpressibleByArrayLiteral {
12 | var array: [T] = []
13 | var set: Set = []
14 |
15 | init() { }
16 |
17 | /// - Returns: true if the element was not already in the set, false otherwise
18 | @discardableResult
19 | func add(_ element: T) -> Bool {
20 | if self.set.insert(element).inserted {
21 | array.append(element)
22 | return true
23 | }
24 |
25 | return false
26 | }
27 |
28 | /// - Returns: true if all elements were not already in the set, false otherwise
29 | @discardableResult
30 | func addAll(_ elements: [T]) -> Bool {
31 | var allIn = true
32 | for e in elements {
33 | if !self.add(e) {
34 | allIn = false
35 | }
36 | }
37 |
38 | return allIn
39 | }
40 |
41 | required init(arrayLiteral elements: T...) {
42 | self.addAll(elements)
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Runtime/Method.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Method.swift
3 | // Runtime
4 | //
5 | // Created by Tanner on 10/18/17.
6 | // Copyright © 2017 Tanner Bennett. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public class Method: Hashable {
12 | public typealias Signauture = (returnType: Type, argumentTypes: [Type])
13 |
14 | public let name: String
15 | public var imp: IMP
16 | public let returnType: Type
17 | public let argumentTypes: [Type]
18 |
19 | public var signature: Signauture {
20 | return (self.returnType, self.argumentTypes)
21 | }
22 |
23 | public init(_ name: String, returns: Type = .void, args: [Type] = [], _ imp: @escaping IMP) {
24 | self.name = name
25 | self.returnType = returns
26 | self.argumentTypes = args
27 | self.imp = imp
28 | }
29 |
30 | convenience public init(name: String, signature: Signauture = (.void, []), _ imp: @escaping IMP) {
31 | self.init(name, returns: signature.returnType, args: signature.argumentTypes, imp)
32 | }
33 |
34 | public var hashValue: Int {
35 | return self.name.hashValue
36 | }
37 |
38 | public static func ==(lhs: Method, rhs: Method) -> Bool {
39 | return lhs.name == rhs.name
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Runtime/Struct.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Struct.swift
3 | // Runtime
4 | //
5 | // Created by Tanner on 10/18/17.
6 | // Copyright © 2017 Tanner Bennett. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | /// As of now, purely for metadata purposes.
12 | /// Provides no way to create and use structs.
13 | /// It may make more sense just to use standard Swift structs
14 | /// alongside instances of `Struct` for reflection purposes.
15 | public class Struct {
16 | let name: String
17 | let instanceSize: Int
18 |
19 | let ivars: [Ivar]
20 | let methods: [Method]
21 | let properties: [Property]
22 |
23 | public init(name: String, instanceSize: Int, ivars: [Ivar.Stub] = [], methods: [Method] = [], properties: [Property] = []) {
24 | self.name = name
25 | self.instanceSize = instanceSize
26 | self.ivars = Ivar.make(from: ivars, 0)
27 | self.methods = methods
28 | self.properties = properties
29 | }
30 | }
31 |
32 | public extension Struct {
33 | static var structList: [Struct] = []
34 |
35 | public static func named(_ name: String) -> Struct! {
36 | return Struct.structList.filter { $0.name == name }.first
37 | }
38 | }
39 |
40 | public extension Struct {
41 | public var describedAsTuple: String {
42 | return "(" + self.ivars.map({ ivar in
43 | if !ivar.name.isEmpty {
44 | return ivar.name + ": " + ivar.type.description
45 | } else {
46 | return ivar.type.description
47 | }
48 | }).joined(separator: ", ")
49 | }
50 |
51 | public var typeEncoding: String {
52 | return ""
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/Runtime/Runtime.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Runtime.swift
3 | // Runtime
4 | //
5 | // Created by Tanner on 10/18/17.
6 | // Copyright © 2017 Tanner Bennett. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public typealias id = Pointer