もういいや
var ScheJS = { }; with (ScheJS) { new function() { ScheJS.eval = function(string) { ScheJS.buffer = string; var context = { }; initContext.call(context); var values = []; pushWhile(values, function() { return evalExpression.call(context, read()) }); return values[values.length - 1]; } 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); var scope = this; return function() { var context = { }; if (args instanceof Array) { for (var i = 0; i < args.length; i++) context[args[i]] = arguments[i]; } else { context[args] = Array.slice(arguments); } context.__proto__ = scope; 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) { return val.car; }, 'cdr': function(val) { return val.cdr; }, 'alert': function(val) { alert(val); } } ScheJS.read = function(string) { if (string) ScheJS.buffer = string; return readExpression(); } ScheJS.readExpression = function() { switch (true) { case eat('('): var expr = []; pushWhile(expr, readExpression); return expr; case eat('[^()\\s]+'): return RegExp.$1; case eat(')'): return false; default: return false; } } function pushWhile(array, func) { for (var x = func(); x; x = func()) array.push(x); } function eat(pattern) { var regexp = new RegExp('^\\s*(' + (pattern || '').replace(/[()]/g, '\\$&') + ')\\s*'); if (buffer.match(regexp)) { buffer = RegExp.rightContext; return true; } else { return false; } } } }