Find file
Fetching contributors…
Cannot retrieve contributors at this time
executable file 249 lines (195 sloc) 4.91 KB
#!/usr/bin/env python
import sys
OPCODES = {
'NOP': 0,
'HALT': 1,
'LOAD': 6,
'SAVE': 7,
'PUSH': 10,
'POP': 11,
'DUP': 12,
'JMP': 16,
'CALL': 17,
'RET': 18,
'JLT': 20,
'JLTE': 21,
'JE': 22,
'JNE': 23,
'JGTE': 24,
'JGT': 25,
# These instructions are more natural for stack-based machines.
'CMPLT': 30,
'CMPLTE': 31,
'CMPE': 32,
'CMPNE': 33,
'CMPGTE': 34,
'CMPGT': 35,
'MUL': 43,
'DIV': 44,
'ADD': 45,
'SUB': 46,
'PRINT': 50,
'DEBUG': 51
}
NAMES = dict((v,k) for k, v in OPCODES.iteritems())
# Set global name for each opcode
module = sys.modules[__name__]
for name, value in OPCODES.iteritems():
setattr(module, name, value)
class Machine:
def __init__(self, sequence):
self.offset = 0
self.sequence = sequence
self.stack = []
def step(self):
instruction = NAMES[self.sequence[self.offset]]
method = getattr(self, "instruction_%s" % instruction.lower())
method()
# print `self.offset` + ": Executing " + `instruction` + " stack: " + `self.stack`
return self.offset >= 0 and self.offset < len(self.sequence)
def run(self):
result = True
while result:
result = self.step()
def instruction_nop(self):
self.offset += 1
def instruction_halt(self):
self.offset = -1
# Basic absolute address load/save unit
def instruction_load(self):
self.offset += 1
address = self.sequence[self.offset]
self.stack.append(self.sequence[address])
self.offset += 1
def instruction_save(self):
self.offset += 1
address = self.sequence[self.offset]
self.sequence[address] = self.stack.pop()
self.offset += 1
# Basic stack manipulation
def instruction_push(self):
self.offset += 1
self.stack.append(self.sequence[self.offset])
self.offset += 1
def instruction_pop(self):
self.offset += 1
self.stack.pop()
def instruction_dup(self):
self.offset += 1
self.stack.append(self.stack[-1])
def instruction_jmp(self):
self.offset += 1
address = self.sequence[self.offset]
self.offset = address
def instruction_call(self):
self.offset += 1
self.stack.append(self.offset + 1)
address = self.sequence[self.offset]
self.offset = address
def instruction_ret(self):
address = self.stack.pop()
self.offset = address
# Jump based on the result of a subtraction
def instruction_jlt(self):
self.offset += 1
address = self.sequence[self.offset]
value = self.stack.pop()
self.offset += 1
if value > 0:
self.offset = address
def instruction_jlte(self):
self.offset += 1
address = self.sequence[self.offset]
value = self.stack.pop()
self.offset += 1
if value >= 0:
self.offset = address
def instruction_je(self):
self.offset += 1
address = self.sequence[self.offset]
value = self.stack.pop()
self.offset += 1
if value == 0:
self.offset = address
def instruction_jne(self):
self.offset += 1
address = self.sequence[self.offset]
value = self.stack.pop()
self.offset += 1
if value != 0:
self.offset = address
def instruction_jgte(self):
self.offset += 1
address = self.sequence[self.offset]
value = self.stack.pop()
self.offset += 1
if value <= 0:
self.offset = address
def instruction_jgt(self):
self.offset += 1
address = self.sequence[self.offset]
value = self.stack.pop()
self.offset += 1
if value < 0:
self.offset = address
# Basic comparision support
def instruction_cmplt(self):
self.offset += 1
b = self.stack.pop()
a = self.stack.pop()
self.stack.append(int(a < b))
def instruction_cmplte(self):
self.offset += 1
b = self.stack.pop()
a = self.stack.pop()
self.stack.append(int(a <= b))
def instruction_cmpe(self):
self.offset += 1
b = self.stack.pop()
a = self.stack.pop()
self.stack.append(int(a == b))
def instruction_cmpne(self):
self.offset += 1
b = self.stack.pop()
a = self.stack.pop()
self.stack.append(int(a != b))
def instruction_cmpgt(self):
self.offset += 1
b = self.stack.pop()
a = self.stack.pop()
self.stack.append(int(a > b))
def instruction_cmpgte(self):
self.offset += 1
b = self.stack.pop()
a = self.stack.pop()
self.stack.append(int(a >= b))
# Basic arithmetic
def instruction_mul(self):
self.offset += 1
self.stack.append(self.stack.pop() * self.stack.pop())
def instruction_div(self):
self.offset += 1
self.stack.append(self.stack.pop() / self.stack.pop())
def instruction_add(self):
self.offset += 1
self.stack.append(self.stack.pop() + self.stack.pop())
def instruction_sub(self):
self.offset += 1
self.stack.append(self.stack.pop() - self.stack.pop())
def instruction_print(self):
self.offset += 1
print self.stack[-1]
def instruction_debug(self):
self.offset += 1
self.debug()
def debug(self):
print "-- Machine State --"
print "Sequence: " + `self.sequence`
print "Stack: " + `self.stack`
print "Offset: " + `self.offset`
if __name__ == '__main__':
buffer = sys.stdin.read()
code = eval(buffer)
machine = Machine(code)
machine.run()
machine.debug()