Last active
December 10, 2015 00:19
-
-
Save ylegall/4350486 to your computer and use it in GitHub Desktop.
brainfuck interpreter
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
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