blob: bb3d8c331cd2c7048719945c3b103b687f5e3cfa [file] [log] [blame]
#!/usr/bin/env python
# This script outputs a Swift source with randomly-generated type definitions,
# which can be used for ABI or layout algorithm fuzzing.
# TODO: generate types with generics, existentials, compositions
from __future__ import print_function
import random
import sys
maxDepth = 5
maxMembers = 5
typesDefined = []
classesDefined = []
nextToDefine = 0
objcInterop = False
if len(sys.argv) >= 2:
if sys.argv[1] == "--objc":
objcInterop = True
if sys.argv[1] == "--help":
print("Usage: " + sys.argv[0] + " [--objc]", file=sys.stderr)
print("", file=sys.stderr)
print(" --objc Include ObjC-interop types", file=sys.stderr)
sys.exit(2)
random.seed()
if objcInterop:
print("import Foundation")
print()
def randomTypeList(depth):
count = random.randint(0, maxMembers)
result = "("
for i in xrange(count):
if i > 0:
result += ", "
result += randomTypeReference(depth + 1)
result += ")"
return result
def randomTypeReference(depth):
def nominal():
global typesDefined
allowNew = depth < maxDepth
bound = len(classesDefined) if allowNew else len(classesDefined) - 1
which = random.randint(0, bound)
if which < len(classesDefined):
return classesDefined[which]
newName = "T" + str(len(typesDefined))
def defineRandomRelatedType(name):
defineRandomNominalType(name, depth)
typesDefined.append((newName, defineRandomRelatedType))
return newName
def tuple():
return randomTypeList(depth + 1)
def metatype():
return "(" + randomTypeReference(depth + 1) + ").Type"
def leaf():
leaves = ["Int", "String", "Int8", "Int16", "Int32", "Int64",
"(() -> ())", "(@convention(c) () -> ())", "AnyObject"]
if objcInterop:
leaves += ["NSObject", "(@convention(block) () -> ())"]
return random.choice(leaves)
if depth < maxDepth:
kinds = [nominal, tuple, metatype, leaf, leaf, leaf, leaf, leaf]
else:
kinds = [leaf]
return random.choice(kinds)()
def defineRandomFields(depth, basename):
numMembers = random.randint(0, maxMembers)
for i in xrange(numMembers):
print(" var " + basename + str(i) + ": " +
randomTypeReference(depth + 1))
def defineRandomClass(name, depth):
global classesDefined
classesDefined.append(name)
print("class " + name, end="")
def inheritNSObject():
print(": NSObject", end="")
def inheritsOtherClass():
print(": ", end="")
name = "T" + str(len(typesDefined))
def defineRandomBaseClass(name):
defineRandomClass(name, depth)
typesDefined.append((name, defineRandomBaseClass))
print(name, end="")
def inheritsNothing():
pass
inheritances = [inheritsNothing]
if depth == 0:
# The contents of classes are interesting only for top-level type
inheritances += [inheritsOtherClass]
if objcInterop:
inheritances += [inheritNSObject]
random.choice(inheritances)()
print(" {")
# Prevent errors about lack of initializers
print(" init(" + name + ": ()) { fatalError() }")
# The contents of classes are interesting only for top-level type
if depth == 0:
defineRandomFields(depth, "x" + name)
print("}")
print()
def defineRandomNominalType(name, depth=0):
def struct():
print("struct " + name + " {")
defineRandomFields(depth, "x")
print("}")
print()
def clas():
defineRandomClass(name, depth)
def enum():
# TODO: indirect cases
print("enum " + name + " {")
numCases = random.randint(0, maxMembers)
for i in xrange(numCases):
print(" case x" + str(i) + randomTypeList(depth + 1))
print("}")
print()
kinds = [struct, clas, enum]
return random.choice(kinds)()
typesDefined.append(("Generated", defineRandomNominalType))
while nextToDefine < len(typesDefined):
name, definer = typesDefined[nextToDefine]
definer(name)
nextToDefine += 1