Skip to content

Instantly share code, notes, and snippets.

@dorentus
Last active August 29, 2015 13:57
Show Gist options
  • Save dorentus/9363879 to your computer and use it in GitHub Desktop.
Save dorentus/9363879 to your computer and use it in GitHub Desktop.
yet another brainfuck interpreter
function brainLuck(code, input){
code = code || '';
input = input || '';
var memory = (function () {
var storage = [], cursor = 0;
return {
read: function () {
return storage[cursor] || 0;
},
write: function (c) {
storage[cursor] = c;
return c;
},
inc: function (step) {
var new_value = this.read() + ( step === undefined ? 1 : step );
while ( new_value > 255 ) new_value -= 256;
storage[cursor] = new_value;
return new_value;
},
dec: function (step) {
var new_value = this.read() - ( step === undefined ? 1 : step );
while ( new_value < 0 ) new_value += 256;
storage[cursor] = new_value;
return new_value;
},
inc_ptr: function (step) {
cursor += ( step === undefined ? 1 : step );
return cursor;
},
dec_ptr: function (step) {
cursor -= ( step === undefined ? 1 : step );
if (cursor < 0) throw 'underflow';
return cursor;
},
};
}()),
input_data = (function () {
var bytes = input.split('').reduce(function (m, c) {
var i = 0, code = undefined;
while (true) {
code = c.charCodeAt(i);
if ( isNaN(code) ) break;
m.push(code);
i = i + 1;
}
return m;
}, []).reverse();
return {
next: function () {
return bytes.pop();
},
};
}()),
instructions = (function () {
var cursor = -1,
current_token = function () {
return code[cursor];
},
step_forward = function () {
cursor = cursor + 1;
return cursor;
},
step_backward = function () {
cursor = cursor - 1;
return cursor;
},
token_is_repeatable = function (token) {
return ( token === '+' || token === '-' || token === '>' || token === '<' || token === '.' || token === ',' );
};
return {
next: function () {
var last_cursor = cursor, token = undefined;
step_forward();
token = current_token();
if ( token === undefined ) return undefined;
if ( token_is_repeatable(token) ) {
while ( true ) {
step_forward();
if ( current_token() !== token ) {
break;
}
}
step_backward();
}
return {
token: token,
count: cursor - last_cursor,
};
},
move_to_matching_bracelet: function (t, t0, step) {
var counter = 1;
while (true) {
cursor = cursor + step;
if ( current_token() === t0 ) {
++counter;
}
else if ( current_token() === t && --counter === 0 ) {
break;
}
}
return cursor;
},
};
}()),
output_stream = (function () {
var stack = [];
return {
put: function (c) {
stack.push(c);
return stack;
},
toString: function () {
return stack.map(function (c) {
return String.fromCharCode(c);
}).join('');
},
};
}()),
repeatly_call = function (fn, count) {
for (var i = 0; i < count; ++i) {
fn();
}
},
instruction = undefined;
while (true) {
instruction = instructions.next();
if ( instruction === undefined ) break;
switch (instruction.token) {
case '>':
memory.inc_ptr(instruction.count);
break;
case '<':
memory.dec_ptr(instruction.count);
break;
case '+':
memory.inc(instruction.count);
break;
case '-':
memory.dec(instruction.count);
break;
case '.':
repeatly_call(function () {
output_stream.put(memory.read())
}, instruction.count);
break;
case ',':
repeatly_call(function () {
memory.write(input_data.next());
}, instruction.count);
break;
case '[':
if ( memory.read() === 0 ) {
instructions.move_to_matching_bracelet(']', '[', 1);
}
break;
case ']':
if ( memory.read() !== 0 ) {
instructions.move_to_matching_bracelet('[', ']', -1);
}
break;
default:
}
}
return output_stream.toString();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment