I'm writing a Python script to randomly generate C functions. This is my first time using classes in Python and I'm basically doing my best to pretend I'm using Java.
I'm looking for a review of my OOP, Python style, and in general whether or not I'm doing things in the "Pythonic" way, whatever that means.
import random
import sys
import string
# writes text to a stored outputString
# fetch the outputString later for outputting
class Output:
def __init__(self):
self.clear()
def clear(self):
self.outputString = ''
self.__lineStart = True
self.lineCount = 0
self.nestingLevel = 0
def __write(self, str):
self.outputString += str
def line(self):
self.__write('\n')
self.__lineStart = True
self.lineCount += 1
def output(self, str):
# start each line with tabs equal to nesting level
if(self.__lineStart == True):
for q in range(0, self.nestingLevel):
self.__write('\t')
self.__lineStart = False
self.__write(str)
def incNesting(self):
self.nestingLevel += 1
def decNesting(self):
self.nestingLevel -= 1
class Variables:
def __init__(self, varCount):
if varCount > 26:
raise Exception('Don\'t you think you\'re being a bit too aggressive?')
self.varCount = varCount
lowercase = list(string.ascii_lowercase)
self.variables = lowercase[0:varCount]
def Rand(self, count = 1):
if count > self.varCount:
raise Exception('Variables.Rand requested more variables than available')
elif count == 1:
return random.choice(self.variables)
elif count > 1:
return random.sample(self.variables, count)
else:
raise Exception('Variables.Rand invalid argument')
def InitStatement(self, out):
out.output('int ')
vars = []
for var in self.variables:
vars.append('%s = %i' % (var, random.randint(-0xFFFFFFF, 0xFFFFFFF)))
out.output(', '.join(vars))
out.output(';')
out.line()
class Action:
def __init__(self, variables, output):
self.variables = variables
self.out = output
self.labelCount = 0
class ControlSelector:
@staticmethod
def RandomControl(output, variables):
controlType = random.choice(ControlType.implementedTypes)
return ControlType.Make(controlType, output, variables)
class ControlType:
STATEMENT = 1
CONDITIONAL = 2
GOTO = 3
CALLGEN = 4
CALLREAL = 5
CALLAPI = 6
STOP = 7
allTypes = [STATEMENT, CONDITIONAL, GOTO, CALLGEN, CALLREAL, CALLAPI, STOP]
implementedTypes = [STATEMENT, CONDITIONAL, STOP]
@staticmethod
def Make(controlType, output, variables): # factory pattern .. I think
if(controlType == ControlType.STATEMENT):
return StatementControl(output, variables)
elif(controlType == ControlType.CONDITIONAL):
return ConditionalControl(output, variables)
elif(controlType == ControlType.STOP):
return StopControl(output, variables)
else:
raise Exception('ControlType.Make bad argument')
def __init__(self, output, variables):
self.out = output
self.variables = variables
def Exec(self):
raise NotImplementedError("")
def PutCode(self):
control = ControlSelector.RandomControl(self.out, self.variables)
control.Exec()
class PutCodeControl(ControlType):
def Exec(self):
self.PutCode()
class StatementControl(ControlType):
def PutAssignment(self):
dest, src = self.variables.Rand(2)
self.out.output(src + ' = ' + dest + ';')
self.out.line()
def Exec(self):
self.PutAssignment()
self.PutCode()
class ConditionalControl(ControlType):
def PutConditional(self):
first, second = self.variables.Rand(2)
self.out.output('if(')
self.out.output(first + ' == ' + second)
self.out.output('){')
self.out.line()
def PutCloseBrace(self):
self.out.output('}')
self.out.line()
def PutIf(self):
self.PutConditional()
self.out.incNesting()
self.PutCode()
self.PutCloseBrace()
self.out.decNesting()
def Exec(self):
self.PutIf()
self.PutCode()
class StopControl(ControlType):
def Exec(self):
return
class Function:
totalFuncCounter = 0
def __init__(self):
self.funcNum = Function.totalFuncCounter
Function.totalFuncCounter += 1
self.variables = Variables(8)
self.out = Output()
self.name = 'RandFunc' + str(self.funcNum)
self.action = Action(self.variables, self.out)
def __FunctionHeader(self):
self.out.output('int ' + self.name + '()')
self.out.line()
self.out.output('{')
self.out.line()
def __FunctionFooter(self):
retval = self.variables.Rand()
self.out.output('return ' + retval + ';')
self.out.line()
self.out.output('}')
self.out.line()
def __Generate(self):
# int functionname()
# {
self.__FunctionHeader()
# int a = 1, b = 2, etc
self.variables.InitStatement(self.out)
# [function body]
PutCodeControl(self.out, self.variables).Exec()
# return a;
self.__FunctionFooter()
def Generate(self, minLines = None):
if minLines == None:
minLines = 1 # < 1 will cause errors
while self.out.lineCount < minLines:
self.out.clear()
self.__Generate()
def OutputString(self):
return self.out.outputString
def PrintLongFunction():
func = Function()
func.Generate(minLines = 50)
sys.stdout.write(func.OutputString())
if __name__ == "__main__":
PrintLongFunction()
Sample output is available here.