# Mik-2 Interpreter
# by Ido Gendel, 2020
# Work in progress, of course...
# How to program in Mik-2:
# The character '#' marks a comment to end-of-line
# First line is the memory initialization:
# [addr1]=value1, [addr2]=value2 ...
# Addresses are 0-based, values are signed integers
# Following lines are commands:
# cmd param
# Available commands:
# RD [addr] # Read value in memory address addr to register
# WR [addr] # Write value from register to memory address addr
# SU [addr] # Subtract value in memory address addr from value in register
# JZ line # If value in register is 0, set program counter to line
#
# Command/line numbers are implicit, 0-based
# WR to address [-1] will output the register value as ASCII to the terminal
# JZ to a line number beyond the actual program will end the program
# RD from an address not previously defined will return 0
COMMENT_IDENTIFIER = "#"
PROGRAM_FILE = "program1.mik2"
memory = {}
program_counter = 0
register = 0
def addr_str_to_number(addr_str):
b1 = addr_str.find("[")
if b1 < 0:
return "Missing '['"
b2 = addr_str.find("]")
if b2 < b1:
return "Missing/misplaced ']'"
try:
value = int(addr_str[b1+1:b2])
if value < -1:
return "Illegal address"
else:
return value
except ValueError:
return "Address Error"
def initialize_memory(memory_string):
global memory
assign_list = memory_string.split(",")
index = 0
for assign_str in assign_list:
eq = assign_str.find("=")
if eq <= 0:
return "Missing/misplaced '=' in item " + str(index)
addr = addr_str_to_number(assign_str[0:eq])
if type(addr) == str:
return "Address error in item '" + str(index) + "' : " + addr
try:
value = int(assign_str[eq + 1:])
except ValueError:
return "Value error in item " + str(index)
memory[addr] = value
index += 1
return ""
def memory_write(key, value):
memory[key] = value
if -1 == key:
print(chr(value), end="")
def memory_read(key):
if not (key in memory.keys()):
memory[key] = 0
return memory[key]
# command_str is stripped of all spaces
def run_command(command_str):
global program_counter
global register
cmd = command_str[:2]
value_str = command_str[2:]
addr = addr_str_to_number(value_str)
program_counter += 1
if cmd == "RD":
if type(addr) == str:
return addr
else:
register = memory_read(addr)
elif cmd == "WR":
if type(addr) == str:
return addr
else:
memory_write(addr, register)
elif cmd == "SU":
if type(addr) == str:
return addr
else:
register -= memory_read(addr)
elif cmd == "JZ":
try:
next_line = int(value_str)
if 0 == register:
program_counter = next_line
except ValueError:
return "line value"
else:
return "Unknown command"
return ""
print("Mik-2 interpreter by Ido Gendel, 2020")
# Read entire program from file
try:
code_file = open(PROGRAM_FILE, "r")
except FileNotFoundError:
print("File not found!")
exit()
raw_code_lines = code_file.readlines()
# Remove comments, newline characters and spaces
code_lines = []
for line in raw_code_lines:
comment_index = line.find(COMMENT_IDENTIFIER)
if comment_index >= 0:
line = line[:comment_index]
if len(line) > 0:
if line[-1] == "\n":
line = line[:-1]
code_lines.append(line.replace(" ", ""))
# Parse and execute memory initialization line
mem_issue = initialize_memory(code_lines[0])
if mem_issue != "":
print("Error in line 0 (memory setup): " + mem_issue)
print(code_lines[0])
exit()
del code_lines[0]
print("Memory: ", memory);
print("Program started, press Ctrl+C to break...")
print("----------")
while True:
if (program_counter < 0):
print("\n----------\nIllegal line number: " + str(program_counter))
break
if program_counter >= len(code_lines):
print("\n----------\nProgram completed.")
break
command = code_lines[program_counter]
cmd_issue = run_command(command)
if cmd_issue != "":
print("\n----------\nCommand error in '" + command + "' : " + cmd_issue)
break
print("Memory:", memory)
Comments