about summary refs log tree commit diff
path: root/users/tazjin/rlox/src/interpreter.rs
diff options
context:
space:
mode:
Diffstat (limited to 'users/tazjin/rlox/src/interpreter.rs')
-rw-r--r--users/tazjin/rlox/src/interpreter.rs38
1 files changed, 27 insertions, 11 deletions
diff --git a/users/tazjin/rlox/src/interpreter.rs b/users/tazjin/rlox/src/interpreter.rs
index 6c61288d5a..01ea217f82 100644
--- a/users/tazjin/rlox/src/interpreter.rs
+++ b/users/tazjin/rlox/src/interpreter.rs
@@ -106,23 +106,33 @@ impl Environment {
         Ok(())
     }
 
-    fn get(&self, name: &parser::Variable) -> Result<Value, Error> {
-        let ident = identifier_str(&name.name)?;
+    fn get(&self, ident: &str, line: usize, depth: usize) -> Result<Value, Error> {
+        println!("looking up {} at depth {}", ident, depth);
+        if depth > 0 {
+            match &self.enclosing {
+                None => {
+                    return Err(Error {
+                        line,
+                        kind: ErrorKind::InternalError(format!(
+                            "invalid depth {} for {}",
+                            depth, ident
+                        )),
+                    })
+                }
+                Some(parent) => {
+                    let env = parent.read().expect("fatal: environment lock poisoned");
+                    return env.get(ident, line, depth - 1);
+                }
+            }
+        }
 
         self.values
             .get(ident)
             .map(Clone::clone)
             .ok_or_else(|| Error {
-                line: name.name.line,
+                line,
                 kind: ErrorKind::UndefinedVariable(ident.into()),
             })
-            .or_else(|err| {
-                if let Some(parent) = &self.enclosing {
-                    parent.read().unwrap().get(name)
-                } else {
-                    Err(err)
-                }
-            })
     }
 
     fn assign(&mut self, name: &scanner::Token, value: Value) -> Result<(), Error> {
@@ -198,10 +208,16 @@ impl Interpreter {
     }
 
     fn get_var(&mut self, var: &parser::Variable) -> Result<Value, Error> {
+        let ident = identifier_str(&var.name)?;
+        let depth = var.depth.ok_or_else(|| Error {
+            line: var.name.line,
+            kind: ErrorKind::UndefinedVariable(ident.into()),
+        })?;
+
         self.env
             .read()
             .expect("environment lock is poisoned")
-            .get(var)
+            .get(ident, var.name.line, depth)
     }
 
     // Interpreter itself