From 5d2747e26f51cc2344a6bd95f93457248fdfebd8 Mon Sep 17 00:00:00 2001 From: Freya Murphy Date: Thu, 29 Feb 2024 17:04:28 -0500 Subject: fin prob --- matrix-lang/src/value/gc.rs | 186 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 matrix-lang/src/value/gc.rs (limited to 'matrix-lang/src/value/gc.rs') 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 { + ptr: NonNull>, + phantom: PhantomData> +} + +struct GcInner { + rc: usize, + data: T +} + +impl Gc { + 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 Gc { + 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 ValueClone for Gc { + 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 From for Gc { + fn from(value: T) -> Self { + Gc::new(value) + } +} + +impl, Idx> IndexMut for Gc { + fn index_mut(&mut self, index: Idx) -> &mut Self::Output { + self.deref_mut().index_mut(index) + } +} + +impl, Idx> Index for Gc { + type Output = T::Output; + + fn index(&self, index: Idx) -> &Self::Output { + self.deref().index(index) + } +} + +impl DerefMut for Gc { + fn deref_mut(&mut self) -> &mut Self::Target { + unsafe { + &mut self.ptr.as_mut().data + } + } +} + +impl Deref for Gc { + type Target = T; + + fn deref(&self) -> &Self::Target { + unsafe { + &self.ptr.as_ref().data + } + } +} + +impl PartialEq for Gc { + fn eq(&self, other: &Self) -> bool { + self.deref().eq(other.deref()) + } +} + +impl Iterator for Gc { + type Item = T::Item; + + fn next(&mut self) -> Option { + self.deref_mut().next() + } +} + +impl Eq for Gc {} + +impl Clone for Gc { + fn clone(&self) -> Self { + unsafe { + let inner = self.ptr.as_ptr().as_mut().unwrap(); + inner.rc += 1; + + Self { + ptr: self.ptr, + phantom: PhantomData + } + } + } +} + +impl Drop for Gc { + 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 Debug for Gc { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if f.alternate() { + write!(f, "{:#?}", self.deref()) + } else { + write!(f, "{:?}", self.deref()) + } + } +} + +impl Display for Gc { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if f.alternate() { + write!(f, "{:#}", self.deref()) + } else { + write!(f, "{}", self.deref()) + } + } +} + +impl Add for Gc { + type Output = T::Output; + + fn add(self, rhs: Self) -> Self::Output { + let a = self.data(); + let b = rhs.data(); + a + b + } +} + +impl Sub for Gc { + type Output = T::Output; + + fn sub(self, rhs: Self) -> Self::Output { + let a = self.data(); + let b = rhs.data(); + a - b + } +} + +impl Mul for Gc { + type Output = T::Output; + + fn mul(self, rhs: Self) -> Self::Output { + let a = self.data(); + let b = rhs.data(); + a * b + } +} -- cgit v1.2.3-freya