feat(prelude): add print function

This commit is contained in:
Jonas Röger 2024-11-06 11:00:57 +01:00
parent b51e185c21
commit 8f1b1840ad
Signed by: jonas
GPG Key ID: 4000EB35E1AE0F07
4 changed files with 103 additions and 14 deletions

View File

@ -1,3 +1,5 @@
use std::fmt::Display;
use super::environment::Environment; use super::environment::Environment;
use super::environment::EnvironmentLayer; use super::environment::EnvironmentLayer;
use super::expression::Expression; use super::expression::Expression;
@ -13,6 +15,19 @@ pub enum EvalError {
NotASymbol(Expression), 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. /// 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. /// 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. /// Err(EvalError) is returned when the right side of a cons cell is not another cons cell or nil.

View File

@ -1,3 +1,5 @@
use std::fmt::Display;
use super::environment::Environment; use super::environment::Environment;
use super::eval::CellIterator; use super::eval::CellIterator;
use super::eval::EvalError; use super::eval::EvalError;
@ -36,6 +38,24 @@ impl From<fn(&Environment, Expression) -> Result<Expression, EvalError>> for Exp
} }
} }
impl From<Vec<Expression>> for Expression {
fn from(mut value: Vec<Expression>) -> 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<i64> for Expression { impl TryInto<i64> for Expression {
type Error = EvalError; type Error = EvalError;
fn try_into(self) -> Result<i64, Self::Error> { fn try_into(self) -> Result<i64, Self::Error> {
@ -48,15 +68,27 @@ impl TryInto<i64> for Expression {
} }
} }
impl From<Vec<Expression>> for Expression { impl TryInto<f64> for Expression {
fn from(mut value: Vec<Expression>) -> Self { type Error = EvalError;
let mut current = Expression::Nil; fn try_into(self) -> Result<f64, Self::Error> {
match self {
for e in value.iter_mut().rev() { Expression::Float(f) => Ok(f),
current = Expression::Cell(Box::new(e.to_owned()), Box::new(current)); _ => Err(EvalError::TypeError(
"Expression is not a Float".to_string(),
)),
}
}
} }
current impl TryInto<String> for Expression {
type Error = EvalError;
fn try_into(self) -> Result<String, Self::Error> {
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<Vec<Expression>, EvalError> {
Ok(lst) => write!(
f,
"({})",
lst.iter()
.map(|e| e.to_string())
.collect::<Vec<String>>()
.join(" ")
),
Err(_) => write!(f, "({} . {})", a, b),
}
}
Expression::Function(_) => write!(f, "<function>"),
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"),
}
}
}

View File

@ -170,6 +170,13 @@ pub fn prelude_set(env: &Environment, expr: Expression) -> Result<Expression, Ev
} }
} }
pub fn prelude_print(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
let [e] = expr.try_into()?;
let e = eval(env, e)?;
println!("Prelude: {}", e);
Ok(e)
}
pub fn mk_prelude(layer: &mut EnvironmentLayer) { pub fn mk_prelude(layer: &mut EnvironmentLayer) {
layer.set("+".to_string(), Expression::Function(prelude_add)); layer.set("+".to_string(), Expression::Function(prelude_add));
layer.set("-".to_string(), Expression::Function(prelude_sub)); 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(">".to_string(), Expression::Function(prelude_gt));
layer.set("let".to_string(), Expression::Function(prelude_let)); layer.set("let".to_string(), Expression::Function(prelude_let));
layer.set("set".to_string(), Expression::Function(prelude_set)); layer.set("set".to_string(), Expression::Function(prelude_set));
layer.set("print".to_string(), Expression::Function(prelude_print));
} }

View File

@ -7,9 +7,9 @@ use crate::lisp::{eval, Environment};
fn main() { fn main() {
let program1 = "((lambda (x y) (+ (if (< x 10) (* x 11) x) y)) 2 20)"; let program1 = "((lambda (x y) (+ (if (< x 10) (* x 11) x) y)) 2 20)";
let program2 = "(set myvar \"hello world!\")"; 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( for r in ExpressionStream::from_char_stream(
program1 program1
@ -19,11 +19,13 @@ fn main() {
) { ) {
match r { match r {
Err(err) => println!("ParserError: {:?}", err), Err(err) => println!("ParserError: {:?}", err),
Ok(expr) => println!( Ok(expr) => {
"{:?} \n vvvvvvvvvvv \n {:?}\n", println!("Evaluating: {}", expr.clone());
expr.clone(), match eval(&environment, expr) {
eval(&environment, expr) Ok(e) => println!("=> {}", e),
), Err(e) => println!("Error: {}", e),
}
}
} }
} }