1
// NOTE
2
//
3
// we use a wrapper type over Arc, instead of just using Arc, so that we can implement traits on it
4
// (e.g. Uniplate, Serialize).
5
//
6
// As we are just using Arc for copy on write, not shared ownership, it is safe to break shared
7
// ownership in Moo's Uniplate implementation, by calling Arc::make_mut and Arc::new on modified
8
// values. In general, this is not safe for all Rc/Arc types, e.g. those that use Cell / RefCell
9
// internally.
10
//
11
// ~niklasdewally 13/08/25
12

            
13
use polyquine::Quine;
14
use proc_macro2::TokenStream;
15
use serde::{Deserialize, Serialize};
16
use std::hash::{Hash, Hasher};
17
use std::ops::DerefMut;
18
use std::{collections::VecDeque, fmt::Display, ops::Deref, sync::Arc};
19
use uniplate::{
20
    Biplate, Tree, Uniplate,
21
    impl_helpers::{transmute_if_same_type, try_transmute_if_same_type},
22
    spez::try_biplate_to,
23
};
24

            
25
/// A clone-on-write, reference counted pointer to an AST type.
26
///
27
/// Cloning values of this type will not clone the underlying value until it is modified, e.g.,
28
/// with [`Moo::make_mut`].
29
///
30
/// Unlike `Rc` and `Arc`, trait implementations on this type do not need to preserve shared
31
/// ownership - that is, two pointers that used to point to the same value may not do so after
32
/// calling a trait method on them. In particular, calling Uniplate methods may cause a
33
/// clone-on-write to occur.
34
///
35
/// **Note:** like Box` and `Rc`, methods on `Moo` are all associated functions, which means you
36
/// have to call them as, e.g. `Moo::make_mut(&value)` instead of `value.make_mut()`. This is so
37
/// that there are no conflicts with the inner type `T`, which this type dereferences to.
38
#[derive(PartialEq, Eq, Clone, Debug)]
39
pub struct Moo<T> {
40
    inner: Arc<T>,
41
}
42

            
43
impl<T: Quine> Quine for Moo<T> {
44
702
    fn ctor_tokens(&self) -> TokenStream {
45
702
        let inner = self.inner.as_ref().ctor_tokens();
46
702
        quote::quote! { ::conjure_cp::ast::Moo::new(#inner) }
47
702
    }
48
}
49

            
50
impl<T> Moo<T> {
51
    /// Constructs a new `Moo<T>`.
52
702
    pub fn new(value: T) -> Moo<T> {
53
702
        Moo {
54
702
            inner: Arc::new(value),
55
702
        }
56
702
    }
57
}
58

            
59
impl<T: Clone> Moo<T> {
60
    /// Makes a mutable reference into the given `Moo`.
61
    ///
62
    /// If there are other `Moo` pointers to the same allocation, then `make_mut` will `clone` the
63
    /// inner value to a new allocation to ensure unique ownership. This is also referred to as
64
    /// clone-on-write.
65
    pub fn make_mut(this: &mut Moo<T>) -> &mut T {
66
        Arc::make_mut(&mut this.inner)
67
    }
68

            
69
    /// If we have the only reference to T then unwrap it. Otherwise, clone T and return the clone.
70
    ///
71
    /// Assuming moo_t is of type `Moo<T>`, this function is functionally equivalent to
72
    /// `(*moo_t).clone()`, but will avoid cloning the inner value where possible.
73
    pub fn unwrap_or_clone(this: Moo<T>) -> T {
74
        Arc::unwrap_or_clone(this.inner)
75
    }
76
}
77

            
78
impl<T> AsRef<T> for Moo<T> {
79
    fn as_ref(&self) -> &T {
80
        self.inner.as_ref()
81
    }
82
}
83

            
84
impl<T> Deref for Moo<T> {
85
    type Target = T;
86

            
87
    fn deref(&self) -> &Self::Target {
88
        self.inner.deref()
89
    }
90
}
91

            
92
impl<T: Clone> DerefMut for Moo<T> {
93
    fn deref_mut(&mut self) -> &mut Self::Target {
94
        Moo::make_mut(self)
95
    }
96
}
97

            
98
impl<T> Uniplate for Moo<T>
99
where
100
    T: Uniplate,
101
{
102
    fn uniplate(
103
        &self,
104
    ) -> (
105
        uniplate::Tree<Self>,
106
        Box<dyn Fn(uniplate::Tree<Self>) -> Self>,
107
    ) {
108
        let this = Moo::clone(self);
109

            
110
        // do not need to preserve shared ownership, so treat this identically to values of the
111
        // inner type.
112
        let (tree, ctx) = try_biplate_to!((**self).clone(), Moo<T>);
113
        (
114
            Tree::Many(VecDeque::from([tree.clone()])),
115
            Box::new(move |x| {
116
                let Tree::Many(trees) = x else { panic!() };
117
                let new_tree = trees.into_iter().next().unwrap();
118
                let mut this = Moo::clone(&this);
119

            
120
                // Only update the pointer with the new value if the value has changed. Without
121
                // this check, writing to the pointer might trigger a clone on write, even
122
                // though the value inside the pointer remained the same.
123
                if new_tree != tree {
124
                    let this = Moo::make_mut(&mut this);
125
                    *this = ctx(new_tree)
126
                }
127

            
128
                this
129
            }),
130
        )
131
    }
132
}
133

            
134
impl<To, U> Biplate<To> for Moo<U>
135
where
136
    To: Uniplate,
137
    U: Uniplate + Biplate<To>,
138
{
139
    fn biplate(&self) -> (Tree<To>, Box<dyn Fn(Tree<To>) -> Self>) {
140
        if let Some(self_as_to) = transmute_if_same_type::<Self, To>(self) {
141
            // To = Self -> return self
142
            let tree = Tree::One(self_as_to.clone());
143
            let ctx = Box::new(move |x| {
144
                let Tree::One(self_as_to) = x else { panic!() };
145

            
146
                let self_as_self = try_transmute_if_same_type::<To, Self>(&self_as_to);
147

            
148
                Moo::clone(self_as_self)
149
            });
150

            
151
            (tree, ctx)
152
        } else {
153
            // To != Self -> return children of type To
154

            
155
            let this = Moo::clone(self);
156

            
157
            // Do not need to preserve shared ownership, so treat this identically to values of the
158
            // inner type.
159
            let (tree, ctx) = try_biplate_to!((**self).clone(), To);
160
            (
161
                Tree::Many(VecDeque::from([tree.clone()])),
162
                Box::new(move |x| {
163
                    let Tree::Many(trees) = x else { panic!() };
164
                    let new_tree = trees.into_iter().next().unwrap();
165
                    let mut this = Moo::clone(&this);
166

            
167
                    // Only update the pointer with the new value if the value has changed. Without
168
                    // this check, writing to the pointer might trigger a clone on write, even
169
                    // though the value inside the pointer remained the same.
170
                    if new_tree != tree {
171
                        let this = Moo::make_mut(&mut this);
172
                        *this = ctx(new_tree)
173
                    }
174

            
175
                    this
176
                }),
177
            )
178
        }
179
    }
180
}
181

            
182
impl<'de, T: Deserialize<'de>> Deserialize<'de> for Moo<T> {
183
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
184
    where
185
        D: serde::Deserializer<'de>,
186
    {
187
        Ok(Moo::new(T::deserialize(deserializer)?))
188
    }
189
}
190

            
191
impl<T: Serialize> Serialize for Moo<T> {
192
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
193
    where
194
        S: serde::Serializer,
195
    {
196
        T::serialize(&**self, serializer)
197
    }
198
}
199

            
200
impl<T: Display> Display for Moo<T> {
201
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
202
        (**self).fmt(f)
203
    }
204
}
205

            
206
impl<T: Hash> Hash for Moo<T> {
207
    fn hash<H: Hasher>(&self, state: &mut H) {
208
        (**self).hash(state);
209
    }
210
}
211

            
212
impl<T> From<T> for Moo<T> {
213
    fn from(value: T) -> Self {
214
        Moo::new(value)
215
    }
216
}