about summary refs log tree commit diff
path: root/src/interpret/scope.rs
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2021-11-14 22:31:34 +0100
committerMel <einebeere@gmail.com>2021-11-14 22:31:34 +0100
commit2a3ab5c161ac98cb3c6326173e5ed78089a9ed68 (patch)
tree2a25e0017f6b90f4296e1d9f5d10980a345e1373 /src/interpret/scope.rs
parent89fcc9a395f2aa9744d507d79d29aa117b89fa7e (diff)
downloadrabbithole-2a3ab5c161ac98cb3c6326173e5ed78089a9ed68.tar.zst
rabbithole-2a3ab5c161ac98cb3c6326173e5ed78089a9ed68.zip
Function calling and the ensuing scope shenanigans
Diffstat (limited to 'src/interpret/scope.rs')
-rw-r--r--src/interpret/scope.rs44
1 files changed, 38 insertions, 6 deletions
diff --git a/src/interpret/scope.rs b/src/interpret/scope.rs
index 478b24d..0db34c2 100644
--- a/src/interpret/scope.rs
+++ b/src/interpret/scope.rs
@@ -3,17 +3,37 @@ use crate::parse::ast::nodes::Identifier;
 use std::{cell::RefCell, collections::HashMap, rc::Rc};
 use thiserror::Error;
 
-pub struct Scope {
-    scopes: Vec<HashMap<Identifier, AssignedValue>>,
-}
+type InnerScope = HashMap<Identifier, AssignedValue>;
+
+#[derive(Debug, Clone)]
+pub struct Scope(Rc<RefCell<InnerScope>>);
 
 impl Scope {
+    fn new() -> Self {
+        Scope(Rc::new(RefCell::new(HashMap::new())))
+    }
+
+    fn get(&self, ident: &str) -> Option<AssignedValue> {
+        self.0.borrow().get(ident).cloned()
+    }
+
+    fn insert(&self, ident: Identifier, value: AssignedValue) {
+        self.0.borrow_mut().insert(ident, value);
+    }
+}
+
+#[derive(Debug, Clone)]
+pub struct ScopeChain {
+    scopes: Vec<Scope>,
+}
+
+impl ScopeChain {
     pub fn new() -> Self {
-        Scope { scopes: Vec::new() }
+        ScopeChain { scopes: Vec::new() }
     }
 
     pub fn nest(&mut self) {
-        self.scopes.push(HashMap::new());
+        self.scopes.push(Scope::new());
     }
 
     pub fn unnest(&mut self) {
@@ -70,9 +90,21 @@ impl Scope {
         }
         Err(ScopeError::UnknownIdentifier(ident.to_string()))
     }
+
+    // In contrast to set_var sets the var in the most inner scope so that it's always found first.
+    // This is used when setting parameters.
+    pub fn set_var_shadowed(&mut self, ident: &str, value: Value) {
+        let inner_scope = self
+            .scopes
+            .last_mut()
+            .expect("Tried accessing scope after last frame is gone.");
+
+        // Can shadowed values be constant? No idea!
+        inner_scope.insert(ident.to_string(), AssignedValue::Mutable(value));
+    }
 }
 
-#[derive(Debug)]
+#[derive(Debug, Clone)]
 enum AssignedValue {
     Constant(Value),
     Mutable(Value),