diff --git a/src/lisp/eval.rs b/src/lisp/eval.rs index 592fa6c..7b28ef9 100644 --- a/src/lisp/eval.rs +++ b/src/lisp/eval.rs @@ -1,3 +1,5 @@ +use std::fmt::Display; + use super::environment::Environment; use super::environment::EnvironmentLayer; use super::expression::Expression; @@ -13,6 +15,19 @@ pub enum EvalError { NotASymbol(Expression), } +impl Display for EvalError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + EvalError::SymbolNotBound(s) => write!(f, "Symbol {} is not bound", s), + EvalError::NotAFunction(e) => write!(f, "Expression {} is not a function", e), + EvalError::NotANumber(e) => write!(f, "Expression {} is not a number", e), + EvalError::ArgumentError(s) => write!(f, "Argument error: {}", s), + EvalError::TypeError(s) => write!(f, "Type error: {}", s), + EvalError::NotASymbol(e) => write!(f, "Expression {} is not a symbol", e), + } + } +} + /// A CellIterator is a convenience struct to iterate a linked cons list. /// The Iterator returns Ok(Expression) as long, as there are elements in the list. /// Err(EvalError) is returned when the right side of a cons cell is not another cons cell or nil. diff --git a/src/lisp/expression.rs b/src/lisp/expression.rs index bda9957..6ceb650 100644 --- a/src/lisp/expression.rs +++ b/src/lisp/expression.rs @@ -1,3 +1,5 @@ +use std::fmt::Display; + use super::environment::Environment; use super::eval::CellIterator; use super::eval::EvalError; @@ -36,6 +38,24 @@ impl From Result> for Exp } } +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, Expression)> for Expression { + fn from(value: (Expression, Expression)) -> Self { + Expression::Cell(Box::new(value.0), Box::new(value.1)) + } +} + impl TryInto for Expression { type Error = EvalError; fn try_into(self) -> Result { @@ -48,15 +68,27 @@ impl TryInto for Expression { } } -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)); +impl TryInto for Expression { + type Error = EvalError; + fn try_into(self) -> Result { + match self { + Expression::Float(f) => Ok(f), + _ => Err(EvalError::TypeError( + "Expression is not a Float".to_string(), + )), } + } +} - current +impl TryInto for Expression { + type Error = EvalError; + fn try_into(self) -> Result { + match self { + Expression::String(s) => Ok(s), + _ => Err(EvalError::TypeError( + "Expression is not a String".to_string(), + )), + } } } @@ -91,3 +123,35 @@ impl TryInto<(Expression, Expression)> for Expression { } } } + +impl Display for Expression { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + 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"), + } + } +} diff --git a/src/lisp/prelude.rs b/src/lisp/prelude.rs index 0e4a5fd..6e4967d 100644 --- a/src/lisp/prelude.rs +++ b/src/lisp/prelude.rs @@ -170,6 +170,13 @@ pub fn prelude_set(env: &Environment, expr: Expression) -> Result Result { + let [e] = expr.try_into()?; + let e = eval(env, e)?; + println!("Prelude: {}", e); + Ok(e) +} + pub fn mk_prelude(layer: &mut EnvironmentLayer) { layer.set("+".to_string(), Expression::Function(prelude_add)); layer.set("-".to_string(), Expression::Function(prelude_sub)); @@ -182,4 +189,5 @@ pub fn mk_prelude(layer: &mut EnvironmentLayer) { layer.set(">".to_string(), Expression::Function(prelude_gt)); layer.set("let".to_string(), Expression::Function(prelude_let)); layer.set("set".to_string(), Expression::Function(prelude_set)); + layer.set("print".to_string(), Expression::Function(prelude_print)); } diff --git a/src/main.rs b/src/main.rs index 1f62b89..677a98f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,9 +7,9 @@ use crate::lisp::{eval, Environment}; fn main() { let program1 = "((lambda (x y) (+ (if (< x 10) (* x 11) x) y)) 2 20)"; let program2 = "(set myvar \"hello world!\")"; - let program3 = "myvar"; + let program3 = "(print myvar)"; - let mut environment = Environment::default(); + let environment = Environment::default(); for r in ExpressionStream::from_char_stream( program1 @@ -19,11 +19,13 @@ fn main() { ) { match r { Err(err) => println!("ParserError: {:?}", err), - Ok(expr) => println!( - "{:?} \n vvvvvvvvvvv \n {:?}\n", - expr.clone(), - eval(&environment, expr) - ), + Ok(expr) => { + println!("Evaluating: {}", expr.clone()); + match eval(&environment, expr) { + Ok(e) => println!("=> {}", e), + Err(e) => println!("Error: {}", e), + } + } } }