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
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; |
|
|
|
} |
|
}
|
|
|