use std::cell::RefCell; use std::sync::Arc; use derive_more::Constructor; use rpds::HashTrieMapSync; use crate::error::Result; use crate::vm::VM; use super::super::common::Symbol; use super::super::public as p; use super::{ToPublic, Value}; #[derive(Debug, Constructor, Clone, PartialEq)] pub struct AttrSet { data: HashTrieMapSync, } impl AttrSet { pub fn empty() -> Self { AttrSet { data: HashTrieMapSync::new_sync(), } } pub fn push_attr_force(&mut self, sym: Symbol, val: Value) { self.data.insert_mut(sym, val); } pub fn push_attr(&mut self, sym: Symbol, val: Value) { if self.data.get_mut(&sym).is_some() { todo!() } self.data.insert_mut(sym, val); } pub fn select(&self, sym: Symbol) -> Option { self.data.get(&sym).cloned() } pub fn has_attr(&self, sym: Symbol) -> bool { self.data.get(&sym).is_some() } pub fn update(mut self, other: AttrSet) -> AttrSet { for (k, v) in other.data.iter() { self.push_attr_force(k.clone(), v.clone()) } self } pub fn update_rec(mut self, other: RecAttrSet) -> AttrSet { for (k, v) in other.data.borrow().iter() { self.push_attr_force(k.clone(), v.clone()) } self } pub fn into_inner(self) -> HashTrieMapSync { self.data } pub fn as_inner(&self) -> &HashTrieMapSync { &self.data } pub fn force_deep(&mut self, vm: &VM) -> Result<()> { let mut map: Vec<_> = self .data .into_iter() .map(|(k, v)| (k.clone(), v.clone())) .collect(); map.iter_mut() .map(|(_, v)| v.force_deep(vm).map(|_| ())) .find(|v| v.is_err()) .map_or(Ok(()), |err| err)?; self.data = map.into_iter().collect(); Ok(()) } } impl ToPublic for AttrSet { fn to_public(self, vm: &VM) -> p::Value { p::Value::AttrSet(p::AttrSet::new( self.data .iter() .map(|(sym, value)| (sym.clone(), value.clone().to_public(vm))) .collect(), )) } } #[derive(Debug, Constructor, Clone, PartialEq)] pub struct RecAttrSet { data: Arc>>, } impl RecAttrSet { pub fn empty() -> RecAttrSet { RecAttrSet { data: Arc::default(), } } pub fn push_attr_force(&mut self, sym: Symbol, val: Value) { self.data.borrow_mut().insert_mut(sym, val); } pub fn push_attr(&mut self, sym: Symbol, val: Value) { if self.data.borrow().get(&sym).is_some() { todo!() } self.data.borrow_mut().insert_mut(sym, val); } pub fn select(&self, sym: Symbol) -> Option { self.data.borrow().get(&sym).cloned() } pub fn has_attr(&self, sym: Symbol) -> bool { self.data.borrow().get(&sym).is_some() } pub fn update(mut self, other: RecAttrSet) -> RecAttrSet { for (k, v) in other.data.borrow().iter() { self.push_attr_force(k.clone(), v.clone()) } self } pub fn update_normal(self, other: AttrSet) -> AttrSet { let map = self .data .borrow() .into_iter() .map(|(k, v)| (k.clone(), v.clone())) .collect(); let mut new = AttrSet::new(map); for (k, v) in other.data.iter() { new.push_attr_force(k.clone(), v.clone()) } new } pub fn into_inner(self) -> HashTrieMapSync { self.data.borrow().clone() } pub fn from_inner(data: Arc>>) -> Self { RecAttrSet { data } } pub fn force_deep(&mut self, vm: &VM) -> Result<()> { let mut map: Vec<_> = self .data .borrow() .into_iter() .map(|(k, v)| (k.clone(), v.clone())) .collect(); map.iter_mut() .map(|(_, v)| v.force_deep(vm).map(|_| ())) .find(|v| v.is_err()) .map_or(Ok(()), |err| err)?; *self.data.borrow_mut() = map.into_iter().collect(); Ok(()) } } impl ToPublic for RecAttrSet { fn to_public(self, vm: &VM) -> p::Value { p::Value::AttrSet(p::AttrSet::new( self.data .borrow() .iter() .map(|(sym, value)| (sym.clone(), value.clone().to_public(vm))) .collect(), )) } }