summaryrefslogtreecommitdiff
path: root/matrix-lang/src/value/gc.rs
diff options
context:
space:
mode:
Diffstat (limited to 'matrix-lang/src/value/gc.rs')
-rw-r--r--matrix-lang/src/value/gc.rs186
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
+ }
+}