4
\$\begingroup\$

Due to the fact that nobody's ever posted this before (sarcasm) I've made a brainfuck interpreter in java. The interpreter fits in a single method, and is designed to be readable, fast, and concise, so please review on those things. I have tested it to confirm that it works.

/**
 * Interpret program as a brainfuck program with the given standard input
 * and output.
 * 
 * @throws IOException
 *             if thrown by stdin or stdout
 */
public static void brainfuck(String program, OutputStream stdout, InputStream stdin) throws IOException {
    int[] commands = program.chars().filter(c -> "><+-./[]".indexOf(c) != -1).toArray();
    int commandPointer = 0;
    int[] memory = new int[30_000];
    int memoryPointer = 0;
    while (commandPointer < commands.length) {
        switch (commands[commandPointer]) {
        case '>':
            memoryPointer++;
            if (memoryPointer >= memory.length)
                memoryPointer = 0;
            break;
        case '<':
            memoryPointer--;
            if (memoryPointer < 0)
                memoryPointer = memory.length - 1;
            break;
        case '+':
            memory[memoryPointer]++;
            if (memory[memoryPointer] > 255)
                memory[memoryPointer] = 0;
            break;
        case '-':
            memory[memoryPointer]--;
            if (memory[memoryPointer] < 0)
                memory[memoryPointer] = 255;
            break;
        case '.':
            stdout.write(memory[memoryPointer]);
            break;
        case ',':
            memory[memoryPointer] = stdin.read();
            memory[memoryPointer] %= 256;
            break;
        case '[':
            if (memory[memoryPointer] == 0) {
                int depth = 1;
                while (depth > 0) {
                    commandPointer++;
                    if (commands[commandPointer] == '[')
                        depth++;
                    else if (commands[commandPointer] == ']')
                        depth--;
                }
            }
            break;
        case ']':
            if (memory[memoryPointer] != 0) {
                int depth = 1;
                while (depth > 0) {
                    commandPointer--;
                    if (commands[commandPointer] == ']')
                        depth++;
                    else if (commands[commandPointer] == '[')
                        depth--;
                }
            }
            break;
        }
        commandPointer++;
    }
}
\$\endgroup\$
1
\$\begingroup\$

You already reached two of your goals. The interpreter is very readable and very concise. It is pretty fast but could easily be made faster, but then the code would become longer and more complicated.

If you want the interpreter to stay readable, leave it as-is. Maybe document the wrap-around semantics in the Javadoc.

One thing you could change is for the , command to just be memory[memoryPointer] = stdin.read() & 0xFF;. This is more common than % 256, since this is about bit msnipulation, not about arithmetics.

\$\endgroup\$
0
\$\begingroup\$

You shouldn't silently ignore invalid characters in your input/program. Why not use the default case for some simple warning or error output?

Also in the case handling for [ and ] you're never checking for memory bounds, which might be a problem for broken/buggy code. You could just unintentionally leave the available memory.

\$\endgroup\$
  • \$\begingroup\$ I used streams to filter out any character that's not a valid command because any character that's not a valid command is considered a comment. Good catch with the bounds though, I guess it would just crash with an ArrayIndexOutOfBoundsException if the brainfuck loops were bad \$\endgroup\$ – Phoenix Aug 18 '16 at 5:46
  • \$\begingroup\$ @Phoenix Ah, okay. Didn't know about the comment thing. \$\endgroup\$ – Mario Aug 18 '16 at 5:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.