Skip to content

Instantly share code, notes, and snippets.

@bellbind
Created July 9, 2009 11:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bellbind/143596 to your computer and use it in GitHub Desktop.
Save bellbind/143596 to your computer and use it in GitHub Desktop.
[Python] brainf**k interpreter with no AST
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