horrlang/horrlang.py

120 lines
3.4 KiB
Python
Executable File

#!/usr/bin/env python
# -*- coding: utf-8 -*-
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, read, write, max_cycles=None):
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 self.mem[self.exc_ptr + 1] >= 0x30 \
and self.mem[self.exc_ptr + 1] <= 0x39:
self.exc_ptr += 1
if not self.cycle():
return parameter
parameter = parameter * 10 + (self.mem[self.exc_ptr] \
- ord('0'))
if parameter == 0:
parameter = 1
return parameter
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):
char = self.mem[self.mem_ptr]
if char > 0 and char < 256:
self.write(chr(char))
def I(self):
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'):
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 H(self):
self.mem[self.mem_ptr] = self.mem[self.mem_ptr] + 1
def K(self):
self.mem[self.mem_ptr] = self.mem[self.mem_ptr] - 1
def run(self, debug=False):
while True:
if self.mem[self.exc_ptr] == 0:
return
char = self.mem[self.exc_ptr]
if char > 0 and char < 256:
control = chr(char)
if debug:
print control
if hasattr(self, control):
getattr(self, control)()
self.exc_ptr += 1
if not self.cycle():
return
if __name__ == "__main__":
Machine(sys.argv[1], sys.stdin.read, sys.stdout.write,
int(sys.argv[2]) if len(sys.argv) > 2 else None).run()