Skip to content

Instantly share code, notes, and snippets.

@netojoaobatista
Created April 18, 2012 17:16
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save netojoaobatista/2415161 to your computer and use it in GitHub Desktop.
Save netojoaobatista/2415161 to your computer and use it in GitHub Desktop.
A brainfuck programming language interpreter written in Javascript
var Context = function() {};
Object.defineProperty(Context,"create",{
writable: false, configurable: false, enumerable: true,
value: function(size,initializer) {
return Object.create(Context.prototype,(function(){
var data = (new Array(size?size:0)).join("|").split("|").map(
initializer||function(){}
);
var pointer = 0;
return {
current: {
enumerable: true,
get: function() { return data[ pointer ]; },
set: function(v) { data[ pointer ] = v; }
},
next: {
writable: false, configurable: false, enumerable: true,
value: function() {
++pointer;
}
},
pointer: {
get: function() { return pointer; }
},
previous: {
writable: false, configurable: false, enumerable: true,
value: function() {
--pointer;
}
}
};
}()));
}
});
function AbstractExpression() {}
AbstractExpression.prototype = {
interpret: function( context ) {}
};
function IncrementDataPointerExpression() {}
IncrementDataPointerExpression.prototype = new AbstractExpression();
IncrementDataPointerExpression.prototype.interpret = function(context) {
context.next();
};
function DecrementDataPointerExpression() {}
DecrementDataPointerExpression.prototype = new AbstractExpression();
DecrementDataPointerExpression.prototype.interpret = function(context) {
context.previous();
};
function IncrementDataExpression() {}
IncrementDataExpression.prototype = new AbstractExpression();
IncrementDataExpression.prototype.interpret = function(context) {
context.current++;
};
function DecrementDataExpression() {}
DecrementDataExpression.prototype = new AbstractExpression();
DecrementDataExpression.prototype.interpret = function(context) {
context.current--;
};
function OutputExpression() {}
OutputExpression.prototype = new AbstractExpression();
OutputExpression.prototype.interpret = function(context) {
console.log(String.fromCharCode(context.current));
};
function AcceptBypeExpression() {}
AcceptBypeExpression.prototype = new AbstractExpression();
AcceptBypeExpression.prototype.interpret = function(context) {
context.current; //TODO ver como ler o byte
};
function LoopExpression(program) {
this.program = program;
}
LoopExpression.prototype = new AbstractExpression();
LoopExpression.prototype.interpret = function(context) {
while (context.current) {
brainfuck(this.program, context);
}
};
function brainfuck(program,context) {
program = program||"";
if (context===undefined||!(context instanceof Context)) {
context = Context.create(30000,function(){ return 0; } );
}
for ( var i = 0; i < program.length; ++i ) {
var char = program.charAt(i);
var expression;
switch ( char ) {
case ">": expression = new IncrementDataPointerExpression(); break;
case "<": expression = new DecrementDataPointerExpression(); break;
case "+": expression = new IncrementDataExpression(); break;
case "-": expression = new DecrementDataExpression(); break;
case ".": expression = new OutputExpression(); break;
case ",": expression = new AcceptByteExpression(); break;
case "[":
var opened = 1;
var j = i+1;
for (; opened > 0 && j < program.length; ++j ) {
char = program.charAt(j);
if ( char == "[") ++opened;
else if ( char == "]") --opened;
}
if (opened==0) {
expression = new LoopExpression(program.substring(i+1,j-1));
i=j-1;
break;
} else {
throw new Error("Unexpected end");
}
default: continue;
}
expression.interpret(context);
}
}
brainfuck( ["+++++ +++++ initialize counter (cell #0) to 10",
"[ use loop to set the next four cells to 70/100/30/10",
"> +++++ ++ add 7 to cell #1",
"> +++++ +++++ add 10 to cell #2",
"> +++ add 3 to cell #3",
"> + add 1 to cell #4",
"<<<< - decrement counter (cell #0)",
"]",
"> ++ . print 'H'",
"> + . print 'e'",
"+++++ ++ . print 'l'",
". print 'l'",
"+++ . print 'o'",
"> ++ . print ' '",
"<< +++++ +++++ +++++ . print 'W'",
"> . print 'o'",
"+++ . print 'r'",
"----- - . print 'l'",
"----- --- . print 'd'",
"> + . print '!'",
"> . print '\n'"].join("\n")
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment