// Javascript brainfuck interpreter see http://www.muppetlabs.com/~breadbox/bf/
// for description of language

var debugging = false;

var output = [];
var input = [];

// The interesting part is in this function
function compile(brainfuck) {

    var javascriptCode;

    // A Brainfuck program has an implicit byte pointer, called "the pointer",
    // which is free to move around within an array of 30000 bytes,
    // initially all set to zero.
    // The pointer itself is initialized to point to the beginning of this array.
    javascriptCode = "var array = [];";
    javascriptCode += "for(var j = 0;j < 30000;j++){array[j]=0;}";
    javascriptCode += "var p = 0;";

    var commands = {
        '>' : "++p;", // Increment the pointer.
        '<' : "--p;", // Decrement the pointer.
        '+' : "array[p]++;", // Increment the byte at the pointer.
        '-' : "array[p]--;", // Decrement the byte at the pointer.
        '.' : "output.push(array[p]);", // Output the byte at the pointer.
        ',' : "array[p] = input.pop();", // Input a byte and store it in the byte at the pointer.
        '[' : "while (array[p]) {", // Jump forward past the matching ] if the byte at the pointer is zero.
        ']' : "}" // Jump backward to the matching [ unless the byte at the pointer is zero.
    }

    for(var i = 0; i < brainfuck.length; i++){
        javascriptCode += commands[brainfuck.charAt(i)];
    }

    return javascriptCode;
}

// This function is boring stuff like IO handling etc...
function brainfuck(inputId, brainfuckId, outputId) {
    var inputArea = document.getElementById(inputId);
    var brainfuckArea = document.getElementById(brainfuckId);
    var outputArea = document.getElementById(outputId);
    if(inputArea == undefined){
        error("<ERROR: no object with id " + inputId);
        return;
    }
    if(brainfuckArea == undefined){
        error("ERROR: no object with id " + brainfuckId);
        return;
    }
    if(outputArea == undefined){
        error("ERROR: no object with id " + outputId);
        return;
    }

    debug("starting");

    // clean output and read input
    output = [];
    var input = [];
    for(var j = 0; j < inputArea.value.length; j++){
        input.push(inputArea.value.charCodeAt(j));
    }
    input.reverse(); // we will the use pop to get input bytes

    var brainfuck = brainfuckArea.value;
    var javascriptInterpitation = compile(brainfuck);

    debug("to evaluate: " + javascriptInterpitation);
    eval(javascriptInterpitation);
    // read output array as string values and write to output area
    var outputString = "";
    for(var i = 0; i < output.length; i++){
        outputString += String.fromCharCode(output[i]);
    }
    outputArea.innerHTML = outputString;

    debug("done");
}

function debug(param) {
    if(debugging){
        alert(param);
    }

}
function error(param) {
    alert(param);
}

