igendel icon

Mik-2 Interpreter

igendel | PRO | 10/18/20 01:57:21 PM UTC (Edited) | 0 ⭐ | 2880 👁️ | Never ⏰ | []
Python |

4.6 KB

|

None

|

0 👍

/

0 👎

# 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