use std::fmt;
use crate::Value;
#[derive(PartialEq, Clone)]
pub struct Cons {
inner: Box<(Value, Value)>,
}
impl fmt::Debug for Cons {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(fmt, "({:?} . {:?})", self.car(), self.cdr())
}
}
impl Cons {
pub fn new<T, U>(car: T, cdr: U) -> Self
where
T: Into<Value>,
U: Into<Value>,
{
Cons {
inner: Box::new((car.into(), cdr.into())),
}
}
pub fn car(&self) -> &Value {
&self.inner.0
}
pub fn car_mut(&mut self) -> &mut Value {
&mut self.inner.0
}
pub fn set_car(&mut self, car: impl Into<Value>) {
self.inner.0 = car.into()
}
pub fn cdr(&self) -> &Value {
&self.inner.1
}
pub fn cdr_mut(&mut self) -> &mut Value {
&mut self.inner.1
}
pub fn set_cdr(&mut self, cdr: impl Into<Value>) {
self.inner.1 = cdr.into()
}
pub fn as_pair(&self) -> (&Value, &Value) {
(&self.inner.0, &self.inner.1)
}
pub fn into_pair(self) -> (Value, Value) {
(self.inner.0, self.inner.1)
}
pub fn iter(&self) -> Iter<'_> {
Iter { cursor: Some(self) }
}
pub fn into_vec(self) -> (Vec<Value>, Value) {
let mut vec = Vec::new();
for (item, rest) in self.into_iter() {
vec.push(item);
if let Some(rest) = rest {
return (vec, rest);
}
}
unreachable!()
}
pub fn to_vec(&self) -> (Vec<Value>, Value) {
let mut vec = Vec::new();
for pair in self.iter() {
vec.push(pair.car().clone());
if !pair.cdr().is_cons() {
return (vec, pair.cdr().clone());
}
}
unreachable!()
}
pub fn to_ref_vec(&self) -> (Vec<&Value>, &Value) {
let mut vec = Vec::new();
for pair in self.iter() {
vec.push(pair.car());
if !pair.cdr().is_cons() {
return (vec, pair.cdr());
}
}
unreachable!()
}
pub fn list_iter(&self) -> ListIter<'_> {
ListIter::cons(self)
}
}
impl IntoIterator for Cons {
type Item = (Value, Option<Value>);
type IntoIter = IntoIter;
fn into_iter(self) -> IntoIter {
IntoIter { cursor: Some(self) }
}
}
impl<'a> IntoIterator for &'a Cons {
type Item = &'a Cons;
type IntoIter = Iter<'a>;
fn into_iter(self) -> Iter<'a> {
self.iter()
}
}
pub struct Iter<'a> {
cursor: Option<&'a Cons>,
}
impl<'a> Iter<'a> {
pub fn peek(&self) -> Option<&Cons> {
self.cursor
}
}
impl<'a> Iterator for Iter<'a> {
type Item = &'a Cons;
fn next(&mut self) -> Option<Self::Item> {
match self.cursor {
Some(pair) => {
match pair.cdr() {
Value::Cons(pair) => self.cursor = Some(pair),
_ => self.cursor = None,
}
Some(pair)
}
None => None,
}
}
}
pub struct IntoIter {
cursor: Option<Cons>,
}
impl IntoIter {
pub fn peek(&self) -> Option<&Cons> {
self.cursor.as_ref()
}
pub fn peek_mut(&mut self) -> Option<&mut Cons> {
self.cursor.as_mut()
}
}
impl Iterator for IntoIter {
type Item = (Value, Option<Value>);
fn next(&mut self) -> Option<Self::Item> {
match self.cursor.take() {
Some(cell) => {
let (car, cdr) = cell.into_pair();
match cdr {
Value::Cons(cell) => {
self.cursor = Some(cell);
Some((car, None))
}
_ => {
self.cursor = None;
Some((car, Some(cdr)))
}
}
}
None => None,
}
}
}
#[derive(Debug, Clone)]
pub struct ListIter<'a>(ListCursor<'a>);
#[derive(Debug, Clone)]
enum ListCursor<'a> {
Cons(&'a Cons),
Dot(&'a Value),
Rest(&'a Value),
Exhausted,
}
impl<'a> ListIter<'a> {
pub fn is_empty(&self) -> bool {
match &self.0 {
ListCursor::Exhausted => true,
_ => false,
}
}
pub fn peek(&self) -> Option<&Value> {
match &self.0 {
ListCursor::Cons(cell) => Some(cell.car()),
ListCursor::Dot(_) => None,
ListCursor::Rest(value) => Some(value),
ListCursor::Exhausted => None,
}
}
pub(crate) fn empty() -> Self {
ListIter(ListCursor::Exhausted)
}
pub(crate) fn cons(cell: &'a Cons) -> Self {
ListIter(ListCursor::Cons(cell))
}
}
impl<'a> Iterator for ListIter<'a> {
type Item = &'a Value;
fn next(&mut self) -> Option<Self::Item> {
match self.0 {
ListCursor::Cons(cell) => {
let car = cell.car();
match cell.cdr() {
Value::Cons(next) => {
self.0 = ListCursor::Cons(next);
}
Value::Null => {
self.0 = ListCursor::Exhausted;
}
cdr => {
self.0 = ListCursor::Dot(cdr);
}
}
Some(car)
}
ListCursor::Dot(value) => {
self.0 = ListCursor::Rest(value);
None
}
ListCursor::Rest(value) => {
self.0 = ListCursor::Exhausted;
Some(value)
}
ListCursor::Exhausted => None,
}
}
}