From e4bf43dc6dff660d520068b5dc8e53e8aa5d9e4c Mon Sep 17 00:00:00 2001 From: numzero Date: Fri, 11 Apr 2025 14:51:02 +0300 Subject: [PATCH] Scope? --- src/lib.rs | 1 + src/scope.rs | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 src/scope.rs diff --git a/src/lib.rs b/src/lib.rs index cd40856..85ce649 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1 +1,2 @@ +pub mod scope; pub mod types; diff --git a/src/scope.rs b/src/scope.rs new file mode 100644 index 0000000..13cc202 --- /dev/null +++ b/src/scope.rs @@ -0,0 +1,63 @@ +use std::{ + cell::RefCell, + collections::{hash_map::Entry, HashMap}, + rc::Rc, +}; + +use crate::types::Value; + +#[derive(Debug, Clone, Default)] +pub struct Variable(Rc>); + +impl Variable { + pub fn get(&self) -> Value { + self.0.borrow().clone() + } + + pub fn set(&self, value: Value) { + *self.0.borrow_mut() = value; + } +} + +#[derive(Debug, Clone, Default)] +struct ScopeInner { + parent: Option, + locals: HashMap, +} + +#[derive(Debug, Clone, Default)] +pub struct Scope(Rc>); + +impl Scope { + pub fn new() -> Self { + Self::default() + } + + pub fn nested(&self) -> Self { + Self(Rc::new(RefCell::new(ScopeInner { + parent: Some(self.clone()), + ..Default::default() + }))) + } + + pub fn add(&self, name: String) { + self.0.borrow_mut().locals.insert(name, Variable::default()); + } + + pub fn get(&self, name: String) -> Variable { + let mut this = self.0.borrow_mut(); + let parent = this.parent.clone(); + match this.locals.entry(name) { + Entry::Occupied(var) => var.get().clone(), + Entry::Vacant(var) => { + if let Some(parent) = parent { + let name = var.into_key(); + drop(this); + parent.get(name) + } else { + var.insert(Variable::default()).clone() + } + } + } + } +}