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()))