about summary refs log tree commit diff
path: root/src/interpret/scope.rs
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2021-10-21 23:46:01 +0200
committerMel <einebeere@gmail.com>2021-10-21 23:46:01 +0200
commitcff714c07e5e2c0f11c121504500a554d60c08cc (patch)
tree6c9e98696530b2661343942948b9f1a50a8665e7 /src/interpret/scope.rs
parenta4980b8dbf1394c2b302f1de7c72d2264426b86e (diff)
downloadrabbithole-cff714c07e5e2c0f11c121504500a554d60c08cc.tar.zst
rabbithole-cff714c07e5e2c0f11c121504500a554d60c08cc.zip
Implement program walking.
Diffstat (limited to 'src/interpret/scope.rs')
-rw-r--r--src/interpret/scope.rs45
1 files changed, 45 insertions, 0 deletions
diff --git a/src/interpret/scope.rs b/src/interpret/scope.rs
new file mode 100644
index 0000000..de32692
--- /dev/null
+++ b/src/interpret/scope.rs
@@ -0,0 +1,45 @@
+use super::value::Value;
+use crate::parse::ast::nodes::Identifier;
+use std::collections::HashMap;
+
+pub struct Scope {
+    scopes: Vec<HashMap<Identifier, Value>>,
+}
+
+impl Scope {
+    pub fn new() -> Self {
+        Scope { scopes: Vec::new() }
+    }
+
+    pub fn nest(&mut self) {
+        self.scopes.push(HashMap::new());
+    }
+
+    pub fn unnest(&mut self) {
+        self.scopes.pop();
+    }
+
+    pub fn set_var(&mut self, ident: &Identifier, value: Value) {
+        for scope in self.scopes.iter_mut() {
+            if scope.contains_key(ident) {
+                scope.insert(ident.clone(), value);
+                return;
+            }
+        }
+
+        let inner_scope = self
+            .scopes
+            .last_mut()
+            .expect("Tried accessing scope after last frame is gone.");
+        inner_scope.insert(ident.clone(), value);
+    }
+
+    pub fn get_var(&self, ident: &Identifier) -> Option<Value> {
+        for scope in self.scopes.iter().rev() {
+            if let Some(value) = scope.get(ident) {
+                return Some(value.clone());
+            }
+        }
+        None
+    }
+}