Created
July 9, 2009 11:51
-
-
Save bellbind/143596 to your computer and use it in GitHub Desktop.
[Python] brainf**k interpreter with no AST
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sys | |
class Engine(object): | |
"""Brainf**k interpreter. | |
usage: | |
bf = Engine() | |
bf("++++++++++++++.") | |
""" | |
def __init__(self): | |
self.insts = { | |
">": self._pinc, | |
"<": self._pdec, | |
"+": self._vinc, | |
"-": self._vdec, | |
".": self._putc, | |
",": self._getc, | |
"[": self._jump, | |
"]": self._loop, | |
} | |
pass | |
def __call__(self, code="", | |
input=sys.stdin, output=sys.stdout, bufsize=30000): | |
env = _Env(input, output, bufsize) | |
ip = 0 | |
while ip < len(code): | |
inst = self.insts.get(code[ip], self._noop) | |
ip = inst(env, code, ip) | |
pass | |
return env | |
def _noop(self, env, code, ip): return ip + 1 | |
def _pinc(self, env, code, ip): env.pinc(); return ip + 1 | |
def _pdec(self, env, code, ip): env.pdec(); return ip + 1 | |
def _vinc(self, env, code, ip): env.vinc(); return ip + 1 | |
def _vdec(self, env, code, ip): env.vdec(); return ip + 1 | |
def _putc(self, env, code, ip): env.putc(); return ip + 1 | |
def _getc(self, env, code, ip): env.getc(); return ip + 1 | |
def _jump(self, env, code, ip): | |
if env.value() != 0: return ip + 1 | |
opens = 0 | |
while opens >= 0: | |
ip += 1 | |
w = code[ip] | |
if w == "]": opens -= 1 | |
if w == "[": opens += 1 | |
pass | |
return ip + 1 | |
def _loop(self, env, code, ip): | |
if env.value() == 0: return ip + 1 | |
closes = 0 | |
while closes >= 0: | |
ip -= 1 | |
w = code[ip] | |
if w == "]": closes += 1 | |
if w == "[": closes -= 1 | |
pass | |
return ip + 1 | |
pass | |
class _Env(object): | |
def __init__(self, input, output, bufsize): | |
self.input = input | |
self.output = output | |
self.buf = [0] * bufsize | |
self.index = 0 | |
pass | |
def value(self): | |
return self.buf[self.index] | |
def pinc(self): self.index += 1 | |
def pdec(self): self.index -= 1 | |
def vinc(self): self.buf[self.index] += 1 | |
def vdec(self): self.buf[self.index] -= 1 | |
def putc(self): self.output.write(chr(self.buf[self.index])) | |
def getc(self): self.buf[self.index] = ord(self.input.read(1)) | |
pass | |
if __name__ == "__main__": | |
code = """ | |
+++++++++[>++++++++>+++++++++++>+++++<<<-]>.>++.+++++++..+++.>-. | |
------------.<++++++++.--------.+++.------.--------.>+. | |
>++++++++++. | |
""" # "Hello, world!\n" from Wikipedia | |
if len(sys.argv) > 1: code = sys.argv[1] | |
engine = Engine() | |
engine(code) | |
pass |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment