Created
November 13, 2016 18:16
-
-
Save Bruntaz/c90d94d94836f7f565c0b502d3bd0544 to your computer and use it in GitHub Desktop.
A first pass at a brainfuck implementation written in Python. It could easily be made more efficient (by removing unnecessary characters before executing etc.) but the code is pretty clean.
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
def executeBrainfuck(brainfuckCode): | |
valueList = [0] | |
listPointer = 0 | |
programCounter = 0 | |
programStack = [] | |
while programCounter < len(brainfuckCode): | |
instruction = brainfuckCode[programCounter] | |
if instruction == ">": # Increment pointer | |
# If list isn't long enough, increase length | |
if listPointer + 1 == len(valueList): | |
valueList.append(0) | |
listPointer += 1 | |
elif instruction == "<": # Decrement pointer | |
listPointer -= 1 | |
if listPointer < 0: # Pointer out of range | |
raise Exception("listPointer is negative") | |
elif instruction == "+": # Increment value | |
valueList[listPointer] += 1 | |
elif instruction == "-": # Decrement value | |
valueList[listPointer] -= 1 | |
elif instruction == ".": # Print value | |
print(chr(valueList[listPointer]), end='') | |
elif instruction == ",": # Input character | |
# Ensure a character is inputted | |
userInput = "" | |
while userInput == "": | |
userInput = input() | |
# Add first inputted character's ASCII value | |
valueList[listPointer] = ord(userInput[0]) | |
elif instruction == "[": # Start loop | |
if valueList[listPointer] == 0: | |
unequalBrackets = 1 | |
# Jump to the end of the loop | |
while unequalBrackets > 0: | |
programCounter += 1 | |
# Crash if no closing bracket is found | |
if programCounter >= len(brainfuckCode): | |
raise Exception("Unequal brackets in loop. There are " + str(unequalBrackets) + " brackets still open.") | |
if brainfuckCode[programCounter] == "[": | |
unequalBrackets += 1 | |
elif brainfuckCode[programCounter] == "]": | |
unequalBrackets -= 1 | |
else: | |
programStack.append(programCounter) | |
elif instruction == "]": # End loop | |
# Loop must be balanced | |
if len(programStack) == 0: | |
raise Exception("programStack is empty") | |
# If value is 0 continue execution, otherwise loop | |
if valueList[listPointer] == 0: | |
programStack.pop() | |
else: | |
programCounter = programStack[-1] | |
else: # If invalid character, ignore it | |
pass | |
programCounter += 1 | |
# Example brainfuck code | |
brainfuckCode = "++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>." | |
executeBrainfuck(brainfuckCode) |
@b8horpet Neither of those are strictly true. There is no formal language spec, so most of this is a matter of debate.
I looked at few implementations real quick for reference. It seems that various implementations use different sized cells anywhere from 8-64 bits, or even a few with unlimited size. It also looks like most implementations do not allow you to move left of cell 0, although some do.
Since any BF programs that relies on over/under flow, or moving left of cell 0, can be rewritten to work without it, I don't think this is a big deal. If one wants to write "portable" BF, you should avoid these anyways.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
in brainfuck you can go left from the starting point
also values are stored as bytes so they wrap around when incremented or decremented