wars_rt/func/
unsync.rs

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