User:Marinus/96 interpreter
Jump to navigation
Jump to search
This is a 96 interpreter.
#!/usr/bin/env python # 96.py - 96 interpreter import sys # array that resizes automatically class Array: def __init__(self): self.arr = [] self.curpos = 0 def __getitem__(self, i): if i < len(self.arr): return self.arr[i] else: return 0 def __setitem__(self, i, v): # grow array if necessary if i >= len(self.arr): self.arr += [0] * (i - len(self.arr) + 1) self.arr[i] = v class PgmError(Exception): pass; class Interpreter: def __init__(self, code): self.code = code[:] self.acc = 0 self.markstack = [] self.ip = 0 # make memory arrays self.arrs = {} for arr in 'abcdefghijklmnopqrstuvwxyz': self.arrs[arr] = Array() self.curarr = self.arrs['a'] self.mp = 0 def run(self): while self.ip < len(self.code): try: self.docmd(self.code[self.ip]) self.ip += 1 except (PgmError, ZeroDivisionError): # error mode pc = 0 while self.ip < len(self.code)-1: self.ip += 1 c = self.code[self.ip] if c == '(': pc += 1 elif c == ';': if pc == 0: self.ip += 1 break elif c == ')': if pc == 0: self.ip += 1 break else: pc -= 1 elif c == ']': try:self.markstack.pop() except:pass def docmd(self, c): ## modify current element #### if c == '+': self.curarr[self.mp] += 1 elif c == '-': if self.curarr[self.mp] == 0: raise PgmError() else: self.curarr[self.mp] -= 1 elif c == '.': self.curarr[self.mp] = 0 elif c in '0123456789': self.curarr[self.mp] *= 10 self.curarr[self.mp] += ord(c) - ord('0') elif c == '@': self.curarr[self.mp] = self.acc ## memory pointer control #### elif c in 'abcdefghijklmnopqrstuvwxyz': self.mp = 0 self.curarr = self.arrs[c] elif c == ',': self.mp += 1 elif c == "'": if self.mp == 0: raise PgmError() else: self.mp -= 1 elif c == '#': self.mp = self.curarr[self.mp] elif c == '_': self.mp = 0 while self.curarr[self.mp] != 0: self.mp += 1 ## unary operators #### elif c == '^': self.acc += 1 elif c == '|': if self.acc == 0: raise PgmError() else: self.acc -= 1 elif c == ' ': self.acc = 0 elif c == ':': self.acc = self.curarr[self.mp] ## binary operators #### elif c == '&': self.acc += self.curarr[self.mp] elif c == '=': self.acc = abs(self.acc - self.curarr[self.mp]) elif c == '*': self.acc *= self.curarr[self.mp] elif c == '/': self.acc /= self.curarr[self.mp] elif c == '%': self.acc %= self.curarr[self.mp] elif c == '\\': self.acc = self.curarr[self.mp] / self.acc elif c == '`': self.acc = self.curarr[self.mp] % self.acc ## test operators #### elif c == '<': self.acc = [1,0][self.acc < self.curarr[self.mp]] elif c == '>': self.acc = [1,0][self.acc > self.curarr[self.mp]] ## i/o #### elif c == '?': line = sys.stdin.readline() if line=='': pass # eof -> no effect elif line.replace('\n','').isdigit() and line[0] != '0': self.acc = int(line) # number input else: # string input i = 0 for ch in line: self.curarr[i] = ord(ch) i += 1 self.curarr[i] = 0 elif c == '"': # string output i = 0 while self.curarr[i] != 0: sys.stdout.write(chr(self.curarr[i]%256)) i += 1 elif c == '$': # int output sys.stdout.write(str(self.acc) + ' ') ## advanced (ooh...) #### elif c == '~': foo = self.acc self.acc = self.curarr[self.mp] self.curarr[self.mp] = foo elif c == '!': self.docmd(chr(self.acc)%256) ## marks #### elif c == '[': self.markstack.append(self.ip + 1) elif c == ']': if len(self.markstack) > 0: self.ip = self.markstack[-1]-1 # -1 because ip is incremented after command is done ## error causing / functions # elif c == '(': if self.acc: raise PgmError() elif c == ';': raise PgmError() elif c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ': self.markstack.append(self.ip + 1) self.ip = self.code.index(c) elif c == '\n': if len(self.markstack) > 0: self.ip = self.markstack.pop()-1 def main(argv): if len(argv) != 2: print "Usage: 96.py <programfile>" sys.exit() try: code = file(argv[1]).read() except IOError, e: print "Can't open file:", e sys.exit() Interpreter(code).run() if __name__=='__main__': main(sys.argv)