/* Functions in JavaScript have a length property, measuring
the number of named formal parameters. This means that a stack-based language
can tell how many items to pop off the stack to pass to the function.
Here is a very simple stack language, implemented in quasi-literate JavaScript.
(That is, you can copy this post out of your browser into a .js file and
run it in Node.) */
var interpreter = {/* The “Standard Library” is implemented as a dictionary of plain JavaScript functions. */
    '+': function(a, b) { return [a + b]; },
    '-': function(a, b) { return [a - b]; },
    'dup': function(a) { return [a, a]; },
    'swap': function(a, b) { return [b, a]; },
    /* Must be wrapped. `console.log.length` === 0 */
    '.': function(i) { console.log(i); },/* run is the entry point to the interpreter.
It resets the inputBuffer and stack fields. */
    'run': function(program) {
        this.inputBuffer = program;
        this.stack = [];
        while (this.inputBuffer) {
            // read one word from inputBuffer & interpret it
            this.interpret(this.word());
        }
    },/* word removes one word from the inputBuffer and returns it. */
    'word': function(/* operates on inputBuffer, not stack */) {
        var word = '';
        while (this.inputBuffer) {
            var ch = this.inputBuffer.charAt(0);
            this.inputBuffer = this.inputBuffer.substr(1);
            if (/^\s?$/.test(ch)) {
                if (word) {
                    break;
                }
            } else {
                word += ch;
            }
        }
        return word;
    },/* interpret decides how to handle each word.
- If the word is in the dictionary, execute it.
 - If it is a number, push the number onto the stack.
 - Otherwise throw an exception.
 
*/
    'interpret': function(word) {
        if (!word) return;
        if (word in this) {
            // it's defined, execute it.
            this.execute(this[word]);
        } else if (isFinite(word)) {
            // it's a number
            this.stack.push(parseFloat(word));
        } else throw new Error('unknown word `' + word + '`');
    },/*
execute provides the interoperability with JavaScript Functions.
It provides the top fn.length
items from the stack as arguments to the function.
If fn returns a value, the value is concatenated
back on top of the stack.
Multiple values can be returned in an array;
Array.prototype.concat will correctly concatenate
all of the values to this.stack in the intended order.
*/
    'execute': function(fn) {
        var len = fn.length;
        // pop the top `len` items off the stack, in order
        var applies = this.stack.splice(-len, len);
        // apply the items to the Function
        var results = fn.apply(this, applies);
        if (results) {
            // put any results back onto the stack
            this.stack = this.stack.concat(results);
        }
    },};/* Unit tests to demonstrate usage */
var assert = require('assert');/* An empty program leaves an empty stack. */
interpreter.run('');
assert.deepEqual(interpreter.stack, []);/* The standard library: dup, -, +, swap */
interpreter.run('3 dup');
assert.deepEqual(interpreter.stack, [3, 3]);
interpreter.run("2 6 -");
assert.deepEqual(interpreter.stack, [-4]);
interpreter.run('5 8 +');
assert.deepEqual(interpreter.stack, [13]);
interpreter.run('10 20');
assert.deepEqual(interpreter.stack, [10, 20]);
interpreter.run('10 20 swap');
assert.deepEqual(interpreter.stack, [20, 10]);/* We can reflect on just about any part of the execution of the interpreter. */
interpreter.run('12 23');
assert.deepEqual(interpreter.stack, [12, 23]);
// continues.../* For example, calling interpret without run or word
can be used to single-step: */
// ...continued
interpreter.interpret('swap');
assert.deepEqual(interpreter.stack, [23, 12]);
// continues.../* We can execute a function that isn’t even in the dictionary: */
// ...continued
interpreter.execute(function(a, b) {
    assert.deepEqual([a, b], [23, 12]);
    return ['whoa', 'nelly'];
});
assert.deepEqual(interpreter.stack, ['whoa', 'nelly']);/* Interpreting the word 'execute' pops a function off the stack */
interpreter.stack = [function() { return ['WOW'] }];
interpreter.interpret('execute');
assert.deepEqual(interpreter.stack, ['WOW']);/* Use the word tokenizer function to put single-word Strings on the stack */
interpreter.run('word foo');
assert.deepEqual(interpreter.stack, ['foo']);/* The preexisting + operator can work with this new String data type */
interpreter.run('word Hello, word World! +');
assert.deepEqual(interpreter.stack, ['Hello,World!']);/* And interpret can be called on Strings on the stack */
interpreter.run('5 5 word + interpret');
assert.deepEqual(interpreter.stack, [10]);/* Even if the String is a result of some other computation! */
interpreter.run('8 9 word sw word ap + interpret');
assert.deepEqual(interpreter.stack, [9, 8]);