diff --git a/src/interpreter/environment.rs b/src/interpreter/environment.rs index 7ec42d8..7c1c473 100644 --- a/src/interpreter/environment.rs +++ b/src/interpreter/environment.rs @@ -81,6 +81,25 @@ 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 { + if distance == 0 { + &self + } else { + self.enclosing.unwrap().borrow().ancestor(distance - 1) + } + } + /// Assign a value to an existing variable. pub fn assign(&mut self, name: &Token, value: Value) -> SloxResult<()> { if self.values.contains_key(&name.lexeme as &str) { diff --git a/src/interpreter/interpretable.rs b/src/interpreter/interpretable.rs index 4d916a1..c28ceed 100644 --- a/src/interpreter/interpretable.rs +++ b/src/interpreter/interpretable.rs @@ -48,6 +48,13 @@ impl<'a> InterpreterState<'a> { variables: parent.variables, } } + + 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), + } + } } /// Interpreter flow control, which may be either a value, a loop break or a