LispInSmallPieces/chapter4/interpreter.js

256 lines
8.0 KiB
JavaScript

// 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);