# This program interpretes code for Random Access Machine - RAM
# RAM is hypothetical computational machine, like Turing's machine,
# used for educational purposes and proving concepts
# may be useful for debugging homework (my case)
# feel free to modify to suit your needs
# usage: takes one parameter - filename of file with RAM machine code
import re
import sys
class Parser:
program = []
# instruction set, True - instruction HAS parameter
instructionSet = [
("READ", False), # acc = stdin
("WRITE", False), # acc -> stdout
("LOAD", True), # acc = mem[param]
("STORE", True), # mem[param] = acc
("ALOAD", True), # acc = mem[mem[param]]
("ASTORE", True), # mem[mem[param]] = acc
("ADD", True), # acc += mem[param]
("SUB", True), # acc -= mem[param]
("MUL", True), # acc *= mem[param]
("DIV", True), # acc = acc / mem[param]
("MOD", True), # acc = acc % mem[param]
("SET", True), # acc = param
("INC", True), # acc += param
("DEC", True), # acc -= param
("JUMP", True), # instruction pointer = param
("JGTZ", True), # instruction pointer = param if acc > 0
("JZERO", True), # instruction pointer = param if acc == 0
("JNEG", True), # instruction pointer = param if acc < 0
("AJUMP", False), # instruction pointer = mem[param]
("NOP", False), # no operation
("HALT", False)] # end program
def parseInput(self, filename):
pattern = "^(\w+)((\s+(-?\d+?))?)\s*$"
f = open(filename, "r")
for line in f:
line = line.split("#")[0]
if(re.match(pattern, line)):
parsedLine = re.search(pattern, line)
instruction = parsedLine.group(1)
parameter = parsedLine.group(4)
hasParameter = False if parameter == None else True
if((instruction, hasParameter) in self.instructionSet):
if(hasParameter == True):
self.program.append((instruction, parameter))
else:
self.program.append((instruction, None))
else:
print "Unknown instruction "+instruction
sys.exit()
else:
print "Unknown instruction "+line
sys.exit()
if(self.program[-1][0] != "HALT"):
self.program.append(("HALT", False))
return self.program
class Interpreter:
program = []
def __init__(self, inputProgram):
self.program = inputProgram
def runProgram(self):
acc = 0 # accumulator
ip = 0 # instruction pointer
mem = dict() # memory
instr = self.program[ip][0]
param = self.program[ip][1]
while(instr != "HALT"):
ip += 1
if(instr == "READ"):
acc = int(sys.stdin.readline())
elif(instr == "WRITE"):
print acc
elif(instr == "LOAD"):
if(int(param) not in mem):
mem[int(param)] = 0
acc = mem[int(param)]
elif(instr == "STORE"):
mem[int(param)] = acc
elif(instr == "ALOAD"):
if(mem[int(param)] not in mem):
mem[mem[int(param)]] = 0
acc = mem[mem[int(param)]]
elif(instr == "ASTORE"):
mem[mem[int(param)]] = acc
elif(instr == "ADD"):
if(int(param) not in mem):
mem[int(param)] = 0
acc = acc + mem[int(param)]
elif(instr == "SUB"):
if(int(param) not in mem):
mem[int(param)] = 0
acc = acc - mem[int(param)]
elif(instr == "MUL"):
if(int(param) not in mem):
mem[int(param)] = 0
acc = acc * mem[int(param)]
elif(instr == "DIV"):
if(int(param) not in mem):
mem[int(param)] = 0
acc = acc / mem[int(param)]
elif(instr == "MOD"):
if(int(param) not in mem):
mem[int(param)] = 0
acc = acc % mem[int(param)]
elif(instr == "SET"):
acc = int(param)
elif(instr == "INC"):
acc = acc + int(param)
elif(instr == "DEC"):
acc = acc - int(param)
elif(instr == "JUMP"):
ip = int(param)
elif(instr == "JGTZ"):
if(acc > 0):
ip = int(param)
elif(instr == "JZERO"):
if(acc == 0):
ip = int(param)
elif(instr == "JNEG"):
if(acc < 0):
ip = int(param)
elif(instr == "AJUMP"):
ip = acc
instr = program[ip][0]
param = program[ip][1]
if(len(sys.argv) >= 2):
filename = sys.argv[1]
else:
print "No input file"
sys.exit()
parser = Parser()
program = parser.parseInput(filename)
interpreter = Interpreter(program)
interpreter.runProgram()