aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkshay <[email protected]>2021-05-18 06:39:46 +0100
committerAkshay <[email protected]>2021-05-18 06:39:46 +0100
commitf3a941bb63275b0efbaa88c65e7ba762d8b05237 (patch)
tree1f577c2be937e2052e6d8f292ef4df92c052c928
parentbea80dbfe722c7bb13e19665ddbadea03b8b6293 (diff)
fix `set!` routine
and discover a drawback of borrowck!
-rw-r--r--src/lisp/eval.rs37
-rw-r--r--src/lisp/test.lisp14
2 files changed, 33 insertions, 18 deletions
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
153 match args { 153 match args {
154 [LispExpr::Ident(id), expr] => { 154 [LispExpr::Ident(id), expr] => {
155 let value = self.eval(&expr)?; 155 let value = self.eval(&expr)?;
156 let local_env = self.app.lisp_env.last_mut(); 156 let loc = lookup_mut(&mut self.app.lisp_env, id)?;
157 if let Some(env) = local_env { 157 *loc = value;
158 env.insert(id.into(), value) 158 Ok(LispExpr::Unit)
159 .ok_or_else(|| EvalError::UnboundVariable(id.into()).into())
160 } else {
161 error!("Unable to set in global env!");
162 Err(EvalError::BadForm.into())
163 }
164 } 159 }
165 _ => { 160 _ => {
166 error!("Invalid usage of `set!`"); 161 error!("Invalid usage of `set!`");
@@ -334,16 +329,22 @@ pub fn create_lambda(cdr: &[LispExpr]) -> Result<LispExpr, LispError> {
334} 329}
335 330
336pub fn lookup(env_list: &[Environment], key: &str) -> Result<LispExpr, LispError> { 331pub fn lookup(env_list: &[Environment], key: &str) -> Result<LispExpr, LispError> {
337 if env_list.is_empty() { 332 Ok(env_list
338 Err(EvalError::UnboundVariable(key.into()).into()) 333 .iter()
339 } else { 334 .rev()
340 let local_env = env_list.last().unwrap(); 335 .find_map(|local_env| local_env.get(key).cloned())
341 if let Some(val) = local_env.get(key) { 336 .ok_or(EvalError::UnboundVariable(key.into()))?)
342 Ok(val.clone()) 337}
343 } else { 338
344 lookup(&env_list[..env_list.len() - 1], key) 339pub fn lookup_mut<'a, 'b>(
345 } 340 env_list: &'a mut [Environment],
346 } 341 key: &'b str,
342) -> Result<&'a mut LispExpr, LispError> {
343 Ok(env_list
344 .iter_mut()
345 .rev()
346 .find_map(|local_env| local_env.get_mut(key))
347 .ok_or(EvalError::UnboundVariable(key.into()))?)
347} 348}
348 349
349pub fn completions<'a>(env_list: &'a [Environment], prefix: &str) -> Vec<&'a str> { 350pub fn completions<'a>(env_list: &'a [Environment], prefix: &str) -> Vec<&'a str> {
diff --git a/src/lisp/test.lisp b/src/lisp/test.lisp
index a167f28..5eb1aaa 100644
--- a/src/lisp/test.lisp
+++ b/src/lisp/test.lisp
@@ -17,3 +17,17 @@
17(assert-eq 17(assert-eq
18 ((lambda (x) x) 2) 18 ((lambda (x) x) 2)
19 2) 19 2)
20
21(define x 2)
22(define y 5)
23(set! x 3)
24(assert-eq x 3)
25
26(define (square-x x)
27 (let [(y x)]
28 (begin
29 (set! y (* x x))
30 y)))
31
32(assert-eq (square-x 2) 4)
33(assert-eq y 5)