#!/usr/bin/python
#
# Simulate a register machine
# According to the command set from
#  Informatik B, SS 09, FU Berlin, Frank Hoffmann,
#  http://www.inf.fu-berlin.de/lehre/SS09/infb/
#
# (c) 2009, Phillip Berndt
# Licensed GPLv3. Search gnu.org. If you fail to find it you are prohibited do
# anything with this code except executing it.
#
# Registers are available as c[i], indexed from 0
# Commands are counted from 1
# Input is available from c[1]..c[inf]
# Output is to be stored into c[0]
#
# Command set:
#  add i	Add c[i] to c[0]
#  cadd i	Add i to c[0]
#  mult,div,sub	Accordingly
#  load i	Load c[i] into c[0]
#  store i	Store c[0] into c[i]
#  cload i	Load i into c[0]
#  goto n	Goto line n
#  end		End execution
# 
# Lines starting with # are threated as comments
#
# Example program for faculty:
#  load 1
#  store 2
#  csub 1
#  store 1
#  if c0 == 0
#  goto 13
#  mult 2
#  store 2
#  load 1
#  csub 1
#  store 1
#  goto 5
#  load 2
#  end
#
import sys

sys.argv = sys.argv[1:]
if len(sys.argv) >= 1 and sys.argv[0] == "debug":
	debug = True
	sys.argv = sys.argv[1:]
else:
	debug = False
if len(sys.argv) < 1:
	print "Syntax: registerSimul [debug] <file> [..init..]"
	print
	sys.exit(1)

cmds = open(sys.argv[0]).readlines()
pos  = 0
registers = {}
registers[0] = 0
for i in range(1, len(sys.argv)):
	registers[i] = int(sys.argv[i])

def getr(a):
	return registers[int(a)] if int(a) in registers else 0

while True:
	try:
		cmd = cmds[pos].split()
		if debug:
			print "(Before) Pos: %d, Cmd: %s, Reg: %s" % (pos, cmd, registers)
		pos = pos + 1
		if cmd[0][0] == "#":
			continue
		if cmd[0] == "add":
			registers[0] += getr(cmd[1])
		elif cmd[0] == "cadd":
			registers[0] += int(cmd[1])
		elif cmd[0] == "sub":
			registers[0] -= getr(cmd[1])
		elif cmd[0] == "csub":
			registers[0] -= int(cmd[1])
		elif cmd[0] == "goto":
			pos = int(cmd[1]) - 1
		elif cmd[0] == "mult":
			registers[0] *= getr(cmd[1])
		elif cmd[0] == "cmult":
			registers[0] *= int(cmd[1])
		elif cmd[0] == "div":
			registers[0] /= getr(cmd[1])
		elif cmd[0] == "cdiv":
			registers[0] /= int(cmd[1])
		elif cmd[0] == "store":
			registers[int(cmd[1])] = registers[0]
		elif cmd[0] == "load":
			registers[0] = getr(cmd[1])
		elif cmd[0] == "cload":
			registers[0] = int(cmd[1])
		elif cmd[0] == "if":
			if not eval(" ".join(cmd[1:]), { "c": registers, "c0": registers[0] }, {}):
				pos += 1
		elif cmd[0] == "end":
			break
		else:
			print "Unknown command: ", cmd
			sys.exit(1)
		if debug:
			print "(After)  Pos: %d, Cmd: %s, Reg: %s" % (pos, cmd, registers)
	except:
		print "Execution error in line ", pos, ": ", " ".join(cmd)
		print "Registers were: ", registers
		print
		sys.exit(1)
print "Output: ", registers[0]
