Created
April 18, 2012 17:16
-
-
Save netojoaobatista/2415161 to your computer and use it in GitHub Desktop.
A brainfuck programming language interpreter written in Javascript
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
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