Skip to content

Instantly share code, notes, and snippets.

@danzimm
Created February 16, 2017 22:53
Show Gist options
  • Select an option

  • Save danzimm/07263bd59ca55cfe9558412e58743275 to your computer and use it in GitHub Desktop.

Select an option

Save danzimm/07263bd59ca55cfe9558412e58743275 to your computer and use it in GitHub Desktop.
Generate msgSend wrappers for swift, written in swift
#!/usr/bin/env swift
import Foundation
extension Int {
var tabs: String {
return Array(count: self, repeatedValue: " ").joinWithSeparator("")
}
}
func printUsage() {
print("Usage: msgSendgen [numberOfArgs]")
}
guard Process.argc == 2 else {
printUsage()
exit(1)
}
guard let numberOfArgs = Int(Process.arguments[1]) where numberOfArgs >= 0 else {
printUsage()
exit(1)
}
func invokationFor(object: String, _ name: String, _ args: String, _ n: Int) -> String {
let args = ([object, "Selector(\(name))"] + (n > 0 ? ((0...(n-1)).map { "\(args)[\($0)]" }) : [])).joinWithSeparator(", ")
return "unsafeBitCast(objc_msgSend, Method\(n).self)(\(args))"
}
let initialDecls = [
"@_silgen_name(\"objc_msgSend\") func objc_msgSend_(_: AnyObject?, _: Selector) -> AnyObject?",
"let objc_msgSend = objc_msgSend_ as @convention(c) (AnyObject?, Selector) -> AnyObject?"
]
let structDecl = [
"struct Runtime {",
]
let typealiases = (0...numberOfArgs).map { (index: Int) -> String in
let prefix = " typealias Method\(index) = @convention(c) ("
let args = ["AnyObject?", "Selector"] + Array(count: index, repeatedValue: "AnyObject?")
let suffix = ") -> AnyObject?"
return prefix + args.joinWithSeparator(", ") + suffix
}
let middleStruct = [
" weak private(set) var object: AnyObject?",
"",
" init(_ cls: AnyClass) { self.object = cls }",
" init(_ object: AnyObject) { self.object = object }",
"",
" func call(name: String, args: [AnyObject?]) -> AnyObject? {",
" switch args.count {",
]
let cases = ((0...numberOfArgs).map { "\(2.tabs)case \($0): return " + invokationFor("object", "name", "args", $0) })
let endStruct = [
" default: return nil",
" }",
" }",
"}",
]
let firstHalf = initialDecls + [""] + structDecl + typealiases
let secondHalf = middleStruct + cases + endStruct
print((firstHalf + secondHalf).joinWithSeparator("\n"))
// vi:syntax=swift:softtabstop=4:tabstop=4:shiftwidth=4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment