The previous version is here. This version takes suggestions from that review into account:brainfuck is now an object instead of a function, and brainfuck.run(source) kicks off the interpreter.There is no built-in support for multiple interpreter instances, but Object.create(brainfuck) will do the trick.Stub functions (which throw errors) are provided for the implementation-dependent read and write functions.This version also addresses the redundancy in the first version by handling loops differently. All loop start and end positions are pre-calculated, so the entire loop is now bypassed when appropriate instead of passing over each operation and no-opping. This also removes the need to keep a stack of loop start positions while the program runs.Also, this version adds proper exports for AMD script loaders and CJS environments, with a fallback to the global namespace object.  (function(global){    // Find start and end positions of each loop.    function findLoops(code) {        var start;        var startpoints = {};        var endpoints = {};        var stack = [];        for (var i = 0; i < code.length; i++) {            if (code[i] == '[') {                stack.push(i);            } else if (code[i] == ']') {                start = stack.pop();                startpoints[i] = start;                endpoints[start] = i;            }        }        return { start: startpoints, end: endpoints };    }    // Run the brainfuck interpreter.    function run(source) {        var brainfuck = this;        var code = source.replace(/[^-+<>.,[\]]/g, '').split('');  // program code        var loop = findLoops(code);  // loop start and end positions        var data = [];  // array of data cells stored by the program code        var cell = 0;   // index in the data array representing one cell of data        var next = 0;   // index in the code array of the next instruction to run         var operation = {            '>': function () { ++cell; },            '<': function () { --cell; },            '+': function () { data[cell] = (data[cell] || 0) + 1; },            '-': function () { data[cell] = (data[cell] || 0) - 1; },            '.': function () { brainfuck.write(data[cell]); },            ',': function () { data[cell] = brainfuck.read(); },            '[': function () { if (!data[cell]) { next = loop.end[next]; } },            ']': function () { if (data[cell]) { next = loop.start[next]; } }        };        while (next < code.length) {            operation[code[next]]();            next++;        }        if (brainfuck.end) {            brainfuck.end();        }    }    // Export a module for AMD loaders, CJS environments, or as a global.    function exportModule(name, module) {        if (global['define'] && global['define']['amd']) {            global['define'](module);        } else if (global['exports']) {            for (var key in module) if (module.hasOwnProperty(key)) {                global['exports'][key] = module[key];            }        } else {            global[name] = module;        }    }    // Export brainfuck module.     exportModule('brainfuck', {         'run': run,        'read': function() { throw new Error('read function not provided'); },        'write': function() { throw new Error('write function not provided'); }    });}(this));Test it out here. I have no specific concerns at this point, I'm just looking for a general review.
Brainfuck interpreter in JavaScript, take 2
javascript;brainfuck;interpreter