diff --git a/bfcompiler.py b/bfcompiler.py new file mode 100644 index 0000000..96627ea --- /dev/null +++ b/bfcompiler.py @@ -0,0 +1,319 @@ +class CompileState(object): + def __init__(self): + self.vars = {} + self.cells = set() + self.currentCell = 0 + + def requestVar(self,name): + try: + return self.vars[name] + except: + cell = 0 + while cell in self.cells: + cell+=1 + self.vars[name] = cell + self.cells.add(cell) + return cell + + def releaseVar(self,name): + try: + cell = self.vars[name] + except KeyError: + return False + + del self.vars[name] + self.cells.remove(cell) + + def requestTempVar(self): + vid = object() + cell = self.requestVar(vid) + return vid, cell + + def incrementCell(self): + self.currentCell += 1 + + def decrementCell(self): + self.currentCell -= 1 + +class Command(object): + def __str__(self): + return self.__class__.__name__ + + def compile(self,state): + raise NotImplementedError + + +class SimpleRepeatedCommand(Command): + def __init__(self,repeats,command): + self.repeats = repeats + self.command = command + + def compile(self,state): + s = "" + for i in range(self.repeats): + s += self.command.compile(state) + return s + + def __str__(self): + return "Repeat(%d)(%s)" % (self.repeats, str(self.command)) + +class CompositeCommand(Command): + def __init__(self,commands): + self.commands = commands + + def compile(self,state): + s="" + for command in self.commands: + s+=command.compile(state) + return s + + def __str__(self): + return "[" + ",".join([ str(command) for command in self.commands]) + "]" + +class SimpleIncrement(Command): + def compile(self,state): + return '+' + +class SimpleDecrement(Command): + def compile(self,state): + return '-' + +class SimpleNextCell(Command): + def compile(self,state): + state.incrementCell() + return '>' + +class SimplePrevCell(Command): + def compile(self,state): + state.decrementCell() + return '<' + +class SimpleOutput(Command): + def compile(self,state): + return '.' + +class SimpleInput(Command): + def compile(self,state): + return ',' + +class SimpleLoopBegin(Command): + def compile(self,state): + return '[' + +class SimpleLoopEnd(Command): + def compile(self,state): + return ']' + +class SimpleLoop(Command): + def __init__(self,command): + self.command = command + + def compile(self,state): + return CompositeCommand([SimpleLoopBegin(), self.command, SimpleLoopEnd()]).compile(state) + +class SelectVariable(Command): + def __init__(self,variable): + self.variable = variable + + def compile(self,state): + d = state.requestVar(self.variable) - state.currentCell + if d < 0: + return SimpleRepeatedCommand(-d,SimplePrevCell()).compile(state) + elif d > 0: + return SimpleRepeatedCommand(d,SimpleNextCell()).compile(state) + else: + return "" + +class ClearCell(Command): + def compile(self,state): + return SimpleLoop(SimpleDecrement()).compile(state) + +class WriteConstant(Command): + def __init__(self,const): + self.const = const + + def compile(self,state): + return CompositeCommand([ClearCell(),SimpleRepeatedCommand(self.const, SimpleIncrement())]).compile(state) + +class SetConstant(Command): + def __init__(self,variable,const): + self.variable = variable + self.const = const + + def compile(self,state): + return CompositeCommand([SelectVariable(self.variable),WriteConstant(self.const)]).compile(state) + +SetVariable = SetConstant + +class Move(Command): + def __init__(self, source, dest): + self.source = source + self.dest = dest + + def compile(self,state): + return CompositeCommand([ + SelectVariable(self.dest), + ClearCell(), + SimpleAddition(self.source,self.dest) + ]).compile(state) + +class Copy(Command): + def __init__(self,source,dest): + self.source = source + self.dest = dest + + def compile(self,state): + tmp, _ = state.requestTempVar() + s = CompositeCommand([ + SelectVariable(self.dest), + ClearCell(), + SelectVariable(tmp), + ClearCell(), + SelectVariable(self.source), + SimpleLoop(CompositeCommand([ + SelectVariable(self.dest), + SimpleIncrement(), + SelectVariable(tmp), + SimpleIncrement(), + SelectVariable(self.source), + SimpleDecrement() + ])), + Move(tmp,self.source) + ]).compile(state) + state.releaseVar(tmp) + return s + +class SimpleAddition(Command): + def __init__(self, source, dest): + self.source = source + self.dest = dest + + def compile(self,state): + return CompositeCommand([ + SelectVariable(self.source), + SimpleLoop(CompositeCommand([ + SelectVariable(self.dest), + SimpleIncrement(), + SelectVariable(self.source), + SimpleDecrement(), + ])) + ]).compile(state) + +class Addition2(Command): + def __init__(self,source,dest): + self.source = source + self.dest = dest + + def compile(self,state): + tmp, _ = state.requestTempVar() + s = CompositeCommand([ + Copy(self.source,tmp), + SimpleAddition(tmp,self.dest) + ]).compile(state) + state.releaseVar(tmp) + return s + +class Condition(Command): + def __init__(self,condition,command): + self.condition = condition + self.command = command + + def compile(self,state): + return CompositeCommand([ + SelectVariable(self.condition), + SimpleLoop(CompositeCommand([ + self.command, + SelectVariable(self.condition), + ClearCell(), + ])), + ]).compile(state) + +class ConditionKeep(Command): + def __init__(self,condition,command): + self.condition = condition + self.command = command + + def compile(self,state): + tmp, _ = state.requestTempVar() + s = CompositeCommand([ + Copy(self.condition,tmp), + Condition(tmp,self.command) + ]).compile(state) + state.releaseVar(tmp) + return s + +class Booleanize(Command): + def __init__(self,variable): + self.variable = variable + + def compile(self,state): + tmp, _ = state.requestTempVar() + s = CompositeCommand([ + SelectVariable(tmp), + ClearCell(), + Condition(self.variable,CompositeCommand([ + SelectVariable(tmp), + SimpleIncrement() + ])), + Move(tmp,self.variable) + ]).compile(state) + state.releaseVar(tmp) + return s + +class Not(Command): + def __init__(self,variable): + self.variable = variable + + def compile(self,state): + tmp, _ = state.requestTempVar() + s = CompositeCommand([ + SelectVariable(tmp), + WriteConstant(1), + Condition(self.variable,CompositeCommand([ + SelectVariable(tmp), + SimpleDecrement() + ])), + Move(tmp,self.variable) + ]).compile(state) + state.releaseVar(tmp) + return s + +class And(Command): + def __init__(self,source,dest): + self.source = source + self.dest = dest + + def compile(self,state): + return ConditionKeep(self.dest, Move(self.source,self.dest)).compile(state) + +class Or(Command): + def __init__(self,source,dest): + self.source = source + self.dest = dest + + def compile(self,state): + return CompositeCommand([ + SimpleAddition(self.source, self.dest), + SelectVariable(self.dest), + Booleanize(self.dest) + ]).compile(state) + +if __name__ == "__main__": + c = CompositeCommand([ + SetVariable("a",2), + SetVariable("b",5), + Addition2("b","a"), + Copy("a","tmp"), + Or("tmp","b"), + ConditionKeep("tmp",CompositeCommand([ + SelectVariable("b"), + SimpleIncrement() + ])), + Not("tmp"), + Condition("tmp",CompositeCommand([ + SelectVariable("b"), + SimpleDecrement() + ])) + ]) + + print(c.compile(CompileState()))