ScheJS

すきJSとよみます
throwとかうんこすぎるのでやめたい

var ScheJS = { };

with (ScheJS) {
new function() {
    ScheJS.eval = function(string) {
        ScheJS.buffer = string;

        var context = { };
        initContext.call(context);
        try {
            while (1)
                var value = evalExpression.call(context, read());
        } catch (e) {
            return value;
        }
    }

    ScheJS.evalExpression = function(expr) {
        if (expr instanceof Array) {
            var evalee = evalExpression.call(this, expr[0]);
            var args = expr.slice(1);
            if (!evalee.isSpecialForm)
                args = args.map(evalExpression, this);
            return evalee.apply(this, args);
        } else {
            switch (true) {
                case expr in this:
                    return this[expr];
                case !isNaN(Number(expr)):
                    return Number(expr);
            }
        }
    }

    ScheJS.initContext = function() {
        for (var n in SPECIAL_FORMS) {
            this[n] = SPECIAL_FORMS[n];
            this[n].isSpecialForm = true;
        }
        for (var n in DEFINITIONS){
            this[n] = DEFINITIONS[n];
        }
    }

    ScheJS.SPECIAL_FORMS = {
        'lambda': function(args) {
            var body = Array.slice(arguments, 1);
            return function() {
                var context = { };
                for (var i = 0; i < args.length; i++)
                    context[args[i]] = arguments[i];
                context.__proto__ = this;
                return body.map(evalExpression, context)[body.length - 1];
            }
        },
        'define': function(name, expr) {
            this[name] = evalExpression.call(this, expr);
        },
        'define-macro': function(name, expr) {
            this[name] = evalExpression.call(this, expr);
            this[name].isSpecialForm = true;
        }
    }

    ScheJS.DEFINITIONS = {
        cons: function(car, cdr) {
            return {
                car: car,
                cdr: cdr,
                toString: function() { return '(' + this.car + ' . ' + this.cdr + ')' }
            };
        },
        car: function(val) {
            if (val instanceof Array)
                return val[0];
            else
                return val.car;
        },
        cdr: function(val) {
            if (val instanceof Array)
                return val.slice(1);
            else
                return val.cdr;
        },
        alert: function(val) {
            alert(val);
        }
    }

    ScheJS.read = function(string) {
        if (string)
            ScheJS.buffer = string;
        return readExpression();
    }

    ScheJS.readExpression = function() {
        eat();

        switch (true) {
            case eat('('):
                var expr = [];
                try {
                    while (1)
                        expr.push(readExpression());
                } catch (e) {
                }
                return expr;

            case eat('[^()\\s]+'):
                return RegExp.$1;

            case eat(')'):
            default:
                throw 'End of S-Expression';
        }
    }

    function eat(pattern) {
        var regexp = new RegExp('^(' + (pattern || '').replace(/[()]/g, '\\$&') + ')\\s*');
        if (buffer.match(regexp)) {
            buffer = RegExp.rightContext;
            return true;
        } else {
            return false;
        }
    }
}
}