use std::any::Any; use std::fmt::Debug; use std::fmt::Display; use std::ops::Deref; use std::ops::DerefMut; use as_any::AsAny; use super::environment::Environment; use super::eval::CellIterator; use super::eval::EvalError; /// A trait for foreign data types that can be used in lisp expressions. /// Note: This trait requires explicit implementation of: /// - partial_cmp_impl /// - clone_impl /// - eq_impl /// - as_any_box /// to ensure object safety. pub trait ForeignData: Debug + Display + AsAny { fn partial_cmp_impl(&self, other: &dyn ForeignData) -> Option; fn clone_impl(&self) -> Box; fn eq_impl(&self, other: &dyn ForeignData) -> bool; fn as_any_box(self: Box) -> Box; } impl ForeignData for T { fn partial_cmp_impl(&self, other: &dyn ForeignData) -> Option { if let Some(other) = other.as_any().downcast_ref::() { self.partial_cmp(other) } else { None } } fn clone_impl(&self) -> Box { Box::new(self.clone()) } fn eq_impl(&self, other: &dyn ForeignData) -> bool { if let Some(other) = other.as_any().downcast_ref::() { self.eq(other) } else { false } } fn as_any_box(self: Box) -> Box { self } } /// A wrapper struct around any foreign data type. This struct is used to convert /// any T implementing ForeignData to an Expression and vice versa. #[derive(Debug)] pub struct ForeignDataWrapper(pub Box); impl ForeignDataWrapper { /// Create a new ForeignDataWrapper from an object implementing ForeignData. pub fn new(data: T) -> Self { ForeignDataWrapper(Box::new(data)) } } impl Deref for ForeignDataWrapper { type Target = T; fn deref(&self) -> &Self::Target { &self.0 } } impl DerefMut for ForeignDataWrapper { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } #[derive(Debug)] /// A Store struct for foreign data types injected in expressions. pub struct ForeignDataStore { /// The actual foreign data. data: Box, } /// The ForeignDataStore struct is used to store any foreign data type in an Expression /// and cannot be constructed outside of this scope. impl ForeignDataStore { /// Create a new ForeignDataStore from a ForeignData trait object. fn new(data: Box) -> Self { ForeignDataStore { data } } /// Get the contained box as an Any-Box with type info of the actual data. fn as_any_box(self) -> Box { self.data.as_any_box() } } impl Clone for ForeignDataStore { fn clone(&self) -> Self { ForeignDataStore { data: self.data.clone_impl(), } } } impl PartialEq for ForeignDataStore { fn eq(&self, other: &Self) -> bool { self.data.eq_impl(other.data.as_ref()) } } impl PartialOrd for ForeignDataStore { fn partial_cmp(&self, other: &Self) -> Option { self.data.partial_cmp_impl(other.data.as_ref()) } } impl Display for ForeignDataStore { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.data) } } #[derive(Clone, Debug, PartialEq, PartialOrd)] /// A sum type of all possible lisp expressions. pub enum Expression { /// The classic lisp cons cell aka (a . b) used to construct expressions. Cell(Box, Box), /// A function expression pointing to native code. Function(fn(&Environment, Expression) -> Result), /// A anonymous function expression consisting of bound symbols and a body expression. AnonymousFunction { argument_symbols: Vec, body: Box, }, /// A foreign data expression. ForeignExpression(ForeignDataStore), /// A Quoted expression. Quote(Box), /// A symbol. Symbol(String), /// Integer values. Integer(i64), /// Float values. Float(f64), /// String values. String(String), /// True True, /// Nil Nil, } impl From> for Expression { fn from(value: ForeignDataWrapper) -> Expression { Expression::ForeignExpression(ForeignDataStore::new(value.0)) } } impl TryFrom for ForeignDataWrapper { type Error = EvalError; fn try_from(value: Expression) -> Result { match value { Expression::ForeignExpression(f) => match f.as_any_box().downcast::() { Ok(data) => Ok(ForeignDataWrapper(data)), Err(_) => Err(EvalError::TypeError( "Expression is not a ForeignDataWrapper".to_string(), )), }, _ => Err(EvalError::TypeError( "Expression is not a ForeignDataWrapper".to_string(), )), } } } impl From Result> for Expression { fn from(f: fn(&Environment, Expression) -> Result) -> Self { Expression::Function(f) } } impl From> for Expression { fn from(mut value: Vec) -> Self { let mut current = Expression::Nil; for e in value.iter_mut().rev() { current = Expression::Cell(Box::new(e.to_owned()), Box::new(current)); } current } } impl From<[Expression; N]> for Expression { fn from(mut value: [Expression; N]) -> Self { let mut current = Expression::Nil; for e in value.iter_mut().rev() { current = Expression::Cell(Box::new(e.to_owned()), Box::new(current)); } current } } impl From<(Expression, Expression)> for Expression { fn from(value: (Expression, Expression)) -> Self { Expression::Cell(Box::new(value.0), Box::new(value.1)) } } impl From for Expression { fn from(value: i64) -> Self { Expression::Integer(value) } } impl From for Expression { fn from(value: f64) -> Self { Expression::Float(value) } } impl From for Expression { fn from(value: String) -> Self { Expression::String(value) } } impl From for Expression { fn from(value: bool) -> Self { if value { Expression::True } else { Expression::Nil } } } impl TryFrom for i64 { type Error = EvalError; fn try_from(value: Expression) -> Result { match value { Expression::Integer(i) => Ok(i), _ => Err(EvalError::TypeError( "Expression is not an Integer".to_string(), )), } } } impl TryFrom for f64 { type Error = EvalError; fn try_from(value: Expression) -> Result { match value { Expression::Integer(i) => Ok(i as f64), Expression::Float(f) => Ok(f), _ => Err(EvalError::TypeError( "Expression is not a Float".to_string(), )), } } } impl TryFrom for String { type Error = EvalError; fn try_from(value: Expression) -> Result { match value { Expression::String(s) => Ok(s), _ => Err(EvalError::TypeError( "Expression is not a String".to_string(), )), } } } impl TryFrom for Vec { type Error = EvalError; fn try_from(value: Expression) -> Result, Self::Error> { CellIterator::new(value).collect() } } impl TryFrom for Vec where ToExpr: TryFrom, { type Error = EvalError; fn try_from(value: Expression) -> Result, Self::Error> { CellIterator::new(value) .map(|x| x?.try_into() as Result) .collect() } } impl TryFrom for [ToExpr; N] where ToExpr: TryFrom, { type Error = EvalError; fn try_from(value: Expression) -> Result<[ToExpr; N], Self::Error> { let buf: Vec = value.try_into()?; let n = buf.len(); buf.try_into() .map_err(|_| EvalError::ArgumentError(format!("Expected {} arguments, got {}", N, n))) } } impl TryFrom for [Expression; N] { type Error = EvalError; fn try_from(value: Expression) -> Result<[Expression; N], Self::Error> { let buf: Vec = value.try_into()?; let n = buf.len(); buf.try_into() .map_err(|_| EvalError::ArgumentError(format!("Expected {} arguments, got {}", N, n))) } } impl TryFrom for (Expression, Expression) { type Error = EvalError; fn try_from(value: Expression) -> Result<(Expression, Expression), Self::Error> { match value { Expression::Cell(a, b) => Ok((*a, *b)), _ => Err(EvalError::TypeError( "Expression must be a Cell".to_string(), )), } } } impl Display for Expression { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Expression::ForeignExpression(e) => write!(f, "{}", e), Expression::Cell(a, b) => { match self.clone().try_into() as Result, EvalError> { Ok(lst) => write!( f, "({})", lst.iter() .map(|e| e.to_string()) .collect::>() .join(" ") ), Err(_) => write!(f, "({} . {})", a, b), } } Expression::Function(_) => write!(f, ""), Expression::AnonymousFunction { argument_symbols, body, } => write!(f, "(lambda ({}) {})", argument_symbols.join(" "), body), Expression::Quote(e) => write!(f, "'{}", e), Expression::Symbol(s) => write!(f, "{}", s), Expression::Integer(i) => write!(f, "{}", i), Expression::Float(fl) => write!(f, "{}", fl), Expression::String(s) => write!(f, "\"{}\"", s), Expression::True => write!(f, "true"), Expression::Nil => write!(f, "nil"), } } }