Multiple implementations (JS, Wasm, C) of a Lisp.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

64 lines
1.9 KiB

import { DataTypes, Cons, Nil } from './datatypes.js';
import { Env } from './env.js';
export class Evaluator {
static async expand(sexp, macros) {
if (sexp.type === DataTypes.Cons) {
const op = await Evaluator.expand(sexp.car, macros)
if (op.type === DataTypes.SpecialForm) {
return await op.value(sexp.cdr, macros, macros);
} else if (op.type === DataTypes.Macro) {
return await op.value(
await Cons.map(sexp.cdr,
async o => await Evaluator.expand(o, macros)));
// return (sexp.cdr.type === DataTypes.Nil
// ? sexp.cdr
// : Cons.reverse(await Cons.reduce(
// sexp.cdr,
// (p, o) => new Cons(await Evaluator.expand(o, macros), p),
// new Nil())))
// .then(opts => op.value(opts));
} else if (sexp.type === DataTypes.Symbol) {
return Env.find(macros, sexp.value) || sexp;
}
return sexp;
}
if (sexp.type === DataTypes.Symbol) {
return Env.find(macros, sexp.value) || sexp;
}
return sexp;
}
static async eval(sexp, env, macros) {
sexp = await Evaluator.expand(sexp, macros)
if (sexp.type === DataTypes.Cons) {
const op = await Evaluator.eval(sexp.car, env, macros)
if (op.type === DataTypes.SpecialForm) {
return await op.value(sexp.cdr, env, macros);
} else if (op.type === DataTypes.Function) {
return await op.value(await Cons.map(sexp.cdr, async o => Evaluator.eval(o, env, macros)));
// return (sexp.cdr.type === DataTypes.Nil
// ? Promise.resolve(sexp.cdr)
// : Cons.reduce(
// sexp.cdr,
// (p, o) => p.then(v => Evaluator.eval(o, env, macros)
// .then(ve => new Cons(ve, v))),
// Promise.resolve(new Nil()))
// .then(v => Cons.reverse(v)))
// .then(opts => op.value(opts));
}
throw 'Illegal function call';
}
if (sexp.type === DataTypes.Symbol) {
return Env.get(env, sexp.value);
}
return sexp;
}
}