summaryrefslogtreecommitdiff
path: root/src/eval/scope.rs
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2021-01-15 16:53:02 +0100
committerLaurenz <laurmaedje@gmail.com>2021-01-15 16:53:02 +0100
commitd763f0f5a6a700352ee8926c15c8e58624f705c9 (patch)
treed287edfdab9793a796404516c7313689e4e69964 /src/eval/scope.rs
parent0f0416054f263b80ccec1a463ce4ab20913bdf71 (diff)
Split state and scopes, less ref-counting 🔀
Diffstat (limited to 'src/eval/scope.rs')
-rw-r--r--src/eval/scope.rs41
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());
}