Created
September 21, 2017 19:36
-
-
Save twostraws/1d154e956ff4bda56b4515a39d37b27b to your computer and use it in GitHub Desktop.
A Swift 4 port of Joe Groff's type-layout-fuzzer.py
This file contains 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
// | |
// type-layout-fuzzer.swift | |
// Paul Hudson / @twostraws / www.hackingwithswift.com | |
// | |
// This is a Swift 4 port of Joe Groff's type-layout-fuzzer.py. | |
// I haven't attempted to Swiftify the code – it's pretty | |
// much a line-by-line port. | |
// | |
// License: public domain / CC0 / seriously, do whatever | |
// you want with it. | |
import Foundation | |
let maxDepth = 5 | |
let maxMembers: UInt32 = 5 | |
var typesToDefine: [UInt32] = [0] | |
var nextName = 1 | |
extension Array { | |
mutating func shuffle() { | |
for i in 0 ..< (count - 1) { | |
let j = Int(arc4random_uniform(UInt32(count - i))) + i | |
swapAt(i, j) | |
} | |
} | |
} | |
func randomTypeList(_ depth: Int) -> String { | |
let count = arc4random_uniform(maxMembers) | |
var result = "(" | |
for i in 0 ..< count { | |
if i > 0 { | |
result += ", " | |
} | |
result += randomTypeReference(depth + 1) | |
} | |
result += ")" | |
return result | |
} | |
func randomTypeReference(_ depth: Int) -> String { | |
func nominal() -> String { | |
let which: UInt32 | |
if depth < maxDepth { | |
which = arc4random_uniform(UInt32(nextName)) | |
} else { | |
which = arc4random_uniform(UInt32(nextName - 1)) | |
} | |
if which == nextName { | |
typesToDefine.append(which) | |
nextName += 1 | |
} | |
return "T" + String(which) | |
} | |
func tuple() -> String { | |
return randomTypeList(depth + 1) | |
} | |
func metatype() -> String { | |
return "(" + randomTypeReference(depth + 1) + ").Type" | |
} | |
func leaf() -> String { | |
var leaves = ["Int", "String", "Int8", "Int16", "Int32", "Int64"] | |
leaves.shuffle() | |
return leaves[0] | |
} | |
var kinds: [() -> String] | |
if depth < maxDepth { | |
kinds = [nominal, tuple, metatype, leaf, leaf, leaf, leaf, leaf] | |
} else { | |
kinds = [leaf] | |
} | |
kinds.shuffle() | |
return kinds[0]() | |
} | |
func defineRandomProduct(_ kind: String, _ name: String, _ depth: Int) { | |
print(kind + " " + name + " {") | |
// Suppress errors about missing initializers | |
print(" init() { fatalError() }") | |
let numMembers = arc4random_uniform(maxMembers) | |
for i in 0 ..< numMembers { | |
print(" var x" + String(i) + ": " + randomTypeReference(depth + 1)) | |
} | |
print("}") | |
} | |
func defineRandomEnum(_ name: String, _ depth: Int) { | |
// TODO: indirect cases | |
print("enum " + name + " {") | |
let numCases = arc4random_uniform(maxMembers) | |
for i in 0 ..< numCases { | |
print(" case x" + String(i) + randomTypeList(depth + 1)) | |
} | |
print("}") | |
} | |
func defineRandomType(_ name: String, _ depth: Int) { | |
func `struct`() { | |
defineRandomProduct("struct", name, depth) | |
} | |
func `class`() { | |
defineRandomProduct("class", name, depth) | |
} | |
func `enum`() { | |
defineRandomEnum(name, depth) | |
} | |
var kinds: [() -> Void] = [`struct`, `class`, `enum`] | |
kinds.shuffle() | |
return kinds[0]() | |
} | |
while typesToDefine.count > 0 { | |
let ty = typesToDefine.removeFirst() | |
defineRandomType("T" + String(ty), 0) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment