diff --git a/src/main.rs b/src/main.rs index 742854d..3a44c4e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -610,6 +610,7 @@ pub fn rw(rule: &Rule, sexp: &Sexp) -> Sexp { pub fn simp(rules: &[Rule], mut expr: Sexp, step_limit: usize, complexity_limit: usize) -> Sexp { for _ in 0..step_limit { expr = expr + .apply_special_form::() .apply_special_form::() .apply_special_form::() .apply_special_form::() @@ -867,6 +868,42 @@ impl<'src> SpecialForm<'src> for LambdaLike<'src> { } } +static QUOTE: Lazy = Lazy::new(|| TABLE.lock().unwrap().intern("quote").unwrap()); +static CONS: Lazy = Lazy::new(|| TABLE.lock().unwrap().intern("cons").unwrap()); + +// sbcl has quote take one arg.... +#[derive(Debug, Clone)] +struct Quote<'src>(&'src Sexp); + +impl<'src> SpecialForm<'src> for Quote<'src> { + fn from_sexp(sexp: &'src Sexp) -> Option { + match sexp { + Sexp::Atom(_) => None, + Sexp::List(xs) => match &xs[..] { + [Sexp::Atom(quote), expr] if *quote == *QUOTE => Some(Self(expr)), + _ => None, + }, + } + } + + fn eval(self) -> Sexp { + let Self(expr) = self; + + match expr { + Sexp::Atom(at) => Sexp::Atom(*at), + Sexp::List(xs) => consify(xs), + } + } +} + +fn consify(xs: &[Sexp]) -> Sexp { + if xs.is_empty() { + Sexp::nil() + } else { + Sexp::List(vec![Sexp::Atom(*CONS), consify(&xs[1..])]) + } +} + pub fn make_rule(sexp: &Sexp) -> Option { match sexp { Sexp::List(xs) => match &xs[..] {