Initial release.
[robmyers:dogecode.git] / dogecode / brainfuck.py
1 #!/usr/bin/python
2 #
3 # Brainfuck Interpreter
4 # Copyright 2011 Sebastian Kaspari
5 # Trivial mods 2014 Rob Myers
6 #
7 # Usage: ./brainfuck.py [FILE]
8
9 import sys
10 from dogecode.getch import getch
11
12 def execute(filename):
13   f = open(filename, "r")
14   evaluate(f.read())
15   f.close()
16
17
18 def evaluate(code):
19   code     = cleanup(list(code))
20   bracemap = buildbracemap(code)
21
22   cells, codeptr, cellptr = [0], 0, 0
23
24   while codeptr < len(code):
25     command = code[codeptr]
26
27     if command == ">":
28       cellptr += 1
29       if cellptr == len(cells): cells.append(0)
30
31     if command == "<":
32       cellptr = 0 if cellptr <= 0 else cellptr - 1
33
34     if command == "+":
35       cells[cellptr] = cells[cellptr] + 1 if cells[cellptr] < 255 else 0
36
37     if command == "-":
38       cells[cellptr] = cells[cellptr] - 1 if cells[cellptr] > 0 else 255
39
40     if command == "[" and cells[cellptr] == 0: codeptr = bracemap[codeptr]
41     if command == "]" and cells[cellptr] != 0: codeptr = bracemap[codeptr]
42     if command == ".": sys.stdout.write(chr(cells[cellptr]))
43     if command == ",": cells[cellptr] = ord(getch.getch())
44       
45     codeptr += 1
46
47
48 def cleanup(code):
49   return list(filter(lambda x: x in ['.', ',', '[', ']', '<', '>', '+', '-'], code))
50
51
52 def buildbracemap(code):
53   temp_bracestack, bracemap = [], {}
54
55   for position, command in enumerate(code):
56     if command == "[": temp_bracestack.append(position)
57     if command == "]":
58       start = temp_bracestack.pop()
59       bracemap[start] = position
60       bracemap[position] = start
61   return bracemap
62
63
64 def main():
65   if len(sys.argv) == 2: execute(sys.argv[1])
66   else: print("Usage:", sys.argv[0], "filename")
67
68 if __name__ == "__main__": main()
69