; (map 'list (flambda (x) (print (oval x))) oblist) (setq !) (setq cddr) (setq cdar) (setq cadr) (setq x 'x) (setq caar) (setq dbg) (setq print) (setq prin) (setq beep) (setq cls \["%0C"]) (setq cond) (setq if) (setq append) (setq member) (setq equal) (setq eq) (setq eql) (setq map) (setq allcdr) (setq allcar) (setq apply) (setq eval) (setq lastp) (setq last?) (setq consp) (setq cons?) (setq listp) (setq list?) (setq atomp) (setq atom?) (setq atom) (setq stringp) (setq string?) (setq string) (setq numberp) (setq number?) (setq number) (setq nullp) (setq null?) (setq null) (setq not) (setq load) (setq traceload) (setq interpret) (setq trace) (setq \\) (setq \)) (setq \() (setq \') (setq quote) (setq concat) (setq cat) (setq and) (setq or) (setq >=) (setq <=) (setq >) (setq <) (setq /=) (setq !=) (setq =) (setq eqn) (setq /) (setq *) (setq -) (setq +) (setq max) (setq min) (setq zerop) (setq zero?) (setq zero 0) (setq i '(0 1)) (setq t) (setq nil '()) (setq nan '\[NaN]) (setq infinity '\[Infinity]) (setq nth) (setq nthcar) (setq nthcdr) (setq last) (setq length) (setq list) (setq cons) (setq cdr) (setq car) (setq fval) (setq oval) (setq setq) (setq set) (setq oblist '\[function () {return Atom.list;}]) (setq df) (setq de) (setq defun) (setq progn) (setq flet) (setq let) (setq flambda) (setq lambda) (setq fexpr) (setq expr) (setq fsubr) (setq subr) (setq undef) ; (map 'list (flambda (x) (print (fval x))) oblist) (de ! (x) (cond ((> x 0) (* x (! (- x 1)))) ((= x 0) 1) ((< x 0) (- (! (- x)))) (t '!))) (de cddr (x) (cdr (cdr x))) (de cdar (x) (cdr (car x))) (de cadr (x) (car (cdr x))) (df x) (de caar (x) (car (car x))) (fsubr dbg \[function (car, cdr) { debugger; var val = cdr.car.valueOf(); Lisp.print(': ' + val); return val; }]) (subr print \[function (car, cdr) { var s = ''; while (Lisp.consp(cdr)) { s += cdr.car; cdr = cdr.cdr; } return Lisp.print(s); }]) (subr prin \[function (car, cdr) { var s = ''; while (Lisp.consp(cdr)) { s += cdr.car; cdr = cdr.cdr; } return Lisp.prin(s); }]) (fsubr beep \[function (car, cdr) { Lisp.beep(); return car; }]) (df cls) (fsubr cond \[function (car, cdr) { while (!Lisp.nullp(cdr)) { var cond = cdr.car; if (!Lisp.nullp(cond)) { var test = cond.car; if (!Lisp.nullp(test.valueOf())) { if (Lisp.nullp(cond = cond.cdr)) return new Cons(); var x = cond.car; return !Lisp.nullp(test.valueOf()) ? x.valueOf() : new Cons(); } } cdr = cdr.cdr; } return new Cons(); }]) (fsubr if \[function (car, cdr) { var test = cdr.car; if (Lisp.nullp(cdr = cdr.cdr)) return new Cons(); var x = cdr.car; if (Lisp.nullp(cdr = cdr.cdr)) return !Lisp.nullp(test.valueOf()) ? x.valueOf() : new Cons(); var y = cdr.car; return !Lisp.nullp(test.valueOf()) ? x.valueOf() : y.valueOf(); }]) (subr append \[function (car, cdr) { return Lisp.append(cdr); }]) (subr member \[function (car, cdr) { car = cdr.car; if (Lisp.nullp(cdr = cdr.cdr)) return Atom.t; cdr = cdr.car; return Lisp.member(car, cdr); }]) (subr equal \[function (car, cdr) { car = cdr.car; if (Lisp.nullp(cdr = cdr.cdr)) return Atom.t; cdr = cdr.car; return (car.toString() == cdr.toString()) ? Atom.t : Atom.nil; }]) (subr eq \[function (car, cdr) { car = cdr.car; if (Lisp.nullp(cdr = cdr.cdr)) return Atom.t; cdr = cdr.car; return ((typeof car == typeof cdr) && (car == cdr)) ? Atom.t : Atom.nil; }]) (subr eql \[function (car, cdr) { car = cdr.car; if (Lisp.nullp(cdr = cdr.cdr)) return Atom.t; cdr = cdr.car; return ((typeof car == typeof cdr) && (car == cdr)) ? Atom.t : Atom.nil; }]) (fsubr map \[function (car, cdr) { var op = cdr.car.valueOf(); var l = new Cons(); if (Lisp.nullp(cdr = cdr.cdr)) return l; var fn = cdr.car; if (Lisp.nullp(cdr = Lisp.evargs(cdr.cdr))) return l; var n = l; while (!Lisp.nullp(cdr)) { var x = Lisp.allcar(cdr); if (Lisp.nullp(x)) break; x = new Cons(fn, x); x = x.valueOf(); x = new Cons(op, new Cons(x, l)); x = x.valueOf(); n = n.cdr = Lisp.consp(x) ? x : new Cons(x); cdr = Lisp.allcdr(cdr); } return Lisp.nullp(l.cdr) ? l : l.cdr; }]) (subr allcdr \[function (car, cdr) { return Lisp.allcdr(cdr.car); }]) (subr allcar \[function (car, cdr) { return Lisp.allcar(cdr.car); }]) (subr apply \[function (car, cdr) { cdr = new Cons(cdr.car, Lisp.append(cdr.cdr)); return cdr.valueOf(); }]) (subr eval \[function (car, cdr) { cdr = Lisp.evargs(cdr); return cdr.car; }]) (subr lastp \[function (car, cdr) { return (Lisp.lastp(cdr.car)) ? Atom.t : Atom.nil; }]) (subr last? \[function (car, cdr) { return (Lisp.lastp(cdr.car)) ? Atom.t : Atom.nil; }]) (subr consp \[function (car, cdr) { return Lisp.consp(cdr.car) ? Atom.t : Atom.nil; }]) (subr cons? \[function (car, cdr) { return Lisp.consp(cdr.car) ? Atom.t : Atom.nil; }]) (subr listp \[function (car, cdr) { return Lisp.consp(cdr.car) ? Atom.t : Atom.nil; }]) (subr list? \[function (car, cdr) { return Lisp.consp(cdr.car) ? Atom.t : Atom.nil; }]) (subr atomp \[function (car, cdr) { return Lisp.consp(cdr.car) ? Atom.nil : Atom.t; }]) (subr atom? \[function (car, cdr) { return Lisp.consp(cdr.car) ? Atom.nil : Atom.t; }]) (subr atom \[function (car, cdr) { return Lisp.consp(cdr.car) ? Atom.nil : Atom.t; }]) (subr stringp \[function (car, cdr) { return Lisp.stringp(cdr.car) ? Atom.t : Atom.nil; }]) (subr string? \[function (car, cdr) { return Lisp.stringp(cdr.car) ? Atom.t : Atom.nil; }]) (subr string \[function (car, cdr) { return Lisp.stringp(cdr.car) ? Atom.t : Atom.nil; }]) (subr numberp \[function (car, cdr) { return Lisp.numberp(cdr.car) ? Atom.t : Atom.nil; }]) (subr number? \[function (car, cdr) { return Lisp.numberp(cdr.car) ? Atom.t : Atom.nil; }]) (subr number \[function (car, cdr) { return Lisp.numberp(cdr.car) ? Atom.t : Atom.nil; }]) (subr nullp \[function (car, cdr) { return Lisp.nullp(cdr.car) ? Atom.t : Atom.nil; }]) (subr null? \[function (car, cdr) { return Lisp.nullp(cdr.car) ? Atom.t : Atom.nil; }]) (subr null \[function (car, cdr) { return Lisp.nullp(cdr.car) ? Atom.t : Atom.nil; }]) (subr not \[function (car, cdr) { return Lisp.nullp(cdr.car) ? Atom.t : Atom.nil; }]) (subr load \[function (car, cdr) { var promises = []; // new Array() while (Lisp.consp(cdr)) { var path = cdr.car; if (Lisp.stringp(path)) promises.push(Read.load(path.slice(1, -1))); // async cdr = cdr.cdr; } Promise.allSettled(promises).then ( function (results) { for (var r of results) { if (r.status != "fulfilled") throw r.reason; // todo : uncaught ! } for (var r of results) { if (car === Atom.tload) Lisp.trace(r.value); else Lisp.interpret(r.value); } } ) return Atom.t; }]) (subr traceload \[function (car, cdr) { var promises = []; // new Array() while (Lisp.consp(cdr)) { var path = cdr.car; if (Lisp.stringp(path)) promises.push(Read.load(path.slice(1, -1))); // async cdr = cdr.cdr; } Promise.allSettled(promises).then ( function (results) { for (var r of results) { if (r.status != "fulfilled") throw r.reason; // todo : uncaught ! } for (var r of results) { if (car === Atom.tload) Lisp.trace(r.value); else Lisp.interpret(r.value); } } ) return Atom.t; }]) (subr interpret \[function (car, cdr) { var val = Atom.undef; while (!Lisp.nullp(cdr)) { var str = Lisp.stringp(cdr.car) ? cdr.car : '"' + cdr.car + '"'; val = (car === Atom.trace) ? Lisp.trace(str.slice(1, -1)) : Lisp.interpret(str.slice(1, -1)); cdr = cdr.cdr; } return val; }]) (subr trace \[function (car, cdr) { var val = Atom.undef; while (!Lisp.nullp(cdr)) { var str = Lisp.stringp(cdr.car) ? cdr.car : '"' + cdr.car + '"'; val = (car === Atom.trace) ? Lisp.trace(str.slice(1, -1)) : Lisp.interpret(str.slice(1, -1)); cdr = cdr.cdr; } return val; }]) (df \\) (df \)) (df \() (fsubr \' \[function (car, cdr) { return cdr.car; }]) (fsubr quote \[function (car, cdr) { return cdr.car; }]) (subr concat \[function (car, cdr) { var x = ''; while (!Lisp.nullp(cdr)) { x += Lstr.write(cdr.car); cdr = cdr.cdr; } return new Lstr(x); }]) (subr cat \[function (car, cdr) { var x = ''; while (!Lisp.nullp(cdr)) { x += Lstr.write(cdr.car); cdr = cdr.cdr; } return new Lstr(x); }]) (fsubr and \[function (car, cdr) { var x = Atom.t; while (!Lisp.nullp(cdr)) { x = cdr.car.valueOf(); if (Lisp.nullp(x) || !x) break; cdr = cdr.cdr; } return x; }]) (fsubr or \[function (car, cdr) { var x = Atom.nil; while (!Lisp.nullp(cdr)) { x = cdr.car.valueOf(); if (!Lisp.nullp(x) && x) break; cdr = cdr.cdr; } return x; }]) (subr >= \[function (car, cdr) { car = cdr.car; if (Lisp.nullp(cdr = cdr.cdr)) return Atom.nil; cdr = cdr.car; return (Lisp.numberp(car) && Lisp.numberp(cdr) && (car.toPrecision(Lmth.magn) >= cdr.toPrecision(Lmth.magn))) ? Atom.t : Atom.nil; }]) (subr <= \[function (car, cdr) { car = cdr.car; if (Lisp.nullp(cdr = cdr.cdr)) return Atom.nil; cdr = cdr.car; return (Lisp.numberp(car) && Lisp.numberp(cdr) && (car.toPrecision(Lmth.magn) <= cdr.toPrecision(Lmth.magn))) ? Atom.t : Atom.nil; }]) (subr > \[function (car, cdr) { car = cdr.car; if (Lisp.nullp(cdr = cdr.cdr)) return Atom.nil; cdr = cdr.car; return (Lisp.numberp(car) && Lisp.numberp(cdr) && (car.toPrecision(Lmth.magn) > cdr.toPrecision(Lmth.magn))) ? Atom.t : Atom.nil; }]) (subr < \[function (car, cdr) { car = cdr.car; if (Lisp.nullp(cdr = cdr.cdr)) return Atom.nil; cdr = cdr.car; return (Lisp.numberp(car) && Lisp.numberp(cdr) && (car.toPrecision(Lmth.magn) < cdr.toPrecision(Lmth.magn))) ? Atom.t : Atom.nil; }]) (subr /= \[function (car, cdr) { return (Atom.eqn.fValue(Atom.eqn, cdr) === Atom.t) ? Atom.nil : Atom.t; }]) (subr != \[function (car, cdr) { return (Atom.eqn.fValue(Atom.eqn, cdr) === Atom.t) ? Atom.nil : Atom.t; }]) (subr = \[function (car, cdr) { car = cdr.car; if (Lisp.nullp(cdr = cdr.cdr)) return Lisp.numberp(car) ? Atom.t : Atom.nil; cdr = cdr.car; return (Lisp.numberp(car) && Lisp.numberp(cdr) && (car.toPrecision(Lmth.magn) == cdr.toPrecision(Lmth.magn))) ? Atom.t : Atom.nil; }]) (subr eqn \[function (car, cdr) { car = cdr.car; if (Lisp.nullp(cdr = cdr.cdr)) return Lisp.numberp(car) ? Atom.t : Atom.nil; cdr = cdr.car; return (Lisp.numberp(car) && Lisp.numberp(cdr) && (car.toPrecision(Lmth.magn) == cdr.toPrecision(Lmth.magn))) ? Atom.t : Atom.nil; }]) (fsubr / \[function (car, cdr) { if (Lisp.lastp(cdr)) return 1 / Atom.mul.fValue(Atom.mul, cdr); else { //return cdr.car.valueOf() / Atom.mul.fValue(Atom.mul, cdr.cdr); var x = cdr.car.valueOf(); var mul = Atom.mul.fValue(Atom.mul, cdr.cdr); var div, rem = x % mul; if ((rem == x) && (rem != 1)) { div = mul / rem; if (Number.isInteger(div)) return new Cons(Atom.div, new Cons(x / rem, new Cons(div))); } div = x / mul; if ((div <= 1) || (rem == 0)) return div; return new Cons(Atom.plus, new Cons((x - rem) / mul, new Cons(new Cons(Atom.div, new Cons(rem, new Cons(mul)))))); } }]) (subr * \[function (car, cdr) { var x = 1; while (Lisp.consp(cdr)) { var y = Number(cdr.car); if (!Number.isNaN(y)) x *= y; cdr = cdr.cdr; } return Number(x.toPrecision(Lmth.magn)); }]) (fsubr - \[function (car, cdr) { if (Lisp.lastp(cdr)) return 0 - Atom.plus.fValue(Atom.plus, cdr); else return cdr.car.valueOf() - Atom.plus.fValue(Atom.plus, cdr.cdr); }]) (subr + \[function (car, cdr) { var x = 0; while (Lisp.consp(cdr)) { var y = Number(cdr.car); if (!Number.isNaN(y)) x += y; cdr = cdr.cdr; } return Number(x.toPrecision(Lmth.magn)); }]) (subr max \[function (car, cdr) { var x = -Infinity; while (Lisp.consp(cdr)) { var y = Number(cdr.car); if (!Number.isNaN(y)) x = (y > x) ? y : x; cdr = cdr.cdr; } return Number(x.toPrecision(Lmth.magn)); }]) (subr min \[function (car, cdr) { var x = +Infinity; while (Lisp.consp(cdr)) { var y = Number(cdr.car); if (!Number.isNaN(y)) x = (y < x) ? y : x; cdr = cdr.cdr; } return Number(x.toPrecision(Lmth.magn)); }]) (subr zerop \[function (car, cdr) { return (cdr.car == 0) ? Atom.t : Atom.nil; }]) (subr zero? \[function (car, cdr) { return (cdr.car == 0) ? Atom.t : Atom.nil; }]) (subr zero \[function (car, cdr) { return (cdr.car == 0) ? Atom.t : Atom.nil; }]) (df i) (df t) (df nil) (df nan) (df infinity) (subr nth \[function (car, cdr) { var l = cdr.car; cdr = cdr.cdr; var n = (Lisp.consp(cdr) && Lisp.numberp(cdr.car)) ? cdr.car : 0; return Lisp.nthcar(l, Lisp.consp(l) ? n-1 : n); }]) (subr nthcar \[function (car, cdr) { var l = cdr.car; cdr = cdr.cdr; var n = (Lisp.consp(cdr) && Lisp.numberp(cdr.car)) ? cdr.car : 0; return Lisp.nthcar(l, Lisp.consp(l) ? n-1 : n); }]) (subr nthcdr \[function (car, cdr) { var l = cdr.car; cdr = cdr.cdr; var n = (Lisp.consp(cdr) && Lisp.numberp(cdr.car)) ? cdr.car : 0; return Lisp.nthcdr(l, Lisp.consp(l) ? n-1 : n); }]) (subr last \[function (car, cdr) { var l = cdr.car; cdr = cdr.cdr; var n = (Lisp.consp(cdr) && Lisp.numberp(cdr.car)) ? cdr.car : 1; return Lisp.nthcdr(l, Lisp.len(l) - n); }]) (subr length \[function (car, cdr) { return Lisp.len(cdr.car); }]) (subr list \[function (car, cdr) { return cdr; }]) (subr cons \[function (car, cdr) { car = cdr.car; if (Lisp.nullp(car)) return new Cons(); cdr = cdr.cdr; if (Lisp.nullp(cdr)) return new Cons(car); return new Cons(car, cdr); }]) (subr cdr \[function (car, cdr) { var arg = cdr.car; if (!Lisp.consp(arg)) return Atom.undef; return arg.cdr === undefined ? Atom.undef : arg.cdr; }]) (subr car \[function (car, cdr) { var arg = cdr.car; if (!Lisp.consp(arg)) return Atom.undef; return arg.car === undefined ? Atom.undef : arg.car; }]) (subr fval \[function (car, cdr) { var atom = cdr.car; if (Lisp.atomp(atom)) { var val = atom.fval; if (val === undefined) return new Cons(Atom.df, new Cons(atom)); else switch (val.type) { case Atom.subr: case Atom.fsubr: var self = new Self(val.def); return new Cons(val.type, new Cons(atom, new Cons(self))); case Atom.expr: return new Cons(Atom.de, new Cons(atom, val.def.cdr)); case Atom.fexpr: return new Cons(Atom.df, new Cons(atom, val.def.cdr)); } } return Atom.undef; }]) (subr oval \[function (car, cdr) { var atom = cdr.car; if (Lisp.atomp(atom)) { var val = atom.oval; if (val === undefined) return new Cons(Atom.setq, new Cons(atom)); else { if (Lisp.stringp(val)) { val = new Self('"' + escape(val) + '"'); } else if (!Lisp.numberp(val)) val = new Tick(val); return new Cons(Atom.setq, new Cons(atom, new Cons(val))); } } return Atom.undef; }]) (fsubr setq \[function (car, cdr) { var atom = cdr.car; if (Lisp.atomp(atom)) { var args = cdr.cdr; if (Lisp.nullp(args)) atom.oval = undefined; else atom.oval = args.car.valueOf(); return atom; } return Atom.undef; }]) (fsubr set \[function (car, cdr) { var atom = cdr.car.valueOf(); if (Lisp.atomp(atom)) { var args = cdr.cdr; if (Lisp.nullp(args)) atom.oval = undefined; else atom.oval = args.car.valueOf(); return atom; } return Atom.undef; }]) (df oblist) (fsubr df \[function (car, cdr) { var atom = cdr.car; if (Lisp.atomp(atom)) { var def = cdr.cdr; if (Lisp.nullp(def)) atom.fval = undefined; else { atom.fval = new Fval ( // (f (a b) (c d)) Atom.fexpr, new Cons(Atom.flambda, def) ); return atom; } } return Atom.undef; }]) (fsubr de \[function (car, cdr) { var atom = cdr.car; if (Lisp.atomp(atom)) { var def = cdr.cdr; if (Lisp.nullp(def)) atom.fval = undefined; else { atom.fval = new Fval ( // (f '(a b) '(c d)) Atom.expr, new Cons(Atom.lambda, def) ); return atom; } } return Atom.undef; }]) (fsubr defun \[function (car, cdr) { var atom = cdr.car.valueOf(); if (Lisp.atomp(atom)) { var def = cdr.cdr; if (Lisp.nullp(def)) atom.fval = undefined; else { atom.fval = new Fval ( // (f '(a b) '(c d)) Atom.expr, new Cons(Atom.lambda, def) ); return atom; } } return Atom.undef; }]) (subr progn \[function (car, cdr) { var x = new Cons(); while (Lisp.consp(cdr) && !Lisp.nullp(cdr)) { x = cdr.car.valueOf(); // eval cdr = cdr.cdr; } return x; }]) (fsubr flet \[function (car, cdr) { var defs = cdr.car; var forms = cdr.cdr; var p = []; // new Array() var x = defs; if (Lisp.consp(x)) while (!Lisp.nullp(x)) { var def = x.car; if (Lisp.atomp(def)) { p.push({a: def}); } else if (Lisp.consp(def) && !Lisp.nullp(def)) { var atom = def.car; if (Lisp.atomp(atom)) { if (Lisp.nullp(def.cdr)) p.push({a: atom}); else { // maximum call stack size exceeded // (flet ((f (g) (g f))) // (g (f) (f g)))) // (f g)) // // maximum call stack size exceeded // (flet ((f () (f))) // (f)) // p.push ( { a: atom, v: new Fval(Atom.expr, new Cons(Atom.lambda, def.cdr)) } ); } } } x = x.cdr; } for (var x of p) { var atom = new Atom(x.a.name); atom.oval = x.a.oval; // let atom.fval = x.a.fval; // flet x.a.fval = x.v; } var val = Atom.undef; while (!Lisp.nullp(forms)) { val = forms.car.valueOf(); // eval forms = forms.cdr; } for (var x of p) { var atom = x.a.pop(); x.a.oval = atom.oval; // let x.a.fval = atom.fval; // flet } return val; }]) (fsubr let \[function (car, cdr) { var vars = cdr.car; var forms = cdr.cdr; var p = []; // new Array() var x = vars; if (Lisp.consp(x)) while (!Lisp.nullp(x)) { var pair = x.car; if (Lisp.atomp(pair)) { p.push({a: pair}); } else if (Lisp.consp(pair) && !Lisp.nullp(pair)) { if (Lisp.nullp(pair.cdr)) p.push({a: pair.car}); else p.push ( { a: pair.car, v: pair.cdr.car.valueOf() } ); } x = x.cdr; } for (var x of p) { var atom = new Atom(x.a.name); atom.oval = x.a.oval; // let atom.fval = x.a.fval; // flet x.a.oval = x.v; } var val = Atom.undef; while (!Lisp.nullp(forms)) { val = forms.car.valueOf(); // eval forms = forms.cdr; } for (var x of p) { var atom = x.a.pop(); x.a.oval = atom.oval; // let x.a.fval = atom.fval; // flet } return val; }]) (fsubr flambda \[function (car, cdr) { var def = cdr.car; if (!Lisp.consp(def)) return Lisp.noarg(car, cdr); var vars = def.car; var forms = def.cdr; function push(x) { if (Lisp.atomp(x)) // push { var atom = new Atom(x.name); atom.oval = x.oval; // let atom.fval = x.fval; // flet } else if (Lisp.consp(x)) while (!Lisp.nullp(x)) { push(x.car); x = x.cdr; } } push(vars); function set(x, l) { if (Lisp.atomp(x)) x.oval = l; else if (Lisp.consp(x)) while (!Lisp.nullp(x)) { if (Lisp.nullp(l)) break; set(x.car, l.car); x = x.cdr; l = l.cdr; } } set(vars, cdr.cdr); var val = Atom.undef; while (!Lisp.nullp(forms)) { val = forms.car.valueOf(); // eval forms = forms.cdr; } function pop(x) { if (Lisp.atomp(x)) // pop { var atom = x.pop(); x.oval = atom.oval; // let x.fval = atom.fval; // flet } else if (Lisp.consp(x)) while (!Lisp.nullp(x)) { pop(x.car); x = x.cdr; } } pop(vars); return val; }]) (fsubr lambda \[function (car, cdr) { var def = cdr.car; if (!Lisp.consp(def)) return Lisp.noarg(car, cdr); var vars = def.car; var forms = def.cdr; function push(x) { if (Lisp.atomp(x)) // push { var atom = new Atom(x.name); atom.oval = x.oval; // let atom.fval = x.fval; // flet } else if (Lisp.consp(x)) while (!Lisp.nullp(x)) { push(x.car); x = x.cdr; } } push(vars); function set(x, l) { if (Lisp.atomp(x)) x.oval = l; else if (Lisp.consp(x)) while (!Lisp.nullp(x)) { if (Lisp.nullp(l)) break; set(x.car, l.car); x = x.cdr; l = l.cdr; } } set(vars, cdr.cdr); var val = Atom.undef; while (!Lisp.nullp(forms)) { val = forms.car.valueOf(); // eval forms = forms.cdr; } function pop(x) { if (Lisp.atomp(x)) // pop { var atom = x.pop(); x.oval = atom.oval; // let x.fval = atom.fval; // flet } else if (Lisp.consp(x)) while (!Lisp.nullp(x)) { pop(x.car); x = x.cdr; } } pop(vars); return val; }]) (fsubr fexpr \[function (car, cdr) { var atom = cdr.car; if (Lisp.atomp(atom)) { var def = cdr.cdr; if (Lisp.nullp(def)) atom.fval = undefined; else { atom.fval = new Fval ( // (f (a b) (c d)) Atom.fexpr, new Cons(Atom.flambda, def) ); return atom; } } return Atom.undef; }]) (fsubr expr \[function (car, cdr) { var atom = cdr.car; if (Lisp.atomp(atom)) { var def = cdr.cdr; if (Lisp.nullp(def)) atom.fval = undefined; else { atom.fval = new Fval ( // (f '(a b) '(c d)) Atom.expr, new Cons(Atom.lambda, def) ); return atom; } } return Atom.undef; }]) (fsubr fsubr \[function (car, cdr) { var atom = cdr.car; if (Lisp.atomp(atom)) { var def = cdr.cdr; if (Lisp.nullp(def)) atom.fval = undefined; else { var self = def.car; if (Lisp.selfp(self)) { eval('def = ' + self.src); if (typeof def === "function") { // todo : def(car, cdr) =?: new Object(car, cdr) atom.fval = new Fval ( // (f '(a b) '(c d)) // (f (a b) (c d)) car, def ); return atom; } } } } return Atom.undef; }]) (fsubr subr \[function (car, cdr) { var atom = cdr.car; if (Lisp.atomp(atom)) { var def = cdr.cdr; if (Lisp.nullp(def)) atom.fval = undefined; else { var self = def.car; if (Lisp.selfp(self)) { eval('def = ' + self.src); if (typeof def === "function") { // todo : def(car, cdr) =?: new Object(car, cdr) atom.fval = new Fval ( // (f '(a b) '(c d)) // (f (a b) (c d)) car, def ); return atom; } } } } return Atom.undef; }]) (df undef)