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;
12pub 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 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}