319 lines
8.3 KiB
Python
319 lines
8.3 KiB
Python
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()))
|