mirror of
https://github.com/gorules/zen.git
synced 2026-10-04 08:02:28 +00:00
116 lines
2.7 KiB
Rust
116 lines
2.7 KiB
Rust
use crate::variable::Variable;
|
|
use smallvec::SmallVec;
|
|
use zen_types::symbol::Symbol;
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct Scope {
|
|
base: Variable,
|
|
locals: SmallVec<[(Symbol, Variable); 4]>,
|
|
}
|
|
|
|
impl Default for Scope {
|
|
fn default() -> Self {
|
|
Self::new(Variable::Null)
|
|
}
|
|
}
|
|
|
|
impl Scope {
|
|
pub fn new(base: Variable) -> Self {
|
|
Self {
|
|
base,
|
|
locals: SmallVec::new(),
|
|
}
|
|
}
|
|
|
|
pub fn base(&self) -> &Variable {
|
|
&self.base
|
|
}
|
|
|
|
pub fn base_mut(&mut self) -> &mut Variable {
|
|
&mut self.base
|
|
}
|
|
|
|
pub fn set_base(&mut self, base: Variable) {
|
|
self.base = base;
|
|
self.locals.clear();
|
|
}
|
|
|
|
pub fn locals(&self) -> &[(Symbol, Variable)] {
|
|
&self.locals
|
|
}
|
|
|
|
pub fn clear_locals(&mut self) {
|
|
self.locals.clear();
|
|
}
|
|
|
|
pub fn set_local(&mut self, name: Symbol, value: Variable) {
|
|
match self
|
|
.locals
|
|
.iter_mut()
|
|
.find(|(key, _)| key.as_str() == name.as_str())
|
|
{
|
|
Some(slot) => slot.1 = value,
|
|
None => self.locals.push((name, value)),
|
|
}
|
|
}
|
|
|
|
pub fn local(&self, name: &Symbol) -> Option<&Variable> {
|
|
self.locals
|
|
.iter()
|
|
.find(|(key, _)| key.as_str() == name.as_str())
|
|
.map(|(_, value)| value)
|
|
}
|
|
|
|
pub fn local_str(&self, name: &str) -> Option<&Variable> {
|
|
self.locals
|
|
.iter()
|
|
.find(|(key, _)| key.as_str() == name)
|
|
.map(|(_, value)| value)
|
|
}
|
|
|
|
pub fn get_str(&self, name: &str) -> Option<Variable> {
|
|
if let Some(value) = self.local_str(name) {
|
|
return Some(value.clone());
|
|
}
|
|
|
|
match &self.base {
|
|
Variable::Object(object) => object.borrow().get_str(name).cloned(),
|
|
_ => None,
|
|
}
|
|
}
|
|
|
|
pub fn get(&self, name: &Symbol) -> Option<Variable> {
|
|
if let Some(value) = self.local(name) {
|
|
return Some(value.clone());
|
|
}
|
|
|
|
match &self.base {
|
|
Variable::Object(object) => object.borrow().get(name).cloned(),
|
|
_ => None,
|
|
}
|
|
}
|
|
|
|
pub fn materialize(&self) -> Variable {
|
|
if self.locals.is_empty() {
|
|
return self.base.shallow_clone();
|
|
}
|
|
|
|
let Variable::Object(base) = &self.base else {
|
|
return self.base.shallow_clone();
|
|
};
|
|
|
|
let mut map = base.borrow().clone();
|
|
for (key, value) in &self.locals {
|
|
map.insert(key.clone(), value.clone());
|
|
}
|
|
|
|
Variable::from_object(map)
|
|
}
|
|
}
|
|
|
|
impl From<Variable> for Scope {
|
|
fn from(value: Variable) -> Self {
|
|
Scope::new(value)
|
|
}
|
|
}
|