From 3117dfeac5bb2991980856221873d1cac72dacad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= Date: Sat, 7 Jan 2023 08:24:27 +0100 Subject: [PATCH] Interpreter - Lookups and assignment based on resolver results * Does not work. Using pointers was a bad idea. --- src/interpreter/environment.rs | 39 +++++++++++++++++++++----------- src/interpreter/interpretable.rs | 20 ++++++++++++---- 2 files changed, 41 insertions(+), 18 deletions(-) diff --git a/src/interpreter/environment.rs b/src/interpreter/environment.rs index 7c1c473..02ff2f0 100644 --- a/src/interpreter/environment.rs +++ b/src/interpreter/environment.rs @@ -82,21 +82,11 @@ impl Environment { } /// Access a variable at a specified distance in a parent environment. - pub fn get_at(&self, distance: usize, name: &Token) -> Value { - self.ancestor(distance) - .values - .get(&name.lexeme as &str) - .unwrap() - .unwrap() - .clone() - } - - /// Access the ancestor environment at a specified distance from the current one. - fn ancestor(&self, distance: usize) -> &Self { + pub fn get_at(&self, distance: usize, name: &Token) -> SloxResult { if distance == 0 { - &self + self.get(name) } else { - self.enclosing.unwrap().borrow().ancestor(distance - 1) + self.ancestor(distance).borrow().get(name) } } @@ -116,4 +106,27 @@ impl Environment { } } } + + /// Set a variable at a specified distance in a parent environment. + pub fn assign_at(&mut self, distance: usize, name: &Token, value: Value) -> SloxResult<()> { + if distance == 0 { + self.assign(name, value) + } else { + self.ancestor(distance).borrow_mut().assign(name, value) + } + } + + /// Read an ancestor from the chain of enclosing environments. + fn ancestor(&self, distance: usize) -> EnvironmentRef { + let mut ancestor = self.enclosing.clone().expect("ancestor() called at root"); + for _ in 1..distance { + let ap = ancestor + .borrow() + .enclosing + .clone() + .expect("ancestor() called with too high a distance"); + ancestor = ap; + } + ancestor + } } diff --git a/src/interpreter/interpretable.rs b/src/interpreter/interpretable.rs index c28ceed..f5c547f 100644 --- a/src/interpreter/interpretable.rs +++ b/src/interpreter/interpretable.rs @@ -49,10 +49,20 @@ impl<'a> InterpreterState<'a> { } } - fn lookup_var(&self, name: &Token, expr : &ast::ExprNode) -> SloxResult { + fn lookup_var(&self, name: &Token, expr: &ast::ExprNode) -> SloxResult { match self.variables.get(&(expr as *const ast::ExprNode)) { - Some(distance) => Ok(self.environment.borrow().get_at(*distance, name)), - None => self.environment.borrow().get(name), + Some(distance) => self.environment.borrow().get_at(*distance, name), + None => self.globals.borrow().get(name), + } + } + + fn assign_var(&self, name: &Token, expr: &ast::ExprNode, value: Value) -> SloxResult<()> { + match self.variables.get(&(expr as *const ast::ExprNode)) { + Some(distance) => self + .environment + .borrow_mut() + .assign_at(*distance, name, value), + None => self.globals.borrow_mut().assign(name, value), } } } @@ -303,7 +313,7 @@ impl Interpretable for ast::ExprNode { match self { ast::ExprNode::Assignment { name, value } => { let value = value.interpret(es)?.result(); - es.environment.borrow_mut().assign(name, value)?; + es.assign_var(name, &self, value)?; Ok(InterpreterFlowControl::default()) } ast::ExprNode::Logical { @@ -319,7 +329,7 @@ impl Interpretable for ast::ExprNode { ast::ExprNode::Unary { operator, right } => self.on_unary(es, operator, right), ast::ExprNode::Grouping { expression } => expression.interpret(es), ast::ExprNode::Litteral { value } => self.on_litteral(value), - ast::ExprNode::Variable { name } => Ok(es.environment.borrow().get(name)?.into()), + ast::ExprNode::Variable { name } => Ok(es.lookup_var(name, &self)?.into()), ast::ExprNode::Call { callee, right_paren,