patterncppMinor
Mini BF interpreter
Viewed 0 times
interpreterministackoverflow
Problem
Many Brainfuck implementations I've come across generally are obtuse, verbose or over-the-top. But I've always seen Brainfuck as "easy to implement", especially for beginners.
My original need for this was to be able to have an actual Brainfuck "machine" that executed instructions to aid with code generation. However, this should also work fine on its own.
How can the "API" be improved?
My original need for this was to be able to have an actual Brainfuck "machine" that executed instructions to aid with code generation. However, this should also work fine on its own.
How can the "API" be improved?
#include
#include
// Mini BF interpreter
struct BF
{
int tape[30000] = {0};
int *ptr = tape;
std::string program = "";
/* The index will be used to control program flow
* when encountering brackets.
*/
std::size_t index = 0;
std::stack brackets;
BF(std::string program = "")
: program(program)
{
}
void addc(char c)
{
program += c;
}
void adds(std::string s)
{
program += s;
}
void run()
{
while (next());
}
void print_memory()
{
for (int i = 0; i ': ++ptr; break;
case '++++[>++>+++>+++>++>+>->>+[>.>---.+++++++..+++.>>.>+.>++."};
BF bf{program};
bf.run();
bf.print_memory();
}Solution
Your program is small and well written, so there's not much else to change, IMO. My comments are mostly on code aesthetics.
-
Your
-
Also, an array of
-
No need to explicitly initialize the string
-
In the constructor, use
-
-
-
Make your interpreter a
-
Very minor thing, but I'd change this:
-
Another tiny thing: I usually dislike short names or abbreviations, so I'd name the class
Lastly, there are two other very good implementations here on CR you should take a look:
-
BrainFuck Interpreter in C++
-
Brainfuck interpreter (with emphasis on robustness) - C
-
Your
tape is a fixed size array, but you are not checking if you ran out of tape/memory. A very big program could crash your interpreter. This is a simple fix that might be worth it, it shouldn't add too much complexity to the code. One simple way is to replace every raw increment/decrement of ptr by a function that checks if you've ran out of space. Then "safely" terminate the interpreter with a friendly error message, instead of a segfault.-
Also, an array of
30000 ints is a lot of memory. Declaring an instance of the interpreter as a local function-level variable might stress the program stack. Maybe replace it by a dynamically allocated container like a std::vector. -
No need to explicitly initialize the string
std::string program = "". A std::string is a class, so it has a constructor that default initializes it to empty.-
In the constructor, use
std::move to move the input string, instead of copying it. When you pass by value, C++ always copies the data. You'll want to avoid that for a long string such as the program text.BF(std::string program = "")
: program(std::move(program))
{
}-
addc and adds are not used. Nevertheless, spell out their names: add_char and add_string.-
print_memory only prints the first 100 values of tape. You should comment the reason for that, otherwise, readers will assume it was a mistake, since tape is a lot larger. An alternative it to take the number of entries to print as a parameter of the function. Also relevant, C++ has the concept of const member functions, which are functions guaranteed not to change any member data. That's the case with print_memory, so it should be const:void print_memory() const { /* ... */ }
^^^^^-
Make your interpreter a
class and turn the internal methods and data private. In a structure, all fields are accessible to users of the object. It is better to hide implementation details and also to prevent users from messing with the internal interpreter states. Only leave the interface methods like run() in the public section of your class.-
Very minor thing, but I'd change this:
while (next()); to while (next()) { } to make it more visible that that's an empty loop.-
Another tiny thing: I usually dislike short names or abbreviations, so I'd name the class
BFInterpreter instead.Lastly, there are two other very good implementations here on CR you should take a look:
-
BrainFuck Interpreter in C++
-
Brainfuck interpreter (with emphasis on robustness) - C
Code Snippets
BF(std::string program = "")
: program(std::move(program))
{
}void print_memory() const { /* ... */ }
^^^^^Context
StackExchange Code Review Q#103956, answer score: 2
Revisions (0)
No revisions yet.