Skip to content

Instantly share code, notes, and snippets.

@dtoma
Last active December 29, 2016 07:05
Show Gist options
  • Save dtoma/ce6a7dee19ba3206ab5dc0534273aac6 to your computer and use it in GitHub Desktop.
Save dtoma/ce6a7dee19ba3206ab5dc0534273aac6 to your computer and use it in GitHub Desktop.
bf interpreter
#include <cstdio>
#include <functional>
#include <unordered_map>
#include <vector>
// Notes
// [some brainfuck fluff by daniel b cristofani](http://www.hevanet.com/cristofd/brainfuck/)
// [The Epistle to the Implementors](http://www.hevanet.com/cristofd/brainfuck/epistle.html)
// [The BrainFuck Compiler Collection](https://github.com/Sirflankalot/bfcc)
// TODO
// - [ ] Parser
// - [ ] Tests
// - [ ] Graphics
// - [ ] Fuzzing
// - [ ] Speed
namespace {
auto print_buffer(std::vector<int32_t> const& buffer, std::size_t data_ptr) {
printf("buffer: ");
for (auto const& e : buffer) { printf("%2i|", (int)e); }
printf("\n ");
printf("%*c\n", (int)(data_ptr * 3) + 2, '^');
}
auto print_tape(std::string const& tape, std::size_t instr_ptr) {
printf("tape: ");
for (auto const& e : tape) { printf("%c", e); }
printf("\n ");
printf("%*c\n", (int)instr_ptr, '^');
}
}
int main(int ac, char** av) {
if (ac < 3) {
fprintf(stderr, "usage:\n\t%s buffer_size<int> program<string>\n", av[0]);
return 1;
}
printf("BF interpreter running\n");
std::string tape { av[2] };
std::size_t instr_ptr = 0;
std::vector<int32_t> buffer(std::atoi(av[1]));
std::size_t data_ptr = 0;
std::unordered_map<char, std::function<void (void)>> commands = {
{ '>', [&data_ptr]() { data_ptr += 1; } },
{ '<', [&data_ptr]() { data_ptr -= 1; } },
{ '+', [&data_ptr, &buffer]() { buffer[data_ptr] += 1; } },
{ '-', [&data_ptr, &buffer]() { buffer[data_ptr] -= 1; } },
{ '.', [&data_ptr, &buffer]() { printf("%c", buffer[data_ptr]); } },
{ ',', [&data_ptr, &buffer]() { buffer[data_ptr] = std::fgetc(stdin); } },
{ '[', [&data_ptr, &buffer, &instr_ptr, tape]() {
if (buffer[data_ptr] != 0) { return; }
instr_ptr -= 1;
while (tape[instr_ptr] != ']') { instr_ptr += 1; }
} },
{ ']', [&data_ptr, &buffer, &instr_ptr, tape]() {
if (buffer[data_ptr] == 0) { return; }
instr_ptr -= 1;
std::size_t closed_braces = 0;
while (tape[instr_ptr] != '[') {
instr_ptr -= 1;
// skip nested loops on the way back to the original '['
if (tape[instr_ptr] == ']') { closed_braces += 1; }
if (tape[instr_ptr] == '[' && closed_braces != 0) {
closed_braces -= 1; instr_ptr -= 1;
}
}
} }
};
auto end = tape.size();
while (instr_ptr < end) {
auto instruction = tape[instr_ptr];
instr_ptr += 1;
if (auto search = commands.find(instruction); search != std::end(commands)) {
search->second();
}
// Uncomment to print the tape and buffer's status and step on enter
// print_buffer(buffer, data_ptr);
// print_tape(tape, instr_ptr);
// std::getc(stdin);
}
printf("\n");
}
@dtoma
Copy link
Author

dtoma commented Dec 27, 2016

Example run with debug uncommented:

BF interpreter running                                                                                                                                                     [1120/98421]
buffer:  1| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0|
        ^
tape: ++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
       ^

buffer:  2| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0|
        ^
tape: ++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
        ^

buffer:  3| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0|
        ^
tape: ++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
         ^

buffer:  4| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0|
        ^
tape: ++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
          ^

buffer:  5| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0|
        ^
tape: ++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
           ^

buffer:  6| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0|
        ^
tape: ++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
            ^

buffer:  7| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0|
        ^
tape: ++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
             ^

buffer:  8| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0|
        ^
tape: ++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
              ^

buffer:  8| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0|
        ^
tape: ++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
               ^

buffer:  8| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0|
           ^
tape: ++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
                ^

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment