From f3a941bb63275b0efbaa88c65e7ba762d8b05237 Mon Sep 17 00:00:00 2001 From: Akshay Date: Tue, 18 May 2021 11:09:46 +0530 Subject: fix `set!` routine and discover a drawback of borrowck! --- src/lisp/eval.rs | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) (limited to 'src/lisp/eval.rs') diff --git a/src/lisp/eval.rs b/src/lisp/eval.rs index 784cba0..c5e4ed0 100644 --- a/src/lisp/eval.rs +++ b/src/lisp/eval.rs @@ -153,14 +153,9 @@ where match args { [LispExpr::Ident(id), expr] => { let value = self.eval(&expr)?; - let local_env = self.app.lisp_env.last_mut(); - if let Some(env) = local_env { - env.insert(id.into(), value) - .ok_or_else(|| EvalError::UnboundVariable(id.into()).into()) - } else { - error!("Unable to set in global env!"); - Err(EvalError::BadForm.into()) - } + let loc = lookup_mut(&mut self.app.lisp_env, id)?; + *loc = value; + Ok(LispExpr::Unit) } _ => { error!("Invalid usage of `set!`"); @@ -334,16 +329,22 @@ pub fn create_lambda(cdr: &[LispExpr]) -> Result { } pub fn lookup(env_list: &[Environment], key: &str) -> Result { - if env_list.is_empty() { - Err(EvalError::UnboundVariable(key.into()).into()) - } else { - let local_env = env_list.last().unwrap(); - if let Some(val) = local_env.get(key) { - Ok(val.clone()) - } else { - lookup(&env_list[..env_list.len() - 1], key) - } - } + Ok(env_list + .iter() + .rev() + .find_map(|local_env| local_env.get(key).cloned()) + .ok_or(EvalError::UnboundVariable(key.into()))?) +} + +pub fn lookup_mut<'a, 'b>( + env_list: &'a mut [Environment], + key: &'b str, +) -> Result<&'a mut LispExpr, LispError> { + Ok(env_list + .iter_mut() + .rev() + .find_map(|local_env| local_env.get_mut(key)) + .ok_or(EvalError::UnboundVariable(key.into()))?) } pub fn completions<'a>(env_list: &'a [Environment], prefix: &str) -> Vec<&'a str> { -- cgit v1.2.3