From b51e185c218fef8a8024155e47e732819baa8ea9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20R=C3=B6ger?= Date: Tue, 5 Nov 2024 23:25:26 +0100 Subject: [PATCH] feat: add shared environment/set --- src/lisp/environment.rs | 76 ++++++++++-- src/lisp/eval.rs | 94 ++++++++++++++ src/lisp/expression.rs | 269 +--------------------------------------- src/lisp/mod.rs | 6 +- src/lisp/prelude.rs | 185 +++++++++++++++++++++++++++ src/main.rs | 21 +++- 6 files changed, 367 insertions(+), 284 deletions(-) create mode 100644 src/lisp/eval.rs create mode 100644 src/lisp/prelude.rs diff --git a/src/lisp/environment.rs b/src/lisp/environment.rs index a798fd5..577733e 100644 --- a/src/lisp/environment.rs +++ b/src/lisp/environment.rs @@ -1,5 +1,10 @@ -use super::expression::Expression; -use std::collections::HashMap; +use super::{expression::Expression, prelude::mk_prelude}; +use std::{ + borrow::BorrowMut, + cell::{RefCell, RefMut}, + collections::HashMap, + rc::Rc, +}; #[derive(PartialEq, Clone, Debug)] /// A Environment is a stack of `EnvironmentLayer`s. Each `EnvironmentLayer` is a mapping from @@ -9,6 +14,8 @@ pub struct Environment<'a> { layer: EnvironmentLayer, /// The outer _fallback_ mapping. outer: Option<&'a Environment<'a>>, + /// A shared layer taking precendence over the outer layer, but not the current layer. + shared: Rc>, } #[derive(PartialEq, Clone, Debug)] @@ -31,8 +38,8 @@ impl EnvironmentLayer { } /// Get a value in the `EnvironmentLayer`. - pub fn get(&self, key: &str) -> Option<&Expression> { - self.symbols.get(key) + pub fn get(&self, key: &str) -> Option { + self.symbols.get(key).cloned() } } @@ -48,12 +55,17 @@ impl<'a> Environment<'a> { Environment { layer: EnvironmentLayer::new(), outer: None, + shared: Rc::new(RefCell::new(EnvironmentLayer::new())), } } /// Construct an `Environment` from a `EnvironmentLayer` with no outer `Environment`. pub fn from_layer(layer: EnvironmentLayer) -> Self { - Environment { layer, outer: None } + Environment { + layer, + outer: None, + shared: Rc::new(RefCell::new(EnvironmentLayer::new())), + } } /// Construct a new `Environment` with `self` as the outer `Environment`. @@ -61,6 +73,7 @@ impl<'a> Environment<'a> { Environment { layer: EnvironmentLayer::new(), outer: Some(self), + shared: self.shared.clone(), } } @@ -69,15 +82,43 @@ impl<'a> Environment<'a> { Environment { layer, outer: Some(&self), + shared: Rc::new(RefCell::new(EnvironmentLayer::new())), + } + } + + /// Set a value in the shared layer. + /// + /// Panics: + /// - if the shared layer cannot be borrowed mutably. + pub fn shared_set(&self, key: String, value: Expression) { + match self.shared.try_borrow_mut() { + Ok(mut shared) => shared.set(key, value), + Err(e) => panic!("Cannot borrow shared layer mutably. ({})", e), + } + } + + /// Get a value from the shared layer. + pub fn shared_get(&self, key: &str) -> Option { + self.shared.borrow().get(key) + } + + /// Get a value from the `Environment`, without looking at the shared layer. + pub fn layer_get(&self, key: &str) -> Option { + if let Some(e) = self.layer.get(key) { + Some(e) + } else { + self.outer?.layer_get(key).clone() } } /// Get a value from the `Environment`. - pub fn get(&self, key: &str) -> Option<&Expression> { + pub fn get(&self, key: &str) -> Option { if let Some(e) = self.layer.get(key) { Some(e) + } else if let Some(e) = self.shared_get(key) { + Some(e) } else { - self.outer?.get(key) + self.outer?.layer_get(key).clone() } } @@ -87,6 +128,19 @@ impl<'a> Environment<'a> { } } +impl Default for Environment<'_> { + /// Get the default prelude layer + fn default() -> Self { + let mut prelude = EnvironmentLayer::new(); + mk_prelude(&mut prelude); + Environment { + layer: prelude, + outer: None, + shared: Rc::new(RefCell::new(EnvironmentLayer::new())), + } + } +} + #[test] fn test_environment() { let mut env = Environment::new(); @@ -94,9 +148,9 @@ fn test_environment() { env.set("b".to_string(), Expression::Integer(2)); let mut inner = env.mk_inner(); inner.set("a".to_string(), Expression::Integer(3)); - assert_eq!(inner.get("a"), Some(&Expression::Integer(3))); - assert_eq!(inner.get("b"), Some(&Expression::Integer(2))); - assert_eq!(env.get("a"), Some(&Expression::Integer(1))); - assert_eq!(env.get("b"), Some(&Expression::Integer(2))); + assert_eq!(inner.get("a"), Some(Expression::Integer(3))); + assert_eq!(inner.get("b"), Some(Expression::Integer(2))); + assert_eq!(env.get("a"), Some(Expression::Integer(1))); + assert_eq!(env.get("b"), Some(Expression::Integer(2))); assert_eq!(env.get("c"), None); } diff --git a/src/lisp/eval.rs b/src/lisp/eval.rs new file mode 100644 index 0000000..592fa6c --- /dev/null +++ b/src/lisp/eval.rs @@ -0,0 +1,94 @@ +use super::environment::Environment; +use super::environment::EnvironmentLayer; +use super::expression::Expression; + +#[derive(Debug)] +/// All possible evaluation errors +pub enum EvalError { + SymbolNotBound(String), + NotAFunction(Expression), + NotANumber(Expression), + ArgumentError(String), + TypeError(String), + NotASymbol(Expression), +} + +/// 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. +pub struct CellIterator { + expr: Option, +} + +impl CellIterator { + pub fn new(expr: Expression) -> CellIterator { + CellIterator { expr: Some(expr) } + } +} + +impl Iterator for CellIterator { + type Item = Result; + fn next(&mut self) -> Option { + if let Some(expr) = self.expr.take() { + match expr { + Expression::Cell(head, tail) => { + self.expr = Some(*tail); + return Some(Ok(*head)); + } + Expression::Nil => { + return None; + } + _ => { + return Some(Err(EvalError::TypeError( + "Expected a cell or nil".to_string(), + ))); + } + } + } else { + None + } + } +} + +/// Dispatch an anonymous function call. Evaluates `body` in `env`, binding `args` to `argument_symbols` +fn dispatch_anonymous_function( + env: &Environment, + argument_symbols: Vec, + body: Expression, + args: Expression, +) -> Result { + let mut args: Vec = args.try_into()?; + + let mut overlay = EnvironmentLayer::new(); + + if args.len() != argument_symbols.len() { + return Err(EvalError::ArgumentError(format!( + "Exprected {} arguments, got {}", + argument_symbols.len(), + args.len() + ))); + } + + for (arg, symbol) in args.iter_mut().zip(argument_symbols.iter()) { + overlay.set(symbol.to_owned(), arg.to_owned()); + } + + eval(&env.overlay(overlay), body) +} + +/// Evaluate an expression inside an environment +pub fn eval(env: &Environment, expr: Expression) -> Result { + match expr { + Expression::Cell(lhs, rhs) => match eval(env, *lhs)? { + Expression::Function(f) => f(env, *rhs), + Expression::AnonymousFunction { + argument_symbols, + body, + } => dispatch_anonymous_function(env, argument_symbols, *body, *rhs), + a => Err(EvalError::NotAFunction(a)), + }, + Expression::Quote(e) => Ok(*e), + Expression::Symbol(s) => eval(env, env.get(&s).ok_or(EvalError::SymbolNotBound(s))?), + x => Ok(x), + } +} diff --git a/src/lisp/expression.rs b/src/lisp/expression.rs index caff7d1..bda9957 100644 --- a/src/lisp/expression.rs +++ b/src/lisp/expression.rs @@ -1,5 +1,6 @@ -use super::environment::{Environment, EnvironmentLayer}; -use std::collections::HashMap; +use super::environment::Environment; +use super::eval::CellIterator; +use super::eval::EvalError; #[derive(Clone, Debug, PartialEq, PartialOrd)] /// A sum type of all possible lisp expressions. @@ -29,54 +30,6 @@ pub enum Expression { Nil, } -#[derive(Debug)] -/// All possible evaluation errors -pub enum EvalError { - SymbolNotBound(String), - NotAFunction(Expression), - NotANumber(Expression), - ArgumentError(String), - TypeError(String), - NotASymbol(Expression), -} - -/// 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. -pub struct CellIterator { - expr: Option, -} - -impl CellIterator { - pub fn new(expr: Expression) -> CellIterator { - CellIterator { expr: Some(expr) } - } -} - -impl Iterator for CellIterator { - type Item = Result; - fn next(&mut self) -> Option { - if let Some(expr) = self.expr.take() { - match expr { - Expression::Cell(head, tail) => { - self.expr = Some(*tail); - return Some(Ok(*head)); - } - Expression::Nil => { - return None; - } - _ => { - return Some(Err(EvalError::TypeError( - "Expected a cell or nil".to_string(), - ))); - } - } - } else { - None - } - } -} - impl From Result> for Expression { fn from(f: fn(&Environment, Expression) -> Result) -> Self { Expression::Function(f) @@ -138,219 +91,3 @@ impl TryInto<(Expression, Expression)> for Expression { } } } - -/// Dispatch an anonymous function call. Evaluates `body` in `env`, binding `args` to `argument_symbols` -fn dispatch_anonymous_function( - env: &Environment, - argument_symbols: Vec, - body: Expression, - args: Expression, -) -> Result { - let mut args: Vec = args.try_into()?; - - let mut overlay = EnvironmentLayer::new(); - - if args.len() != argument_symbols.len() { - return Err(EvalError::ArgumentError(format!( - "Exprected {} arguments, got {}", - argument_symbols.len(), - args.len() - ))); - } - - for (arg, symbol) in args.iter_mut().zip(argument_symbols.iter()) { - overlay.set(symbol.to_owned(), arg.to_owned()); - } - - eval(&env.overlay(overlay), body) -} - -/// Evaluate an expression inside an environment -fn eval(env: &Environment, expr: Expression) -> Result { - match expr { - Expression::Cell(lhs, rhs) => match eval(env, *lhs)? { - Expression::Function(f) => f(env, *rhs), - Expression::AnonymousFunction { - argument_symbols, - body, - } => dispatch_anonymous_function(env, argument_symbols, *body, *rhs), - a => Err(EvalError::NotAFunction(a)), - }, - Expression::Quote(e) => Ok(*e), - Expression::Symbol(s) => eval( - env, - env.get(&s).ok_or(EvalError::SymbolNotBound(s)).cloned()?, - ), - x => Ok(x), - } -} - -//==================Prelude evaluation environment============================== - -fn prelude_add(env: &Environment, expr: Expression) -> Result { - let [a, b] = expr.try_into()?; - - match eval(env, a)? { - Expression::Integer(a) => match eval(env, b)? { - Expression::Integer(b) => Ok(Expression::Integer(a + b)), - Expression::Float(b) => Ok(Expression::Float(a as f64 + b)), - x => Err(EvalError::NotANumber(x)), - }, - Expression::Float(a) => match eval(env, b)? { - Expression::Float(b) => Ok(Expression::Float(a + b)), - Expression::Integer(b) => Ok(Expression::Float(a + b as f64)), - x => Err(EvalError::NotANumber(x)), - }, - x => Err(EvalError::NotANumber(x)), - } -} - -fn prelude_sub(env: &Environment, expr: Expression) -> Result { - let [a, b] = expr.try_into()?; - - match eval(env, a)? { - Expression::Integer(a) => match eval(env, b)? { - Expression::Integer(b) => Ok(Expression::Integer(a - b)), - Expression::Float(b) => Ok(Expression::Float(a as f64 - b)), - x => Err(EvalError::NotANumber(x)), - }, - Expression::Float(a) => match eval(env, b)? { - Expression::Float(b) => Ok(Expression::Float(a - b)), - Expression::Integer(b) => Ok(Expression::Float(a - b as f64)), - x => Err(EvalError::NotANumber(x)), - }, - x => Err(EvalError::NotANumber(x)), - } -} - -fn prelude_mul(env: &Environment, expr: Expression) -> Result { - let [a, b] = expr.try_into()?; - - match eval(env, a)? { - Expression::Integer(a) => match eval(env, b)? { - Expression::Integer(b) => Ok(Expression::Integer(a * b)), - Expression::Float(b) => Ok(Expression::Float(a as f64 * b)), - x => Err(EvalError::NotANumber(x)), - }, - Expression::Float(a) => match eval(env, b)? { - Expression::Float(b) => Ok(Expression::Float(a * b)), - Expression::Integer(b) => Ok(Expression::Float(a * b as f64)), - x => Err(EvalError::NotANumber(x)), - }, - x => Err(EvalError::NotANumber(x)), - } -} - -fn prelude_div(env: &Environment, expr: Expression) -> Result { - let [a, b] = expr.try_into()?; - - match eval(env, a)? { - Expression::Integer(a) => match eval(env, b)? { - Expression::Integer(b) => Ok(Expression::Integer(a / b)), - Expression::Float(b) => Ok(Expression::Float(a as f64 / b)), - x => Err(EvalError::NotANumber(x)), - }, - Expression::Float(a) => match eval(env, b)? { - Expression::Float(b) => Ok(Expression::Float(a / b)), - Expression::Integer(b) => Ok(Expression::Float(a / b as f64)), - x => Err(EvalError::NotANumber(x)), - }, - x => Err(EvalError::NotANumber(x)), - } -} - -fn prelude_lambda(_env: &Environment, expr: Expression) -> Result { - let [args, body] = expr.try_into()?; - let mut arg_exprs: Vec = args.try_into()?; - let argument_symbols: Vec = arg_exprs - .iter_mut() - .map(|a| match a { - Expression::Symbol(s) => Ok(s.to_owned()), - x => Err(EvalError::NotASymbol(x.to_owned())), - }) - .collect::, EvalError>>()?; - Ok(Expression::AnonymousFunction { - argument_symbols, - body: Box::new(body), - }) -} - -fn prelude_let(env: &Environment, expr: Expression) -> Result { - let [bindings, body] = expr.try_into()?; - - let bindings = CellIterator::new(bindings) - .map(|e| { - let (s, e) = e?.try_into()?; - if let Expression::Symbol(s) = s { - Ok((s, eval(env, e)?)) - } else { - Err(EvalError::ArgumentError( - "Let bindings must be an alist with elements (symbol . expr)".to_string(), - )) - } - }) - .collect::, EvalError>>()?; - - eval(&env.overlay(bindings.into()), body) -} - -fn prelude_if(env: &Environment, expr: Expression) -> Result { - let [predicate, e_then, e_else] = expr.try_into()?; - - match eval(env, predicate)? { - Expression::Nil => eval(env, e_else), - _ => eval(env, e_then), - } -} - -fn prelude_eq(env: &Environment, expr: Expression) -> Result { - let [a, b] = expr.try_into()?; - let a = eval(env, a)?; - let b = eval(env, b)?; - - if a == b { - Ok(Expression::True) - } else { - Ok(Expression::Nil) - } -} - -fn prelude_lt(env: &Environment, expr: Expression) -> Result { - let [a, b] = expr.try_into()?; - let a = eval(env, a)?; - let b = eval(env, b)?; - - if a < b { - Ok(Expression::True) - } else { - Ok(Expression::Nil) - } -} - -fn prelude_gt(env: &Environment, expr: Expression) -> Result { - let [a, b] = expr.try_into()?; - let a = eval(env, a)?; - let b = eval(env, b)?; - - if a > b { - Ok(Expression::True) - } else { - Ok(Expression::Nil) - } -} - -pub fn eval_prelude(expr: Expression) -> Result { - let mut prelude = Environment::new(); - prelude.set("+".to_string(), Expression::Function(prelude_add)); - prelude.set("-".to_string(), Expression::Function(prelude_sub)); - prelude.set("*".to_string(), Expression::Function(prelude_mul)); - prelude.set("/".to_string(), Expression::Function(prelude_div)); - prelude.set("lambda".to_string(), Expression::Function(prelude_lambda)); - prelude.set("if".to_string(), Expression::Function(prelude_if)); - prelude.set("==".to_string(), Expression::Function(prelude_eq)); - prelude.set("<".to_string(), Expression::Function(prelude_lt)); - prelude.set(">".to_string(), Expression::Function(prelude_gt)); - prelude.set("let".to_string(), Expression::Function(prelude_let)); - - eval(&prelude, expr) -} diff --git a/src/lisp/mod.rs b/src/lisp/mod.rs index 6e01290..8a62709 100644 --- a/src/lisp/mod.rs +++ b/src/lisp/mod.rs @@ -1,8 +1,10 @@ pub mod environment; +pub mod eval; pub mod expression; +pub mod prelude; pub use environment::Environment; pub use environment::EnvironmentLayer; -pub use expression::eval_prelude; -pub use expression::EvalError; +pub use eval::eval; +pub use eval::EvalError; pub use expression::Expression; diff --git a/src/lisp/prelude.rs b/src/lisp/prelude.rs new file mode 100644 index 0000000..0e4a5fd --- /dev/null +++ b/src/lisp/prelude.rs @@ -0,0 +1,185 @@ +use super::environment::Environment; +use super::environment::EnvironmentLayer; +use super::eval::eval; +use super::eval::CellIterator; +use super::eval::EvalError; +use super::expression::Expression; +use std::collections::HashMap; + +pub fn prelude_add(env: &Environment, expr: Expression) -> Result { + let [a, b] = expr.try_into()?; + + match eval(env, a)? { + Expression::Integer(a) => match eval(env, b)? { + Expression::Integer(b) => Ok(Expression::Integer(a + b)), + Expression::Float(b) => Ok(Expression::Float(a as f64 + b)), + x => Err(EvalError::NotANumber(x)), + }, + Expression::Float(a) => match eval(env, b)? { + Expression::Float(b) => Ok(Expression::Float(a + b)), + Expression::Integer(b) => Ok(Expression::Float(a + b as f64)), + x => Err(EvalError::NotANumber(x)), + }, + x => Err(EvalError::NotANumber(x)), + } +} + +pub fn prelude_sub(env: &Environment, expr: Expression) -> Result { + let [a, b] = expr.try_into()?; + + match eval(env, a)? { + Expression::Integer(a) => match eval(env, b)? { + Expression::Integer(b) => Ok(Expression::Integer(a - b)), + Expression::Float(b) => Ok(Expression::Float(a as f64 - b)), + x => Err(EvalError::NotANumber(x)), + }, + Expression::Float(a) => match eval(env, b)? { + Expression::Float(b) => Ok(Expression::Float(a - b)), + Expression::Integer(b) => Ok(Expression::Float(a - b as f64)), + x => Err(EvalError::NotANumber(x)), + }, + x => Err(EvalError::NotANumber(x)), + } +} + +pub fn prelude_mul(env: &Environment, expr: Expression) -> Result { + let [a, b] = expr.try_into()?; + + match eval(env, a)? { + Expression::Integer(a) => match eval(env, b)? { + Expression::Integer(b) => Ok(Expression::Integer(a * b)), + Expression::Float(b) => Ok(Expression::Float(a as f64 * b)), + x => Err(EvalError::NotANumber(x)), + }, + Expression::Float(a) => match eval(env, b)? { + Expression::Float(b) => Ok(Expression::Float(a * b)), + Expression::Integer(b) => Ok(Expression::Float(a * b as f64)), + x => Err(EvalError::NotANumber(x)), + }, + x => Err(EvalError::NotANumber(x)), + } +} + +pub fn prelude_div(env: &Environment, expr: Expression) -> Result { + let [a, b] = expr.try_into()?; + + match eval(env, a)? { + Expression::Integer(a) => match eval(env, b)? { + Expression::Integer(b) => Ok(Expression::Integer(a / b)), + Expression::Float(b) => Ok(Expression::Float(a as f64 / b)), + x => Err(EvalError::NotANumber(x)), + }, + Expression::Float(a) => match eval(env, b)? { + Expression::Float(b) => Ok(Expression::Float(a / b)), + Expression::Integer(b) => Ok(Expression::Float(a / b as f64)), + x => Err(EvalError::NotANumber(x)), + }, + x => Err(EvalError::NotANumber(x)), + } +} + +pub fn prelude_lambda(_env: &Environment, expr: Expression) -> Result { + let [args, body] = expr.try_into()?; + let mut arg_exprs: Vec = args.try_into()?; + let argument_symbols: Vec = arg_exprs + .iter_mut() + .map(|a| match a { + Expression::Symbol(s) => Ok(s.to_owned()), + x => Err(EvalError::NotASymbol(x.to_owned())), + }) + .collect::, EvalError>>()?; + Ok(Expression::AnonymousFunction { + argument_symbols, + body: Box::new(body), + }) +} + +pub fn prelude_let(env: &Environment, expr: Expression) -> Result { + let [bindings, body] = expr.try_into()?; + + let bindings = CellIterator::new(bindings) + .map(|e| { + let (s, e) = e?.try_into()?; + if let Expression::Symbol(s) = s { + Ok((s, eval(env, e)?)) + } else { + Err(EvalError::ArgumentError( + "Let bindings must be an alist with elements (symbol . expr)".to_string(), + )) + } + }) + .collect::, EvalError>>()?; + + eval(&env.overlay(bindings.into()), body) +} + +pub fn prelude_if(env: &Environment, expr: Expression) -> Result { + let [predicate, e_then, e_else] = expr.try_into()?; + + match eval(env, predicate)? { + Expression::Nil => eval(env, e_else), + _ => eval(env, e_then), + } +} + +pub fn prelude_eq(env: &Environment, expr: Expression) -> Result { + let [a, b] = expr.try_into()?; + let a = eval(env, a)?; + let b = eval(env, b)?; + + if a == b { + Ok(Expression::True) + } else { + Ok(Expression::Nil) + } +} + +pub fn prelude_lt(env: &Environment, expr: Expression) -> Result { + let [a, b] = expr.try_into()?; + let a = eval(env, a)?; + let b = eval(env, b)?; + + if a < b { + Ok(Expression::True) + } else { + Ok(Expression::Nil) + } +} + +pub fn prelude_gt(env: &Environment, expr: Expression) -> Result { + let [a, b] = expr.try_into()?; + let a = eval(env, a)?; + let b = eval(env, b)?; + + if a > b { + Ok(Expression::True) + } else { + Ok(Expression::Nil) + } +} + +pub fn prelude_set(env: &Environment, expr: Expression) -> Result { + let [s, e] = expr.try_into()?; + + match s { + Expression::Symbol(s) => { + env.shared_set(s, e); + Ok(Expression::Nil) + } + x => Err(EvalError::NotASymbol(x)), + } +} + +pub fn mk_prelude(layer: &mut EnvironmentLayer) { + layer.set("+".to_string(), Expression::Function(prelude_add)); + layer.set("-".to_string(), Expression::Function(prelude_sub)); + layer.set("*".to_string(), Expression::Function(prelude_mul)); + layer.set("/".to_string(), Expression::Function(prelude_div)); + layer.set("lambda".to_string(), Expression::Function(prelude_lambda)); + layer.set("if".to_string(), Expression::Function(prelude_if)); + layer.set("==".to_string(), Expression::Function(prelude_eq)); + layer.set("<".to_string(), Expression::Function(prelude_lt)); + 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)); +} diff --git a/src/main.rs b/src/main.rs index 4cbe31f..1f62b89 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,21 +1,32 @@ mod lisp; mod parser; -use lisp::eval_prelude; use parser::ExpressionStream; -fn main() { - let program = "((lambda (x y) (+ (if (< x 10) (* x 11) x) y)) 2 20)"; +use crate::lisp::{eval, Environment}; - for r in ExpressionStream::from_char_stream(program.chars()) { +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 mut environment = Environment::default(); + + for r in ExpressionStream::from_char_stream( + program1 + .chars() + .chain(program2.chars()) + .chain(program3.chars()), + ) { match r { Err(err) => println!("ParserError: {:?}", err), Ok(expr) => println!( "{:?} \n vvvvvvvvvvv \n {:?}\n", expr.clone(), - eval_prelude(expr) + eval(&environment, expr) ), } } println!("Interpreter Done!"); + println!("Environment: {:?}", environment); }