feat: add shared environment/set

This commit is contained in:
Jonas Röger 2024-11-05 23:25:26 +01:00
parent 5de2230fec
commit b51e185c21
Signed by: jonas
GPG Key ID: 4000EB35E1AE0F07
6 changed files with 367 additions and 284 deletions

View File

@ -1,5 +1,10 @@
use super::expression::Expression; use super::{expression::Expression, prelude::mk_prelude};
use std::collections::HashMap; use std::{
borrow::BorrowMut,
cell::{RefCell, RefMut},
collections::HashMap,
rc::Rc,
};
#[derive(PartialEq, Clone, Debug)] #[derive(PartialEq, Clone, Debug)]
/// A Environment is a stack of `EnvironmentLayer`s. Each `EnvironmentLayer` is a mapping from /// A Environment is a stack of `EnvironmentLayer`s. Each `EnvironmentLayer` is a mapping from
@ -9,6 +14,8 @@ pub struct Environment<'a> {
layer: EnvironmentLayer, layer: EnvironmentLayer,
/// The outer _fallback_ mapping. /// The outer _fallback_ mapping.
outer: Option<&'a Environment<'a>>, outer: Option<&'a Environment<'a>>,
/// A shared layer taking precendence over the outer layer, but not the current layer.
shared: Rc<RefCell<EnvironmentLayer>>,
} }
#[derive(PartialEq, Clone, Debug)] #[derive(PartialEq, Clone, Debug)]
@ -31,8 +38,8 @@ impl EnvironmentLayer {
} }
/// Get a value in the `EnvironmentLayer`. /// Get a value in the `EnvironmentLayer`.
pub fn get(&self, key: &str) -> Option<&Expression> { pub fn get(&self, key: &str) -> Option<Expression> {
self.symbols.get(key) self.symbols.get(key).cloned()
} }
} }
@ -48,12 +55,17 @@ impl<'a> Environment<'a> {
Environment { Environment {
layer: EnvironmentLayer::new(), layer: EnvironmentLayer::new(),
outer: None, outer: None,
shared: Rc::new(RefCell::new(EnvironmentLayer::new())),
} }
} }
/// Construct an `Environment` from a `EnvironmentLayer` with no outer `Environment`. /// Construct an `Environment` from a `EnvironmentLayer` with no outer `Environment`.
pub fn from_layer(layer: EnvironmentLayer) -> Self { 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`. /// Construct a new `Environment` with `self` as the outer `Environment`.
@ -61,6 +73,7 @@ impl<'a> Environment<'a> {
Environment { Environment {
layer: EnvironmentLayer::new(), layer: EnvironmentLayer::new(),
outer: Some(self), outer: Some(self),
shared: self.shared.clone(),
} }
} }
@ -69,15 +82,43 @@ impl<'a> Environment<'a> {
Environment { Environment {
layer, layer,
outer: Some(&self), 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<Expression> {
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<Expression> {
if let Some(e) = self.layer.get(key) {
Some(e)
} else {
self.outer?.layer_get(key).clone()
} }
} }
/// Get a value from the `Environment`. /// Get a value from the `Environment`.
pub fn get(&self, key: &str) -> Option<&Expression> { pub fn get(&self, key: &str) -> Option<Expression> {
if let Some(e) = self.layer.get(key) { if let Some(e) = self.layer.get(key) {
Some(e) Some(e)
} else if let Some(e) = self.shared_get(key) {
Some(e)
} else { } 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] #[test]
fn test_environment() { fn test_environment() {
let mut env = Environment::new(); let mut env = Environment::new();
@ -94,9 +148,9 @@ fn test_environment() {
env.set("b".to_string(), Expression::Integer(2)); env.set("b".to_string(), Expression::Integer(2));
let mut inner = env.mk_inner(); let mut inner = env.mk_inner();
inner.set("a".to_string(), Expression::Integer(3)); inner.set("a".to_string(), Expression::Integer(3));
assert_eq!(inner.get("a"), Some(&Expression::Integer(3))); assert_eq!(inner.get("a"), Some(Expression::Integer(3)));
assert_eq!(inner.get("b"), Some(&Expression::Integer(2))); assert_eq!(inner.get("b"), Some(Expression::Integer(2)));
assert_eq!(env.get("a"), Some(&Expression::Integer(1))); assert_eq!(env.get("a"), Some(Expression::Integer(1)));
assert_eq!(env.get("b"), Some(&Expression::Integer(2))); assert_eq!(env.get("b"), Some(Expression::Integer(2)));
assert_eq!(env.get("c"), None); assert_eq!(env.get("c"), None);
} }

94
src/lisp/eval.rs Normal file
View File

@ -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<Expression>,
}
impl CellIterator {
pub fn new(expr: Expression) -> CellIterator {
CellIterator { expr: Some(expr) }
}
}
impl Iterator for CellIterator {
type Item = Result<Expression, EvalError>;
fn next(&mut self) -> Option<Self::Item> {
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<String>,
body: Expression,
args: Expression,
) -> Result<Expression, EvalError> {
let mut args: Vec<Expression> = 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<Expression, EvalError> {
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),
}
}

View File

@ -1,5 +1,6 @@
use super::environment::{Environment, EnvironmentLayer}; use super::environment::Environment;
use std::collections::HashMap; use super::eval::CellIterator;
use super::eval::EvalError;
#[derive(Clone, Debug, PartialEq, PartialOrd)] #[derive(Clone, Debug, PartialEq, PartialOrd)]
/// A sum type of all possible lisp expressions. /// A sum type of all possible lisp expressions.
@ -29,54 +30,6 @@ pub enum Expression {
Nil, 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<Expression>,
}
impl CellIterator {
pub fn new(expr: Expression) -> CellIterator {
CellIterator { expr: Some(expr) }
}
}
impl Iterator for CellIterator {
type Item = Result<Expression, EvalError>;
fn next(&mut self) -> Option<Self::Item> {
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<fn(&Environment, Expression) -> Result<Expression, EvalError>> for Expression { impl From<fn(&Environment, Expression) -> Result<Expression, EvalError>> for Expression {
fn from(f: fn(&Environment, Expression) -> Result<Expression, EvalError>) -> Self { fn from(f: fn(&Environment, Expression) -> Result<Expression, EvalError>) -> Self {
Expression::Function(f) 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<String>,
body: Expression,
args: Expression,
) -> Result<Expression, EvalError> {
let mut args: Vec<Expression> = 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<Expression, EvalError> {
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<Expression, EvalError> {
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<Expression, EvalError> {
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<Expression, EvalError> {
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<Expression, EvalError> {
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<Expression, EvalError> {
let [args, body] = expr.try_into()?;
let mut arg_exprs: Vec<Expression> = args.try_into()?;
let argument_symbols: Vec<String> = arg_exprs
.iter_mut()
.map(|a| match a {
Expression::Symbol(s) => Ok(s.to_owned()),
x => Err(EvalError::NotASymbol(x.to_owned())),
})
.collect::<Result<Vec<String>, EvalError>>()?;
Ok(Expression::AnonymousFunction {
argument_symbols,
body: Box::new(body),
})
}
fn prelude_let(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
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::<Result<HashMap<String, Expression>, EvalError>>()?;
eval(&env.overlay(bindings.into()), body)
}
fn prelude_if(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
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<Expression, EvalError> {
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<Expression, EvalError> {
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<Expression, EvalError> {
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<Expression, EvalError> {
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)
}

View File

@ -1,8 +1,10 @@
pub mod environment; pub mod environment;
pub mod eval;
pub mod expression; pub mod expression;
pub mod prelude;
pub use environment::Environment; pub use environment::Environment;
pub use environment::EnvironmentLayer; pub use environment::EnvironmentLayer;
pub use expression::eval_prelude; pub use eval::eval;
pub use expression::EvalError; pub use eval::EvalError;
pub use expression::Expression; pub use expression::Expression;

185
src/lisp/prelude.rs Normal file
View File

@ -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<Expression, EvalError> {
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<Expression, EvalError> {
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<Expression, EvalError> {
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<Expression, EvalError> {
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<Expression, EvalError> {
let [args, body] = expr.try_into()?;
let mut arg_exprs: Vec<Expression> = args.try_into()?;
let argument_symbols: Vec<String> = arg_exprs
.iter_mut()
.map(|a| match a {
Expression::Symbol(s) => Ok(s.to_owned()),
x => Err(EvalError::NotASymbol(x.to_owned())),
})
.collect::<Result<Vec<String>, EvalError>>()?;
Ok(Expression::AnonymousFunction {
argument_symbols,
body: Box::new(body),
})
}
pub fn prelude_let(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
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::<Result<HashMap<String, Expression>, EvalError>>()?;
eval(&env.overlay(bindings.into()), body)
}
pub fn prelude_if(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
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<Expression, EvalError> {
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<Expression, EvalError> {
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<Expression, EvalError> {
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<Expression, EvalError> {
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));
}

View File

@ -1,21 +1,32 @@
mod lisp; mod lisp;
mod parser; mod parser;
use lisp::eval_prelude;
use parser::ExpressionStream; use parser::ExpressionStream;
fn main() { use crate::lisp::{eval, Environment};
let program = "((lambda (x y) (+ (if (< x 10) (* x 11) x) y)) 2 20)";
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 { match r {
Err(err) => println!("ParserError: {:?}", err), Err(err) => println!("ParserError: {:?}", err),
Ok(expr) => println!( Ok(expr) => println!(
"{:?} \n vvvvvvvvvvv \n {:?}\n", "{:?} \n vvvvvvvvvvv \n {:?}\n",
expr.clone(), expr.clone(),
eval_prelude(expr) eval(&environment, expr)
), ),
} }
} }
println!("Interpreter Done!"); println!("Interpreter Done!");
println!("Environment: {:?}", environment);
} }