wars_rt/
func.rs

1use alloc::boxed::Box;
2use core::{
3    iter::{empty, once},
4    marker::PhantomData,
5    mem::transmute,
6};
7// use std::vec::Vec;
8use alloc::{sync::Arc, vec, vec::Vec};
9use anyhow::Context;
10use tramp::{tramp, BorrowRec, Thunk};
11pub mod unsync;
12pub mod value;
13pub fn ret<'a, T>(a: T) -> BorrowRec<'a, T> {
14    BorrowRec::Ret(a)
15}
16pub use crate::CtxSpec;
17use crate::{func::value::ForLt, Traverse};
18#[repr(transparent)]
19pub struct Value<C: CtxSpec>(pub value::Value<C, BorrowForLt<C>>);
20pub struct BorrowForLt<C: CtxSpec> {
21    ph: PhantomData<C>,
22}
23impl<'a, C: CtxSpec> ForLt<'a> for BorrowForLt<C> {
24    type ForLt = tramp::BorrowRec<'a, anyhow::Result<Vec<Value<C>>>>;
25}
26#[cfg(feature = "dumpster")]
27const _: () = {
28    use dumpster::Trace;
29    unsafe impl<C: CtxSpec<ExternRef: Trace>> Trace for Value<C> {
30        fn accept<V: dumpster::Visitor>(&self, visitor: &mut V) -> Result<(), ()> {
31            self.0.accept(visitor)
32        }
33    }
34};
35impl<C: CtxSpec> Traverse<C> for Value<C> {
36    fn traverse<'a>(&'a self) -> Box<dyn Iterator<Item = &'a <C as CtxSpec>::ExternRef> + 'a> {
37        self.0.traverse()
38    }
39    fn traverse_mut<'a>(
40        &'a mut self,
41    ) -> Box<dyn Iterator<Item = &'a mut <C as CtxSpec>::ExternRef> + 'a> {
42        self.0.traverse_mut()
43    }
44}
45pub fn call_ref<'a, A: CoeVec<C> + 'static, B: CoeVec<C> + 'static, C: CtxSpec + 'a>(
46    ctx: &'a mut C,
47    go: Df<A, B, C>,
48    a: A,
49) -> tramp::BorrowRec<'a, anyhow::Result<B>> {
50    // let go: Df<A, B, C> = cast(go);
51    go(ctx, a)
52}
53impl<C: CtxSpec> Clone for Value<C> {
54    fn clone(&self) -> Self {
55        Self(self.0.clone())
56    }
57}
58pub trait Coe<C: CtxSpec>: Sized {
59    fn coe(self) -> Value<C>;
60    fn uncoe(x: Value<C>) -> anyhow::Result<Self>;
61}
62pub fn cast<A: Coe<C> + 'static, B: Coe<C> + 'static, C: CtxSpec>(a: A) -> B {
63    let a = match castaway::cast!(a, B) {
64        Ok(b) => return b,
65        Err(a) => a,
66    };
67    B::uncoe(A::coe(a)).unwrap()
68}
69impl<C: CtxSpec> Coe<C> for Value<C> {
70    fn coe(self) -> Value<C> {
71        self
72    }
73    fn uncoe(x: Value<C>) -> anyhow::Result<Self> {
74        Ok(x)
75    }
76}
77impl<C: CtxSpec, D: Coe<C>> Coe<C> for Option<D> {
78    fn coe(self) -> Value<C> {
79        match self {
80            None => Value(value::Value::Null),
81            Some(d) => d.coe(),
82        }
83    }
84    fn uncoe(x: Value<C>) -> anyhow::Result<Self> {
85        if let value::Value::Null = &x.0 {
86            return Ok(None);
87        }
88        return Ok(Some(D::uncoe(x)?));
89    }
90}
91macro_rules! coe_impl_prim {
92    ($a:tt in $b:ident) => {
93        impl<C: CtxSpec> Coe<C> for $a {
94            fn coe(self) -> Value<C> {
95                Value(value::Value::$b(self))
96            }
97            fn uncoe(x: Value<C>) -> anyhow::Result<Self> {
98                match x.0 {
99                    value::Value::$b(a) => Ok(a),
100                    _ => anyhow::bail!("invalid type"),
101                }
102            }
103        }
104    };
105}
106coe_impl_prim!(u32 in I32);
107coe_impl_prim!(u64 in I64);
108coe_impl_prim!(f32 in F32);
109coe_impl_prim!(f64 in F64);
110#[cfg(feature = "dumpster")]
111pub trait CoeField<C: CtxSpec>: Sized {
112    fn coe(self) -> crate::gc::Field<Value<C>>;
113    fn uncoe(x: crate::gc::Field<Value<C>>) -> anyhow::Result<Self>;
114}
115#[cfg(feature = "dumpster")]
116pub trait CoeFieldVec<C: CtxSpec>: Sized {
117    const NUM: usize;
118    fn coe(self) -> Vec<crate::gc::Field<Value<C>>>;
119    fn uncoe(a: Vec<crate::gc::Field<Value<C>>>) -> anyhow::Result<Self>;
120}
121#[cfg(feature = "dumpster")]
122const _: () = {
123    use crate::gc::{Const, Field, Mut, Struct};
124    use std::sync::Mutex;
125    impl<C: CtxSpec, V: Coe<C>> CoeField<C> for Const<V> {
126        fn coe(self) -> crate::gc::Field<Value<C>> {
127            crate::gc::Field::Const(self.0.coe())
128        }
129        fn uncoe(x: crate::gc::Field<Value<C>>) -> anyhow::Result<Self> {
130            V::uncoe(match x {
131                crate::gc::Field::Const(a) => a,
132                crate::gc::Field::Mut(arc) => arc.lock().unwrap().clone(),
133            })
134            .map(Self)
135        }
136    }
137    impl<C: CtxSpec, V: Coe<C>> CoeField<C> for Mut<V> {
138        fn coe(self) -> crate::gc::Field<Value<C>> {
139            crate::gc::Field::Mut(Arc::new(Mutex::new(self.0.coe())))
140        }
141        fn uncoe(x: crate::gc::Field<Value<C>>) -> anyhow::Result<Self> {
142            V::uncoe(match x {
143                crate::gc::Field::Const(a) => a,
144                crate::gc::Field::Mut(arc) => arc.lock().unwrap().clone(),
145            })
146            .map(Self)
147        }
148    }
149    impl<C: CtxSpec> CoeFieldVec<C> for () {
150        fn coe(self) -> Vec<Field<Value<C>>> {
151            vec![]
152        }
153        fn uncoe(a: Vec<Field<Value<C>>>) -> anyhow::Result<Self> {
154            Ok(())
155        }
156        const NUM: usize = 0;
157    }
158    impl<C: CtxSpec, A: CoeField<C>, B: CoeFieldVec<C>> CoeFieldVec<C> for (A, B) {
159        fn coe(self) -> Vec<Field<Value<C>>> {
160            let mut a = self.1.coe();
161            a.push(self.0.coe());
162            return a;
163        }
164        fn uncoe(mut a: Vec<Field<Value<C>>>) -> anyhow::Result<Self> {
165            let Some(x) = a.pop() else {
166                anyhow::bail!("list too small")
167            };
168            let y = A::uncoe(x).context("invalid item (note coe lists are REVERSED)")?;
169            let z = B::uncoe(a)?;
170            Ok((y, z))
171        }
172        const NUM: usize = B::NUM + 1;
173    }
174    impl<C: CtxSpec, V: CoeFieldVec<C>> Coe<C> for Struct<V> {
175        fn coe(self) -> Value<C> {
176            Value(value::Value::Gc(crate::gc::GcCore::Fields(
177                match self.0.coe() {
178                    a => unsafe {
179                        use core::mem::transmute;
180                        transmute(a)
181                    },
182                },
183            )))
184        }
185        fn uncoe(x: Value<C>) -> anyhow::Result<Self> {
186            match x.0 {
187                value::Value::Gc(crate::gc::GcCore::Fields(f)) => V::uncoe(unsafe {
188                    use core::mem::transmute;
189                    transmute(f)
190                })
191                .map(Self),
192                _ => anyhow::bail!("nota gc"),
193            }
194        }
195    }
196};
197pub trait CoeVec<C: CtxSpec>: Sized {
198    const NUM: usize;
199    fn coe(self) -> Vec<Value<C>>;
200    fn uncoe(a: Vec<Value<C>>) -> anyhow::Result<Self>;
201}
202impl<C: CtxSpec> CoeVec<C> for () {
203    fn coe(self) -> Vec<Value<C>> {
204        vec![]
205    }
206    fn uncoe(a: Vec<Value<C>>) -> anyhow::Result<Self> {
207        Ok(())
208    }
209    const NUM: usize = 0;
210}
211impl<C: CtxSpec, A: Coe<C>, B: CoeVec<C>> CoeVec<C> for (A, B) {
212    fn coe(self) -> Vec<Value<C>> {
213        let mut a = self.1.coe();
214        a.push(self.0.coe());
215        return a;
216    }
217    fn uncoe(mut a: Vec<Value<C>>) -> anyhow::Result<Self> {
218        let Some(x) = a.pop() else {
219            anyhow::bail!("list too small")
220        };
221        let y = A::uncoe(x).context("invalid item (note coe lists are REVERSED)")?;
222        let z = B::uncoe(a)?;
223        Ok((y, z))
224    }
225    const NUM: usize = B::NUM + 1;
226}
227pub fn map_rec<'a, T: 'a, U>(
228    r: BorrowRec<'a, T>,
229    go: impl FnOnce(T) -> U + 'a,
230) -> BorrowRec<'a, U> {
231    match r {
232        BorrowRec::Ret(a) => BorrowRec::Ret(go(a)),
233        BorrowRec::Call(t) => BorrowRec::Call(Thunk::new(move || {
234            let t = t.compute();
235            map_rec(t, go)
236        })),
237    }
238}
239pub trait Dx<'a, A, B, C: 'a>:
240    Fn(&'a mut C, A) -> tramp::BorrowRec<'a, anyhow::Result<B>> + Send + Sync + 'static
241{
242}
243impl<
244        'a,
245        A,
246        B,
247        C: 'a,
248        T: Fn(&'a mut C, A) -> tramp::BorrowRec<'a, anyhow::Result<B>> + Send + Sync + 'static,
249    > Dx<'a, A, B, C> for T
250{
251}
252pub type Df<A, B, C> = Arc<dyn for<'a> Dx<'a, A, B, C>>;
253pub fn da<A, B, C, F: for<'a> Dx<'a, A, B, C>>(f: F) -> Df<A, B, C> {
254    Arc::new(f)
255}
256impl<C: CtxSpec + 'static, A: CoeVec<C> + 'static, B: CoeVec<C> + 'static> Coe<C> for Df<A, B, C> {
257    fn coe(self) -> Value<C> {
258        pub fn x<
259            C: CtxSpec,
260            T: (for<'a> Fn(
261                    &'a mut C,
262                    Vec<value::Value<C, BorrowForLt<C>>>,
263                ) -> tramp::BorrowRec<'a, anyhow::Result<Vec<Value<C>>>>)
264                + Send
265                + Sync
266                + 'static,
267        >(
268            a: T,
269        ) -> T {
270            return a;
271        }
272        Value(value::Value::FunRef(Arc::new(x(
273            move |ctx: &mut C, x: Vec<value::Value<C, BorrowForLt<C>>>| {
274                let x = match A::uncoe(unsafe { transmute::<_, Vec<Value<C>>>(x) }) {
275                    Ok(x) => x,
276                    Err(e) => return BorrowRec::Ret(Err(e)),
277                };
278                let x = self(ctx, x);
279                map_rec(x, |a| a.map(|b| b.coe()))
280            },
281        ))))
282    }
283    fn uncoe(x: Value<C>) -> anyhow::Result<Self> {
284        let value::Value::FunRef(x) = x.0 else {
285            anyhow::bail!("invalid value")
286        };
287        Ok(Arc::new(move |ctx, a| {
288            let v = a.coe();
289            let v = x(ctx, unsafe{transmute(v)});
290            map_rec(v, |a| a.and_then(B::uncoe))
291        }))
292    }
293}
294pub trait Call<A, B, C>:
295    for<'a> Fn(&'a mut C, A) -> tramp::BorrowRec<'a, anyhow::Result<B>> + 'static
296{
297    fn call(&self, c: &mut C, a: A) -> anyhow::Result<B>;
298}
299impl<A, B, C, T: for<'a> Fn(&'a mut C, A) -> tramp::BorrowRec<'a, anyhow::Result<B>> + 'static>
300    Call<A, B, C> for T
301{
302    fn call(&self, c: &mut C, a: A) -> anyhow::Result<B> {
303        tramp((self)(c, a))
304    }
305}