use std::fmt;

use crate::vm::value::Value;

#[derive(Debug, Clone, PartialEq)]
pub struct ConsCell(pub Value, pub Value);

impl ConsCell {
    pub fn end(value: Value) -> Self {
        Self(value, Value::Nil)
    }

    fn fmt_inner(&self, f: &mut fmt::Formatter<'_>, first: bool) -> fmt::Result {
        let Self(car, cdr) = self;
        if !first {
            write!(f, " ")?;
        }
        write!(f, "{car}")?;
        match cdr {
            Value::Nil => Ok(()),
            Value::Cons(cons) => cons.fmt_inner(f, false),
            _ => {
                write!(f, " . {cdr}")
            }
        }
    }
}

impl fmt::Display for ConsCell {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.fmt_inner(f, true)
    }
}
