Skip to content

Instantly share code, notes, and snippets.

@ylegall
Last active December 10, 2015 00:19
Show Gist options
  • Save ylegall/4350486 to your computer and use it in GitHub Desktop.
Save ylegall/4350486 to your computer and use it in GitHub Desktop.
brainfuck interpreter
module brainfuck;
import std.algorithm;
import std.conv;
import std.container;
import std.file;
import std.stdio;
enum DATA_SIZE = 1024;
private
{
char[] text; // program text
ubyte[] data; // program data
uint pc; // program counter
uint dp; // data pointer
uint[uint] jumpTable; // hash table to store jump addresses
}
/**
* execute an operation
*/
private void exec(char op)
{
import std.cstream;
switch(op) {
case '<':
--dp;
break;
case '>':
if (dp >= data.length) {
data.length = max(dp + 1, data.length * 2);
}
++dp;
break;
case '+':
data[dp]++;
break;
case '-':
data[dp]--;
break;
case '.':
write(cast(char)(data[dp]));
break;
case ',':
data[dp] = din.getc();
break;
case '[':
if (data[dp] == 0) {
pc = jumpTable[pc];
}
break;
case ']':
if (data[dp] != 0) {
pc = jumpTable[pc];
}
break;
default:
debug writeln("invalid operator: ", op);
break;
}
}
/**
*
*/
private void run()
{
data = new ubyte[DATA_SIZE];
pc = 0;
dp = 0;
while (pc < text.length) {
exec(text[pc]);
++pc;
}
}
/**
* Loads the file into memory and creates a jump table.
*/
private void load(File input)
{
int i = 0;
auto stack = new int[0];
void addChar(char c) {
if (i >= text.length) {
text.length = std.algorithm.max(i+1, text.length * 2);
}
text[i++] = c;
}
char c;
while (input.readf("%c", &c)) {
switch(c) {
case '<':
case '>':
case '+':
case '-':
case '.':
case ',':
addChar(c);
break;
case '[':
stack ~= [i];
addChar(c);
break;
case ']':
assert(stack.length, "unmatched ]");
auto t = stack[$-1];
stack = stack[0 .. $-1];
jumpTable[t] = i;
jumpTable[i] = t;
addChar(c);
break;
default:
break;
}
}
if (stack.length > 0) {
debug writeln("warning: unmatched [");
}
}
int main(string[] args)
{
if (args.length > 1) {
auto size = getSize(args[1]);
text = new char[cast(uint)size];
load(File(args[1], "r"));
} else {
load(stdin);
}
run();
debug writeln("halt");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment