diff --git a/horrlang.py b/horrlang.py index 7269483..14a84b6 100755 --- a/horrlang.py +++ b/horrlang.py @@ -3,18 +3,50 @@ import sys +class InfiniteArray: + def __init__(self, values=None): + self.chunks = {} + if values is not None: + for key, value in enumerate(values): + self[key] = value + + def get_chunk(self, index): + if index not in self.chunks: + self.chunks[index] = [0 for i in xrange(4096)] + return self.chunks[index] + + def __getitem__(self, index): + return self.get_chunk(index / 4096)[index % 4096] + + def __setitem__(self, index, value): + self.get_chunk(index / 4096)[index % 4096] = value + class Machine: - def __init__(self, code): - self.mem = [ord(char) for char in code] + def __init__(self, code, read, write, user_data=None, max_cycles=None): + self.user_data = user_data + self.read = read + self.write = write + self.mem = InfiniteArray([ord(char) for char in code]) self.exc_ptr = 0 self.mem_ptr = 0 + self.max_cycles = max_cycles + self.cycles = 0 + + def cycle(self): + self.cycles += 1 + if self.max_cycles is not None: + if self.cycles >= self.max_cycles: + return False + return True def get_integer(self): parameter = 0 while chr(self.mem[self.exc_ptr + 1]) >= '0' \ and chr(self.mem[self.exc_ptr + 1]) <= '9': self.exc_ptr += 1 + if not self.cycle(): + return parameter parameter = parameter * 10 + (self.mem[self.exc_ptr] \ - ord('0')) if parameter == 0: @@ -23,27 +55,33 @@ class Machine: def L(self): self.mem_ptr -= self.get_integer() + if self.mem_ptr < 0: + self.mem_ptr = 0 def R(self): self.mem_ptr += self.get_integer() def O(self): - sys.stdout.write(chr(self.mem[self.mem_ptr])) + self.write(chr(self.mem[self.mem_ptr])) def I(self): - self.mem[self.mem_ptr] = ord(sys.stdin.read(1)) + self.mem[self.mem_ptr] = ord(self.read(1)) def N(self): self.exc_ptr += 1 search = self.mem[self.exc_ptr] while self.mem[self.exc_ptr] != search: self.exc_ptr += 1 + if not self.cycle(): + return def P(self): search = self.mem[self.exc_ptr + 1] self.exc_ptr -= 1 while self.mem[self.exc_ptr] != search: self.exc_ptr -= 1 + if not self.cycle(): + return def J(self): if self.mem[self.mem_ptr] != ord('0'): @@ -51,6 +89,8 @@ class Machine: self.exc_ptr -= 1 while self.mem[self.exc_ptr] != search: self.exc_ptr -= 1 + if not self.cycle(): + return def H(self): self.mem[self.mem_ptr] = self.mem[self.mem_ptr] + 1 @@ -58,13 +98,18 @@ class Machine: def K(self): self.mem[self.mem_ptr] = self.mem[self.mem_ptr] - 1 - def run(self): + def run(self, debug=False): while True: - if self.exc_ptr >= len(self.mem): - sys.exit(0) + if self.mem[self.exc_ptr] == 0: + return control = chr(self.mem[self.exc_ptr]) + if debug: + print control if hasattr(self, control): getattr(self, control)() self.exc_ptr += 1 + if not self.cycle(): + return -Machine(sys.argv[1]).run() +if __name__ == "__main__": + Machine(sys.argv[1], sys.stdin.read, sys.stdout.write, None).run()