feat(prelude): add print function
This commit is contained in:
parent
b51e185c21
commit
8f1b1840ad
@ -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.
|
||||
|
||||
@ -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<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 {
|
||||
type Error = EvalError;
|
||||
fn try_into(self) -> Result<i64, Self::Error> {
|
||||
@ -48,15 +68,27 @@ impl TryInto<i64> for Expression {
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
impl TryInto<f64> for Expression {
|
||||
type Error = EvalError;
|
||||
fn try_into(self) -> Result<f64, Self::Error> {
|
||||
match self {
|
||||
Expression::Float(f) => Ok(f),
|
||||
_ => 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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
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));
|
||||
}
|
||||
|
||||
16
src/main.rs
16
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),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user