patternpythonMinorCanonical
Basic Brainfuck interpreter (part 2)
Viewed 0 times
brainfuckpartinterpreterbasic
Problem
I have this obsession with esoteric programming languages. So I decided to spiff up my previous Brainfuck interpreter.
If there are any issues, please mention them. All I'm looking for is any general improvements.
# Simple BrainF*** interpreter
# Class that stores lang variables
class Lang(object):
step = 0
cell = [0] * 30000
test_cell = [0] * 30000
pos = 0
test_pos = 0
loop = False
loop_ret = 0
# Main interpreter function
def interpreter():
code_input = raw_input('Code: ')
steps = len(code_input)
while Lang.step ':
if Lang.pos 30000:
Lang.pos = 0
elif code_input[Lang.step] == ' 0:
Lang.cell_pos -= 1
elif Lang.pos 30000:
Lang.test_pos += 1
elif Lang.test_pos 0:
Lang.test_pos -= 1
elif Lang.test_pos < 0:
Lang.test_pos = 30000
elif code_input[Lang.step] == "$":
if Lang.test_cell[Lang.test_pos] == Lang.cell[Lang.pos]:
print True
elif Lang.test_cell[Lang.test_pos] != Lang.cell[Lang.pos]:
print False
Lang.step += 1
# Running the program
if __name__ == "__main__":
interpreter()If there are any issues, please mention them. All I'm looking for is any general improvements.
Solution
In a word: dictionaries.
You have a class that only has class attributes and lacks any methods; that could just be a dictionary:
(Alternatively, if you really want attribute (
You have a whole bunch of
This makes your
along with e.g.:
(Note use of
This has two advantages:
You could also add some input validation:
(Note switch to
You have a class that only has class attributes and lacks any methods; that could just be a dictionary:
lang = dict(
step = 0,
cell = [0] * 30000,
test_cell = [0] * 30000,
pos = 0,
test_pos = 0,
loop = False,
loop_ret = 0
)(Alternatively, if you really want attribute (
foo.bar) rather than key (foo['bar']) access to the values, look into collections.namedtuple.)You have a whole bunch of
elifs; that could also be a dictionary (with some judiciously-named functions):commands = {
"+": increment_byte,
"-": decrement_byte,
...
}This makes your
interpreter loop:def interpreter():
lang = dict(...)
commands = {...}
code_input = raw_input('Code: ')
steps = len(code_input)
while lang['step'] < steps:
command = code_input[lang['step']]
if command in commands:
commands[command](lang)
lang['step'] += 1along with e.g.:
def increment_byte(lang):
"""Increment the byte at the data pointer."""
val = lang['cell'][lang['pos']]
lang['cell'][lang['pos']] = ((val + 1) % 256)(Note use of
% per @user50399's answer.)This has two advantages:
- very simple loop in
interpreter; and
commandsacts as a syntax guide (covering @Dagg's comment).
You could also add some input validation:
def accept_input(lang):
"""Accept one char of input, storing its value in the byte at the data pointer."""
while True:
try:
i = ord(raw_input("Enter char: "))
except TypeError:
pass
else:
if i in range(256):
lang['cell'][lang['pos']] = i
break
print("Not a valid input.")(Note switch to
ord per @user50399's answer.)Code Snippets
lang = dict(
step = 0,
cell = [0] * 30000,
test_cell = [0] * 30000,
pos = 0,
test_pos = 0,
loop = False,
loop_ret = 0
)commands = {
"+": increment_byte,
"-": decrement_byte,
...
}def interpreter():
lang = dict(...)
commands = {...}
code_input = raw_input('Code: ')
steps = len(code_input)
while lang['step'] < steps:
command = code_input[lang['step']]
if command in commands:
commands[command](lang)
lang['step'] += 1def increment_byte(lang):
"""Increment the byte at the data pointer."""
val = lang['cell'][lang['pos']]
lang['cell'][lang['pos']] = ((val + 1) % 256)def accept_input(lang):
"""Accept one char of input, storing its value in the byte at the data pointer."""
while True:
try:
i = ord(raw_input("Enter char: "))
except TypeError:
pass
else:
if i in range(256):
lang['cell'][lang['pos']] = i
break
print("Not a valid input.")Context
StackExchange Code Review Q#58873, answer score: 5
Revisions (0)
No revisions yet.