// Generated by CoffeeScript 1.9.1 (function() { var LispInterpreterError, Node, Symbol, astSymbolsToLispSymbols, caadr, caar, cadar, cadddr, caddr, cadr, car, cdar, cddr, cdr, cons, env_init, eq, evaluateApplication, evaluateBegin, evaluateIf, evaluateLambda, evaluateSet, evaluateVariable, listToString, listToVector, makeEvaluator, metacadr, metadata_evaluation, nil, nilp, normalizeForm, normalizeForms, pairp, prox, ref, ref1, ref2, sBehavior, sFunction, sType, setcar, setcdr, straight_evaluation, the_false_value, update, updates, extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, hasProp = {}.hasOwnProperty; ref = require("cons-lists/lists"), listToString = ref.listToString, listToVector = ref.listToVector, pairp = ref.pairp, cons = ref.cons, car = ref.car, cdr = ref.cdr, caar = ref.caar, cddr = ref.cddr, cdar = ref.cdar, cadr = ref.cadr, caadr = ref.caadr, cadar = ref.cadar, caddr = ref.caddr, nilp = ref.nilp, nil = ref.nil, setcdr = ref.setcdr, metacadr = ref.metacadr, setcar = ref.setcar; ref1 = require("../chapter1/astToList"), normalizeForms = ref1.normalizeForms, normalizeForm = ref1.normalizeForm; ref2 = require('../chapter1/reader_types'), Node = ref2.Node, Symbol = ref2.Symbol; LispInterpreterError = (function(superClass) { extend(LispInterpreterError, superClass); LispInterpreterError.prototype.name = 'LispInterpreterError'; function LispInterpreterError(message) { this.message = message; } return LispInterpreterError; })(Error); the_false_value = cons("false", "boolean"); eq = function(id1, id2) { if (id1 instanceof Symbol && id2 instanceof Symbol) { return id1.name === id2.name; } return id1 === id2; }; astSymbolsToLispSymbols = function(node) { var handler; if (nilp(node)) { return nil; } if (!node.type === 'list') { throw new LispInterpreterError("Not a list of variable names"); } handler = function(cell) { if (nilp(cell)) { return nil; } return cons((car(cell)).value, handler(cdr(cell))); }; return handler(node.value); }; cadddr = metacadr('cadddr'); metadata_evaluation = { listp: function(node) { return node.type === 'list'; }, symbolp: function(node) { return node.type === 'symbol'; }, numberp: function(node) { return node.type === 'number'; }, stringp: function(node) { return node.type === 'string'; }, commentp: function(node) { return node.type === 'comment'; }, nvalu: function(node) { return node.value; }, mksymbols: function(list) { return astSymbolsToLispSymbols(list); } }; straight_evaluation = { listp: function(cell) { return cell.__type === 'list'; }, symbolp: function(cell) { var ref3; return typeof cell === 'string' && cell.length > 0 && ((ref3 = cell[0]) !== "\"" && ref3 !== ";"); }, commentp: function(cell) { return typeof cell === 'string' && cell.length > 0 && cell[0] === ";"; }, numberp: function(cell) { return typeof cell === 'number'; }, stringp: function(cell) { return typeof cell === 'string' && cell.length > 0 && cell[0] === "\""; }, boolp: function(cell) { return typeof cell === 'boolean'; }, nullp: function(cell) { return cell === null; }, vectorp: function(cell) { return (!straight_evaluation.listp(cell)) && toString.call(cell) === '[object Array]'; }, recordp: function(cell) { return (cell._prototype == null) && toSTring.call(cell) === '[object Object]'; }, objectp: function(cell) { return (cell._prototype != null) && toString.call(cell) === '[object Object]'; }, nilp: function(cell) { return nilp(cell); }, nvalu: function(cell) { return cell; }, mksymbols: function(cell) { return cell; } }; sType = new Symbol('type'); sBehavior = new Symbol('behavior'); sFunction = new Symbol('function'); env_init = function(id) { throw LispInterpreterError("No binding for " + id); }; update = function(mem, addr, value) { return function(addra) { if (addra === addr) { return value; } else { return mem(addra); } }; }; updates = function(mem, addrs, values) { if (pairp(addrs)) { return updates(update(mem, car(addrs), car(values)), cdr(addrs), cdr(values)); } else { return mem; } }; evaluateVariable = function(name, env, mem, kont) { return kont(mem, env(name), mem); }; evaluateSet = function(name, exp, env, mem, kont) { return evaluate(exp, env, mem, function(value, newmem) { return kont(value, update(newmem, env(name), value)); }); }; evaluateApplication = function(exp, exprs, env, mem, kont) { var evaluateArguments; evaluateArguments = function(exprs, env, mem, kont) { if (pairp(exprs)) { return evaluate(car(exprs), env, mem, function(value, mem2) { return evaluateArguments(cdr(exprs), env, mem2, function(value2, mems3) { return kont(cons(value, value2), mems3); }); }); } else { return kont(cons(), mem); } }; return evaluate(exp, env, mem, function(fun, mems) { return evaluateArguments(exprs, env, mems, function(value2, mem3) { if (eq(fun(sType), sFunction)) { return (fun(sBehavior))(value2, mem3, kont); } else { throw new LispInterpreterError("Not a function " + (car(value2))); } }); }); }; evaluateLambda = function(names, exprs, env, mem, kont) { return allocate(1, mem, function(addrs, mem2) { return kont(createFunction(car(addrs), function(values, mem, kont) { if (eq(length(names), length(values))) { return allocate(length(names), mem, function(addrs, mem2) { return evaluateBegin(exprs, updates(env, names, addrs), updates(mem2, addrs, values), kont); }); } else { throw new LispInterpreterError("Incorrect Arrity"); } }), mem2); }); }; evaluateIf = function(expc, expt, expf, env, mem, kont) { return evaluate(expc, env, mem, function(env, mems) { return evaluate((env("boolify"))(expt, expf), env, mems, kont); }); }; evaluateBegin = function(exps, env, mem, kont) { if (pairp(cdr(exps))) { return evaluate(car(exps), env, mem, function(_, mems) { return evaluateBegin(cdr(exps), env, mems, kont); }); } else { return evaluate(car(exps), env, mem, kont); } }; prox = { "quote": function(body, env, mem, kont, ix) { return evaluateQuote(cadr(body), env, mem, kont); }, "if": function(body, env, mem, kont, ix) { return evaluateIf(cadr(body), caddr(body), cadddr(body), env, mem, kont); }, "begin": function(body, env, mem, kont, ix) { return evaluateBegin(cdr(body), env, mem, kont); }, "set!": function(body, env, mem, kont, ix) { return evaluateSet(ix.nvalu(cadr(body)), caddr(body), env, mem, kont); }, "lambda": function(body, env, mem, kont, ix) { return evaluateLambda(ix.mksymbols(cadr(body)), cddr(body), env, mem, kont); } }; makeEvaluator = function(ix) { if (ix == null) { ix = straight_evaluation; } return function(exp, env, mem, kont) { var body, head; if (ix.atomp(exp)) { if (ix.symbolp(exp)) { return evaluateVariable(exp, env, mem, kont); } else { return evaluateQuote(exp, env, mem, kont); } } else { body = ix.nvalu(exp); head = car(body); if (prox[ix.nvalu(head)] != null) { return prox[ix.nvalue(head)](body, env, mem, kont, ix); } else { return evaluateApplication(body, cadr(body), env, mem, kont); } } }; }; }).call(this);