igendel

Mik-2 Interpreter

Oct 16th, 2020 (edited)
975
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. # Mik-2 Interpreter
  2. # by Ido Gendel, 2020
  3. # Work in progress, of course...
  4.  
  5. # How to program in Mik-2:
  6. # The character '#' marks a comment to end-of-line
  7. # First line is the memory initialization:
  8. #    [addr1]=value1, [addr2]=value2 ...
  9. #    Addresses are 0-based, values are signed integers
  10. # Following lines are commands:
  11. #    cmd param
  12. # Available commands:
  13. #    RD [addr] # Read value in memory address addr to register
  14. #    WR [addr] # Write value from register to memory address addr
  15. #    SU [addr] # Subtract value in memory address addr from value in register
  16. #    JZ line   # If value in register is 0, set program counter to line
  17. #
  18. # Command/line numbers are implicit, 0-based
  19. # WR to address [-1] will output the register value as ASCII to the terminal
  20. # JZ to a line number beyond the actual program will end the program
  21. # RD from an address not previously defined will return 0
  22.  
  23. COMMENT_IDENTIFIER = "#"
  24. PROGRAM_FILE = "program1.mik2"
  25.  
  26. memory = {}
  27. program_counter = 0
  28. register = 0
  29.  
  30. def addr_str_to_number(addr_str):
  31.     b1 = addr_str.find("[")
  32.     if b1 < 0:
  33.         return "Missing '['"
  34.     b2 = addr_str.find("]")
  35.     if b2 < b1:
  36.         return "Missing/misplaced ']'"
  37.     try:
  38.         value = int(addr_str[b1+1:b2])
  39.         if value < -1:
  40.             return "Illegal address"
  41.         else:
  42.             return value
  43.     except ValueError:
  44.         return "Address Error"
  45.  
  46.  
  47. def initialize_memory(memory_string):
  48.  
  49.     global memory
  50.    
  51.     assign_list = memory_string.split(",")
  52.     index = 0
  53.     for assign_str in assign_list:
  54.         eq = assign_str.find("=")
  55.         if eq <= 0:
  56.             return "Missing/misplaced '=' in item " + str(index)
  57.         addr = addr_str_to_number(assign_str[0:eq])
  58.         if type(addr) == str:
  59.             return "Address error in item '" + str(index) + "' : " + addr
  60.         try:
  61.             value = int(assign_str[eq + 1:])
  62.         except ValueError:
  63.             return "Value error in item " + str(index)
  64.         memory[addr] = value
  65.         index += 1
  66.        
  67.     return ""    
  68.  
  69.  
  70. def memory_write(key, value):
  71.     memory[key] = value
  72.     if -1 == key:
  73.         print(chr(value), end="")
  74.  
  75.  
  76. def memory_read(key):
  77.     if not (key in memory.keys()):
  78.         memory[key] = 0
  79.     return memory[key]    
  80.        
  81.  
  82. # command_str is stripped of all spaces
  83. def run_command(command_str):
  84.  
  85.     global program_counter
  86.     global register
  87.    
  88.     cmd = command_str[:2]
  89.     value_str = command_str[2:]
  90.     addr = addr_str_to_number(value_str)
  91.  
  92.     program_counter += 1
  93.  
  94.     if cmd == "RD":
  95.         if type(addr) == str:
  96.             return addr
  97.         else:
  98.             register = memory_read(addr)
  99.  
  100.     elif cmd == "WR":
  101.         if type(addr) == str:
  102.             return addr
  103.         else:
  104.             memory_write(addr, register)
  105.  
  106.     elif cmd == "SU":
  107.         if type(addr) == str:
  108.             return addr
  109.         else:
  110.             register -= memory_read(addr)
  111.  
  112.     elif cmd == "JZ":
  113.         try:
  114.             next_line = int(value_str)
  115.             if 0 == register:
  116.                 program_counter = next_line
  117.         except ValueError:
  118.             return "line value"
  119.     else:
  120.         return "Unknown command"
  121.  
  122.     return ""
  123.    
  124.  
  125. print("Mik-2 interpreter by Ido Gendel, 2020")
  126. # Read entire program from file
  127. try:
  128.     code_file = open(PROGRAM_FILE, "r")
  129. except FileNotFoundError:
  130.     print("File not found!")
  131.     exit()
  132. raw_code_lines = code_file.readlines()
  133.  
  134. # Remove comments, newline characters and spaces
  135. code_lines = []
  136. for line in raw_code_lines:
  137.     comment_index = line.find(COMMENT_IDENTIFIER)
  138.     if comment_index >= 0:
  139.         line = line[:comment_index]
  140.     if len(line) > 0:
  141.         if line[-1] == "\n":
  142.             line = line[:-1]
  143.         code_lines.append(line.replace(" ", ""))
  144.  
  145. # Parse and execute memory initialization line
  146. mem_issue = initialize_memory(code_lines[0])
  147. if mem_issue != "":
  148.     print("Error in line 0 (memory setup): " + mem_issue)
  149.     print(code_lines[0])
  150.     exit()
  151. del code_lines[0]
  152.  
  153. print("Memory: ", memory);
  154. print("Program started, press Ctrl+C to break...")
  155. print("----------")
  156.  
  157. while True:
  158.     if (program_counter < 0):
  159.         print("\n----------\nIllegal line number: " + str(program_counter))
  160.         break
  161.     if program_counter >= len(code_lines):
  162.         print("\n----------\nProgram completed.")
  163.         break
  164.  
  165.     command = code_lines[program_counter]
  166.     cmd_issue = run_command(command)
  167.     if cmd_issue != "":
  168.         print("\n----------\nCommand error in '" + command + "' : " + cmd_issue)
  169.         break
  170.  
  171. print("Memory:", memory)    
  172.    
  173.  
RAW Paste Data