RAM Model of Computation

Random Access Machine (RAM) is a theoretical model of computing that consists of a very basic set of operations that operate on a set of "registers" to describe effective computability. In this assignment, we will implement a Python implementation of RAM. The RAM model consists of an indefinite number of registers, R1, R2, ..., each capable of storing a natural number. The instruction set consists of the following 7 instructions:
  1. INC Ri, increment the contents of register Ri by 1.
  2. DEC Ri, decrement the contents of register Ri by 1; keep Ri unchanged if Ri is 0.
  3. CLR Ri, set the contents of register Ri to 0.
  4. MOV Ri Rj, replace the contents of register Ri by the contents of Rj, leaving Rj the same.
  5. JMP N, next instruction to execute is set to the one with label N.
  6. Rj JMP N, if contents of Rj is 0 the next instruction to execute is set to the one with label N, otherwise the instruction that follows executes as usual.
  7. CONTINUE, do nothing.
Any of the above instructions, when used in a RAM program, may be preceded by a label Ni:, where i is a natural number. A RAM program consists of two parts: the first part assigns values to registers and the second part is a finite sequence of instructions, usually ending with the CONTINUE instruction. The RAM program may contain comment lines that begin with a #.

It is possible to use a register (in the second part of the program) without assigning it a value in the first part of the program. Such registers should be assumed to have a value of 0.

An example of a RAM program is shown below (p1.ram):

# Program to add two numbers
# inputs are in r1 and r2
# output, as always, is in r1
#
# initialize input registers
r1 = 9
R2 = 3
#
# begin program
n0: R2 JMP N1
    INC R1
    DEC R2
    JMP N0
N1: CONTINUE
The execution of a RAM program starts with the assignment of values to registers and then executing the instructions in the second part one at a time in sequence. The sequence may be altered by one of the the JMP instructions. The RAM program terminates when it executes the CONTINUE instruction.

Write a Python program that executes a RAM program stored in a file whose name is provided as command line input. An optional -d command line parameter may be provided to execute the RAM program in debug mode in which each instruction that is executed is displayed. Two sample runs are shown below:

Mac-mini:ram raj$ python3 RAM.py p1.ram
Input:
R1 ==> 9
R2 ==> 3

Output:
R1 = 12

Mac-mini:ram raj$ python3 RAM.py -d p1.ram
Input:
R1 ==> 9
R2 ==> 3

Executing: N0:	R2 JMP N1
Executing: 	INC R1
Executing: 	DEC R2
Executing: 	JMP N0
Executing: N0:	R2 JMP N1
Executing: 	INC R1
Executing: 	DEC R2
Executing: 	JMP N0
Executing: N0:	R2 JMP N1
Executing: 	INC R1
Executing: 	DEC R2
Executing: 	JMP N0
Executing: N0:	R2 JMP N1
Executing: N1:	CONTINUE

Output:
R1 = 12
Mac-mini:ram raj$ 

Dictionaries to the rescue!!

To solve this assignment, we will resort to the dictionary data structure of Python. In particular, we will record the values of registers, the instruction number for labels, and inner details of individual instructions in dictionaries. Here are the three variables that you would have to construct and manipulate in the program:
registers = {'R1': 9, 'R2': 3}

code = [ {'labeldef': 'N0', 'opcode': 'CJMP', 'register1': 'R2', 'jmplabel': 'N1'}, 
         {'opcode': 'INC', 'register1': 'R1'}, 
         {'opcode': 'DEC', 'register1': 'R2'}, 
         {'opcode': 'UJMP', 'jmplabel': 'N0'}, 
         {'labeldef': 'N1', 'opcode': 'CONTINUE'}
       ]

labels = {'N0': 0, 'N1': 4}

Few RAM programs for your testing purposes:

$ more p1.ram
# Program to add two numbers
# inputs are in r1 and r2
# output, as always, is in r1
#
# initialize input registers
r1 = 9
R2 = 3
#
# begin program
n0: R2 JMP N1
    INC R1
    DEC R2
    JMP N0
N1: CONTINUE

$ more p2.ram
R1 = 19
R2 = 3

        MOV R3 R2
N1:     R1 JMP N4
        MOV R2 R3
N2:     R2 JMP N3
        DEC R1
        DEC R2
        R1 JMP N4
        JMP N2
N3:     INC R4
        JMP N1
N4:     R2 JMP N5
        MOV R1 R4
        CONTINUE
N5:     INC R4
        MOV R1 R4
        CONTINUE

$ more p3.ram
R1 = 3			
R2 = 5

	MOV R3 R1		
N1:	DEC R2			
	R2 JMP N4
	MOV R6 R3		
	MOV R5 R1		
N2:	DEC R5			
	R5 JMP N1
	MOV R4 R6
N3:	R4 JMP N2
	INC R3			
	DEC R4			
	JMP N3
N4:	MOV R1 R3		
	CONTINUE

$ more p4.ram
r3 = 9
r2 = 3
n1: inc r1
  dec r2
  r2 jmp n3
n2: inc r1
  dec r3
  r3 jmp n2
n3: continue
p1.ram, p2.ram, p3.ram, p4.ram.

Submit: RAM.py