#[macro_use]
mod from;
mod display;
mod eval;
mod iter;
mod parse;
use super::{utils, Error, Primitive, Result, SyntaxError};
use self::SExp::{Atom, Null, Pair};
#[derive(PartialEq, Clone)]
pub enum SExp {
Null,
Atom(Primitive),
Pair { head: Box<SExp>, tail: Box<SExp> },
}
impl SExp {
pub(super) fn split_car(self) -> ::std::result::Result<(Self, Self), Error> {
match self {
Null => Err(Error::NullList),
Atom(_) => Err(Error::NotAList {
atom: self.to_string(),
}),
Pair { head, tail } => Ok((*head, *tail)),
}
}
pub(super) fn car(self) -> Result {
Ok(self.split_car()?.0)
}
pub(super) fn cdr(self) -> Result {
Ok(self.split_car()?.1)
}
pub(super) fn set_car(&mut self, new: Self) -> Result {
match self {
Null => Err(Error::NullList),
Atom(_) => Err(Error::NotAList {
atom: self.to_string(),
}),
Pair { head, .. } => {
*head = Box::new(new);
Ok(Atom(Primitive::Undefined))
}
}
}
pub(super) fn set_cdr(&mut self, new: Self) -> Result {
match self {
Null => Err(Error::NullList),
Atom(_) => Err(Error::NotAList {
atom: self.to_string(),
}),
Pair { tail, .. } => {
*tail = Box::new(new);
Ok(Atom(Primitive::Undefined))
}
}
}
#[must_use]
pub fn cons(self, exp: Self) -> Self {
Pair {
head: Box::new(exp),
tail: Box::new(self),
}
}
#[must_use]
pub fn sym(sym: &str) -> Self {
Atom(Primitive::Symbol(sym.to_string()))
}
#[must_use]
pub fn type_of(&self) -> &str {
match self {
Null => "null",
Atom(p) => p.type_of(),
Pair { .. } => "list",
}
}
}