Skip to content

Instantly share code, notes, and snippets.

@edalorzo
Created December 12, 2013 22:25
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 edalorzo/7936657 to your computer and use it in GitHub Desktop.
Save edalorzo/7936657 to your computer and use it in GitHub Desktop.
Befunge-93 Interpreter
var interpret = (function(){
var stack = [];
var sysout = [];
var dir = '>'
var strmode = false;
var skipmode = false;
var pc = {row:0,col:0};
var program = [];
function run(source){
stack = [], sysout = [], dir = '>';
strmode = false, skipmode = false;
pc = {row:0,col:0}, program = source;
var opcode = program[pc.row][pc.col];
while(opcode !== '@' || strmode){
if(skipmode){
toggleSkipMode();
}else if(strmode){
opcode =='"' ? toggleStringMode() : push(opcode);
}else if(/[<^v>]/.test(opcode)){
dir = opcode;
}else if(opcode=='_'){
dir = (pop() == 0 ? '>' : '<');
}else if(opcode=='|'){
dir = (pop() == 0 ? 'v' : '^');
}else if(opcode=='?'){
dir = randir();
}else if(/\d/.test(opcode)){
push(opcode | 0);
}else {
switch(opcode){
case '.': printInt(); break;
case ',': printChar(); break;
case '+': sum(); break;
case '-': sub(); break;
case '*': mul(); break;
case '/': div(); break;
case '%': mod(); break;
case '!': not(); break;
case '`': gt(); break;
case '"': toggleStringMode(); break;
case "#": toggleSkipMode(); break;
case '$': pop(); break;
case ':': dup(); break;
case '\\': swap(); break;
case 'g': get(); break;
case 'p': put(); break;
}
}
opcode = move(program);
}
return sysout.join('');
}
//TODO:deal with empty stack
function pop(){
return stack.pop() | 0;
}
function push(x){
if(typeof x == 'string'){
x = x.charCodeAt(0);
}
stack.push(x | 0);
}
function toggleStringMode(){
strmode = !strmode;
}
function toggleSkipMode(){
skipmode = !skipmode;
}
function printInt(){
sysout.push(pop());
}
function printChar(){
sysout.push(String.fromCharCode(pop()));
}
function randir(){
var res = dir;
switch(Math.round(Math.random() * 4)){
case 0: res='>'; break;
case 1: res='<'; break;
case 2: res='^'; break;
case 3: res='v'; break;
}
return res;
}
function dup(){
if(stack.length==0){
push(0);
}else{
var a = pop();
push(a);
push(a);
}
}
function swap(){
var a=pop(), b=pop();
push(a);
push(b);
}
function not(){
push(pop() == 0 ? 1 : 0);
}
function gt(){
var a = pop(), b = pop();
push(b > a ? 1 : 0);
}
function sum(){
var a = pop(), b = pop();
push(a + b);
}
function sub(){
var a = pop(), b = pop();
push(b - a);
}
function mul(){
var a = pop(), b = pop();
push(a * b);
}
function div(){
var a = pop(), b = pop();
push(Math.round(b / a));
}
function mod(){
var a = pop(), b = pop();
push(b % a);
}
function get(){
var y=pop(), x=pop();
push(program[y][x]);
}
function put(){
var y=pop(), x=pop(), v=pop();
program[y][x]=v;
}
function move(){
switch(dir){
case '>': pc.col = next(pc.col+1,program[pc.row].length); break;
case '<': pc.col = prev(pc.col-1,program[pc.row].length); break;
case 'v': pc.row = next(pc.row+1,program.length); break;
case '^': pc.row = prev(pc.row-1,program.length); break;
}
return program[pc.row][pc.col];
}
function next(p,q){
return p >= q ? 0 : p;
}
function prev(p,q){
return p < 0 ? q : p;
}
return function(code){
return run(code.split('\n').map(function(s){ return s.split('');}));
};
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment