use std::iter; use crate::sexp::SExp; use crate::sexp::SLeaf; use crate::sexp::SExp::*; use crate::sexp::SLeaf::*; impl From for Box { fn from(int: i32) -> Self { Box::new(Atom(Int(int))) } } impl From for Box { fn from(leaf: SLeaf) -> Self { Box::new(Atom(leaf)) } } impl From for SLeaf { fn from(int: i32) -> Self { Int(int) } } pub fn scons(x: impl Into>, y: impl Into>) -> SExp { SCons(x.into(), y.into()) } pub fn var(name: &str) -> SExp { Atom(Var(name.to_string())) } impl SExp { /// Transforms this SExp into a Vec. /// /// Errors if the left-hand side of SCons has an SCons, /// or if the passed SExp is an Atom, or if the /// lists aren't Nil-terminated. /// /// ```rust /// use melisp::sexp::{SExp::*, SLeaf::*, util::*}; /// assert_eq!( /// scons(1, scons(2, scons(3, Nil))).into_vec(), /// Ok(vec![Int(1), Int(2), Int(3)]) /// ); /// assert!(scons(scons(1, Nil), Nil).into_vec().is_err()); /// assert!(scons(1, 2).into_vec().is_err()); /// ``` pub fn into_vec(self) -> Result, String> { match self { SCons(a, b) => match (*a, *b) { (Atom(a), Atom(Nil)) => Ok(iter::once(a).collect::>()), (Atom(a), b) => Ok(iter::once(a).chain(b.into_vec()?).collect::>()), (a, b) => Err(format!("invalid list structure: {:?}", scons(a, b))) }, _ => Err("expected list, found atom".to_string()), } } pub fn parts(self) -> Vec { match self { Atom(x) => vec![Atom(x)], SCons(a, b) if *b == Atom(Nil) => vec![*a], SCons(a, b) => { let mut res = vec![*a]; res.extend_from_slice(&(*b).parts()); res }, } } }