diff options
| author | Laurenz <laurmaedje@gmail.com> | 2021-01-15 16:53:02 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2021-01-15 16:53:02 +0100 |
| commit | d763f0f5a6a700352ee8926c15c8e58624f705c9 (patch) | |
| tree | d287edfdab9793a796404516c7313689e4e69964 /src/eval/scope.rs | |
| parent | 0f0416054f263b80ccec1a463ce4ab20913bdf71 (diff) | |
Split state and scopes, less ref-counting 🔀
Diffstat (limited to 'src/eval/scope.rs')
| -rw-r--r-- | src/eval/scope.rs | 41 |
1 files changed, 36 insertions, 5 deletions
diff --git a/src/eval/scope.rs b/src/eval/scope.rs index dd7cc1da..62ee7e40 100644 --- a/src/eval/scope.rs +++ b/src/eval/scope.rs @@ -1,27 +1,58 @@ use std::collections::HashMap; use std::fmt::{self, Debug, Formatter}; +use std::iter; use super::Value; -/// A map from identifiers to values. +/// A hierarchy of scopes. +#[derive(Debug, Clone, PartialEq)] +pub struct Scopes<'a> { + /// The active scope. + top: Scope, + /// The stack of lower scopes. + scopes: Vec<Scope>, + /// The base scope. + base: &'a Scope, +} + +impl<'a> Scopes<'a> { + /// Create a new hierarchy of scopes. + pub fn new(base: &'a Scope) -> Self { + Self { top: Scope::new(), scopes: vec![], base } + } + + /// Look up the value of a variable in the scopes. + pub fn get(&self, var: &str) -> Option<&Value> { + iter::once(&self.top) + .chain(&self.scopes) + .chain(iter::once(self.base)) + .find_map(|scope| scope.get(var)) + } + + /// Define a variable in the active scope. + pub fn define(&mut self, var: impl Into<String>, value: impl Into<Value>) { + self.top.set(var, value); + } +} + +/// A map from variable names to values. #[derive(Default, Clone, PartialEq)] pub struct Scope { values: HashMap<String, Value>, } impl Scope { - // Create a new empty scope with a fallback function that is invoked when no - // match is found. + // Create a new empty scope. pub fn new() -> Self { Self::default() } - /// Return the value of the given variable. + /// Look up the value of a variable. pub fn get(&self, var: &str) -> Option<&Value> { self.values.get(var) } - /// Store the value for the given variable. + /// Store the value for a variable. pub fn set(&mut self, var: impl Into<String>, value: impl Into<Value>) { self.values.insert(var.into(), value.into()); } |
