diff options
Diffstat (limited to 'matrix-lang/src/value/gc.rs')
-rw-r--r-- | matrix-lang/src/value/gc.rs | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/matrix-lang/src/value/gc.rs b/matrix-lang/src/value/gc.rs new file mode 100644 index 0000000..5ef8b80 --- /dev/null +++ b/matrix-lang/src/value/gc.rs @@ -0,0 +1,186 @@ +use std::{ops::{Index, IndexMut, Deref, DerefMut, Add, Sub, Mul}, marker::PhantomData, ptr::NonNull, fmt::{Debug, Display}}; +use crate::prelude::*; + +pub struct Gc<T> { + ptr: NonNull<GcInner<T>>, + phantom: PhantomData<GcInner<T>> +} + +struct GcInner<T> { + rc: usize, + data: T +} + +impl<T> Gc<T> { + pub fn new(data: T) -> Self { + let boxed = Box::new(GcInner { + rc: 1, + data, + }); + Self { + ptr: NonNull::new(Box::into_raw(boxed)).unwrap(), + phantom: PhantomData + } + } +} + +impl <T: Clone> Gc<T> { + pub fn into_inner(self) -> T { + unsafe { + self.ptr.as_ref().data.clone() + } + } + + fn data(&self) -> T { + unsafe { + self.ptr.as_ref().data.clone() + } + } +} + +impl <T: ValueClone> ValueClone for Gc<T> { + fn deep_clone(&self) -> Self { + unsafe { + let data = self.ptr.as_ref().data.deep_clone(); + Self::new(data) + } + } + + fn shallow_clone(&self) -> Self { + unsafe { + let data = self.ptr.as_ref().data.shallow_clone(); + Self::new(data) + } + } +} + +impl<T> From<T> for Gc<T> { + fn from(value: T) -> Self { + Gc::new(value) + } +} + +impl<T: IndexMut<Idx>, Idx> IndexMut<Idx> for Gc<T> { + fn index_mut(&mut self, index: Idx) -> &mut Self::Output { + self.deref_mut().index_mut(index) + } +} + +impl<T: Index<Idx>, Idx> Index<Idx> for Gc<T> { + type Output = T::Output; + + fn index(&self, index: Idx) -> &Self::Output { + self.deref().index(index) + } +} + +impl<T> DerefMut for Gc<T> { + fn deref_mut(&mut self) -> &mut Self::Target { + unsafe { + &mut self.ptr.as_mut().data + } + } +} + +impl<T> Deref for Gc<T> { + type Target = T; + + fn deref(&self) -> &Self::Target { + unsafe { + &self.ptr.as_ref().data + } + } +} + +impl <T: PartialEq> PartialEq for Gc<T> { + fn eq(&self, other: &Self) -> bool { + self.deref().eq(other.deref()) + } +} + +impl <T: Iterator> Iterator for Gc<T> { + type Item = T::Item; + + fn next(&mut self) -> Option<Self::Item> { + self.deref_mut().next() + } +} + +impl<T: Eq> Eq for Gc<T> {} + +impl<T> Clone for Gc<T> { + fn clone(&self) -> Self { + unsafe { + let inner = self.ptr.as_ptr().as_mut().unwrap(); + inner.rc += 1; + + Self { + ptr: self.ptr, + phantom: PhantomData + } + } + } +} + +impl<T> Drop for Gc<T> { + fn drop(&mut self) { + unsafe { + let inner = self.ptr.as_mut(); + if inner.rc > 1 { + inner.rc -= 1; + } else { + let _ = Box::from_raw(self.ptr.as_ptr()); + } + } + } +} + +impl<T: Debug> Debug for Gc<T> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if f.alternate() { + write!(f, "{:#?}", self.deref()) + } else { + write!(f, "{:?}", self.deref()) + } + } +} + +impl<T: Display> Display for Gc<T> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if f.alternate() { + write!(f, "{:#}", self.deref()) + } else { + write!(f, "{}", self.deref()) + } + } +} + +impl <T: Add + Clone> Add for Gc<T> { + type Output = T::Output; + + fn add(self, rhs: Self) -> Self::Output { + let a = self.data(); + let b = rhs.data(); + a + b + } +} + +impl <T: Sub + Clone> Sub for Gc<T> { + type Output = T::Output; + + fn sub(self, rhs: Self) -> Self::Output { + let a = self.data(); + let b = rhs.data(); + a - b + } +} + +impl <T: Mul + Clone> Mul for Gc<T> { + type Output = T::Output; + + fn mul(self, rhs: Self) -> Self::Output { + let a = self.data(); + let b = rhs.data(); + a * b + } +} |