base and extension fully compiles, host in good shape
This commit is contained in:
@@ -1,12 +1,13 @@
|
||||
use std::any::{Any, TypeId, type_name};
|
||||
use std::fmt;
|
||||
use std::future::Future;
|
||||
use std::io::{Read, Write};
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::Deref;
|
||||
use std::pin::Pin;
|
||||
use std::rc::Rc;
|
||||
|
||||
use ahash::HashMap;
|
||||
use async_std::io::{Read, Write};
|
||||
use async_std::stream;
|
||||
use dyn_clone::{DynClone, clone_box};
|
||||
use futures::future::LocalBoxFuture;
|
||||
@@ -34,7 +35,7 @@ pub trait AtomCard: 'static + Sized {
|
||||
pub trait AtomicVariant {}
|
||||
pub trait Atomic: 'static + Sized {
|
||||
type Variant: AtomicVariant;
|
||||
type Data: Clone + Coding + Sized;
|
||||
type Data: Clone + Coding + Sized + 'static;
|
||||
fn reg_reqs() -> MethodSetBuilder<Self>;
|
||||
}
|
||||
impl<A: Atomic> AtomCard for A {
|
||||
@@ -102,10 +103,10 @@ impl ForeignAtom<'static> {
|
||||
let rep = (self.ctx.reqnot.request(api::Fwd(
|
||||
self.atom.clone(),
|
||||
Sym::parse(M::NAME, &self.ctx.i).await.unwrap().tok().to_api(),
|
||||
enc_vec(&m),
|
||||
enc_vec(&m).await,
|
||||
)))
|
||||
.await?;
|
||||
Some(M::Response::decode(&mut &rep[..]))
|
||||
Some(M::Response::decode(Pin::new(&mut &rep[..])).await)
|
||||
}
|
||||
}
|
||||
impl fmt::Display for ForeignAtom<'_> {
|
||||
@@ -118,10 +119,13 @@ impl fmt::Debug for ForeignAtom<'_> {
|
||||
}
|
||||
impl AtomRepr for ForeignAtom<'_> {
|
||||
type Ctx = SysCtx;
|
||||
fn from_api(atom: &api::Atom, pos: Pos, ctx: &mut Self::Ctx) -> Self {
|
||||
async fn from_api(atom: &api::Atom, pos: Pos, ctx: &mut Self::Ctx) -> Self {
|
||||
Self { atom: atom.clone(), _life: PhantomData, ctx: ctx.clone(), expr: None, pos }
|
||||
}
|
||||
fn to_api(&self) -> orchid_api::Atom { self.atom.clone() }
|
||||
async fn to_api(&self) -> orchid_api::Atom { self.atom.clone() }
|
||||
async fn print(&self) -> String {
|
||||
self.ctx.reqnot.request(api::ExtAtomPrint(self.atom.clone())).await
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NotTypAtom {
|
||||
@@ -151,8 +155,8 @@ trait_set! {
|
||||
trait AtomReqCb<A> = for<'a> Fn(
|
||||
&'a A,
|
||||
SysCtx,
|
||||
&'a mut dyn Read,
|
||||
&'a mut dyn Write
|
||||
Pin<&'a mut dyn Read>,
|
||||
Pin<&'a mut dyn Write>,
|
||||
) -> LocalBoxFuture<'a, ()>
|
||||
}
|
||||
|
||||
@@ -167,8 +171,9 @@ impl<A: AtomCard> MethodSetBuilder<A> {
|
||||
assert!(!M::NAME.is_empty(), "AtomMethod::NAME cannoot be empty");
|
||||
self.handlers.push((
|
||||
M::NAME,
|
||||
Rc::new(move |a: &A, ctx: SysCtx, req: &mut dyn Read, rep: &mut dyn Write| {
|
||||
async { Supports::<M>::handle(a, ctx, M::decode(req)).await.encode(rep) }.boxed_local()
|
||||
Rc::new(move |a: &A, ctx: SysCtx, req: Pin<&mut dyn Read>, rep: Pin<&mut dyn Write>| {
|
||||
async { Supports::<M>::handle(a, ctx, M::decode(req).await).await.encode(rep).await }
|
||||
.boxed_local()
|
||||
}),
|
||||
));
|
||||
self
|
||||
@@ -197,8 +202,8 @@ impl<A: AtomCard> MethodSet<A> {
|
||||
atom: &'a A,
|
||||
ctx: SysCtx,
|
||||
key: Sym,
|
||||
req: &'a mut dyn Read,
|
||||
rep: &'a mut dyn Write,
|
||||
req: Pin<&'a mut dyn Read>,
|
||||
rep: Pin<&'a mut dyn Write>,
|
||||
) -> bool {
|
||||
match self.handlers.get(&key) {
|
||||
None => false,
|
||||
@@ -228,14 +233,14 @@ impl<A: AtomicFeatures> TypAtom<'static, A> {
|
||||
expr,
|
||||
typ: Box::new(A::info()),
|
||||
}),
|
||||
Ok(atm) => match downcast_atom::<A>(atm) {
|
||||
Ok(atm) => match downcast_atom::<A>(atm).await {
|
||||
Ok(tatom) => Ok(tatom),
|
||||
Err(fa) => Err(NotTypAtom {
|
||||
pos: fa.pos.clone(),
|
||||
ctx: fa.ctx.clone(),
|
||||
expr: fa.ex(),
|
||||
typ: Box::new(A::info()),
|
||||
}),
|
||||
Ok(tatom) => Ok(tatom),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -243,15 +248,16 @@ impl<A: AtomicFeatures> TypAtom<'static, A> {
|
||||
impl<A: AtomicFeatures> TypAtom<'_, A> {
|
||||
pub async fn request<M: AtomMethod>(&self, req: M) -> M::Response
|
||||
where A: Supports<M> {
|
||||
M::Response::decode(
|
||||
M::Response::decode(Pin::new(
|
||||
&mut &(self.data.ctx.reqnot.request(api::Fwd(
|
||||
self.data.atom.clone(),
|
||||
Sym::parse(M::NAME, &self.data.ctx.i).await.unwrap().tok().to_api(),
|
||||
enc_vec(&req),
|
||||
enc_vec(&req).await,
|
||||
)))
|
||||
.await
|
||||
.unwrap()[..],
|
||||
)
|
||||
))
|
||||
.await
|
||||
}
|
||||
}
|
||||
impl<A: AtomicFeatures> Deref for TypAtom<'_, A> {
|
||||
@@ -264,7 +270,7 @@ pub struct AtomCtx<'a>(pub &'a [u8], pub Option<api::AtomId>, pub SysCtx);
|
||||
pub trait AtomDynfo: 'static {
|
||||
fn tid(&self) -> TypeId;
|
||||
fn name(&self) -> &'static str;
|
||||
fn decode(&self, ctx: AtomCtx<'_>) -> Box<dyn Any>;
|
||||
fn decode<'a>(&'a self, ctx: AtomCtx<'a>) -> LocalBoxFuture<'a, Box<dyn Any>>;
|
||||
fn call<'a>(&'a self, ctx: AtomCtx<'a>, arg: api::ExprTicket) -> LocalBoxFuture<'a, GExpr>;
|
||||
fn call_ref<'a>(&'a self, ctx: AtomCtx<'a>, arg: api::ExprTicket) -> LocalBoxFuture<'a, GExpr>;
|
||||
fn print<'a>(&'a self, ctx: AtomCtx<'a>) -> LocalBoxFuture<'a, String>;
|
||||
@@ -272,14 +278,14 @@ pub trait AtomDynfo: 'static {
|
||||
&'a self,
|
||||
ctx: AtomCtx<'a>,
|
||||
key: Sym,
|
||||
req: &'b mut dyn Read,
|
||||
rep: &'c mut dyn Write,
|
||||
req: Pin<&'b mut dyn Read>,
|
||||
rep: Pin<&'c mut dyn Write>,
|
||||
) -> LocalBoxFuture<'a, bool>;
|
||||
fn command<'a>(&'a self, ctx: AtomCtx<'a>) -> LocalBoxFuture<'a, OrcRes<Option<GExpr>>>;
|
||||
fn serialize<'a, 'b: 'a>(
|
||||
&'a self,
|
||||
ctx: AtomCtx<'a>,
|
||||
write: &'b mut dyn Write,
|
||||
write: Pin<&'b mut dyn Write>,
|
||||
) -> LocalBoxFuture<'a, Option<Vec<api::ExprTicket>>>;
|
||||
fn deserialize<'a>(
|
||||
&'a self,
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
use std::any::{Any, TypeId, type_name};
|
||||
use std::borrow::Cow;
|
||||
use std::future::Future;
|
||||
use std::io::{Read, Write};
|
||||
use std::pin::Pin;
|
||||
use std::rc::Rc;
|
||||
|
||||
use async_once_cell::OnceCell;
|
||||
use async_std::io::{Read, Write};
|
||||
use futures::FutureExt;
|
||||
use futures::future::{LocalBoxFuture, ready};
|
||||
use itertools::Itertools;
|
||||
@@ -31,8 +32,8 @@ impl<A: OwnedAtom + Atomic<Variant = OwnedVariant>> AtomicFeaturesImpl<OwnedVari
|
||||
AtomFactory::new(move |ctx| async move {
|
||||
let rec = ctx.obj_store.add(Box::new(self));
|
||||
let (id, _) = get_info::<A>(ctx.cted.inst().card());
|
||||
let mut data = enc_vec(&id);
|
||||
rec.encode(&mut data).await;
|
||||
let mut data = enc_vec(&id).await;
|
||||
rec.encode(Pin::<&mut Vec<u8>>::new(&mut data)).await;
|
||||
api::Atom { drop: Some(api::AtomId(rec.id())), data, owner: ctx.id }
|
||||
})
|
||||
}
|
||||
@@ -55,8 +56,11 @@ pub struct OwnedAtomDynfo<T: OwnedAtom> {
|
||||
impl<T: OwnedAtom> AtomDynfo for OwnedAtomDynfo<T> {
|
||||
fn tid(&self) -> TypeId { TypeId::of::<T>() }
|
||||
fn name(&self) -> &'static str { type_name::<T>() }
|
||||
fn decode(&self, AtomCtx(data, ..): AtomCtx) -> Box<dyn Any> {
|
||||
Box::new(<T as AtomCard>::Data::decode(&mut &data[..]))
|
||||
fn decode<'a>(&'a self, AtomCtx(data, ..): AtomCtx<'a>) -> LocalBoxFuture<'a, Box<dyn Any>> {
|
||||
async {
|
||||
Box::new(<T as AtomCard>::Data::decode(Pin::new(&mut &data[..])).await) as Box<dyn Any>
|
||||
}
|
||||
.boxed_local()
|
||||
}
|
||||
fn call(&self, AtomCtx(_, id, ctx): AtomCtx, arg: api::ExprTicket) -> LocalBoxFuture<'_, GExpr> {
|
||||
with_atom(id.unwrap(), &ctx, |a| a.remove()).dyn_call(ctx.clone(), arg)
|
||||
@@ -82,8 +86,8 @@ impl<T: OwnedAtom> AtomDynfo for OwnedAtomDynfo<T> {
|
||||
&'a self,
|
||||
AtomCtx(_, id, ctx): AtomCtx,
|
||||
key: Sym,
|
||||
req: &'b mut dyn Read,
|
||||
rep: &'c mut dyn Write,
|
||||
req: Pin<&'b mut dyn Read>,
|
||||
rep: Pin<&'c mut dyn Write>,
|
||||
) -> LocalBoxFuture<'a, bool> {
|
||||
async move {
|
||||
with_atom(id.unwrap(), &ctx, |a| {
|
||||
@@ -110,11 +114,11 @@ impl<T: OwnedAtom> AtomDynfo for OwnedAtomDynfo<T> {
|
||||
fn serialize<'a, 'b: 'a>(
|
||||
&'a self,
|
||||
AtomCtx(_, id, ctx): AtomCtx<'a>,
|
||||
write: &'b mut dyn Write,
|
||||
mut write: Pin<&'b mut dyn Write>,
|
||||
) -> LocalBoxFuture<'a, Option<Vec<api::ExprTicket>>> {
|
||||
async move {
|
||||
let id = id.unwrap();
|
||||
id.encode(write);
|
||||
id.encode(write.as_mut()).await;
|
||||
with_atom(id, &ctx, |a| clone!(ctx; async move { a.dyn_serialize(ctx, write).await }))
|
||||
.await
|
||||
.map(|v| v.into_iter().map(|t| t.handle().tk).collect_vec())
|
||||
@@ -138,20 +142,22 @@ impl<T: OwnedAtom> AtomDynfo for OwnedAtomDynfo<T> {
|
||||
}
|
||||
|
||||
pub trait DeserializeCtx: Sized {
|
||||
fn read<T: Decode>(&mut self) -> T;
|
||||
fn read<T: Decode>(&mut self) -> impl Future<Output = T>;
|
||||
fn is_empty(&self) -> bool;
|
||||
fn assert_empty(self) { assert!(self.is_empty(), "Bytes found after decoding") }
|
||||
fn decode<T: Decode>(mut self) -> T {
|
||||
let t = self.read();
|
||||
self.assert_empty();
|
||||
t
|
||||
fn decode<T: Decode>(mut self) -> impl Future<Output = T> {
|
||||
async {
|
||||
let t = self.read().await;
|
||||
self.assert_empty();
|
||||
t
|
||||
}
|
||||
}
|
||||
fn sys(&self) -> SysCtx;
|
||||
}
|
||||
|
||||
struct DeserCtxImpl<'a>(&'a [u8], &'a SysCtx);
|
||||
impl DeserializeCtx for DeserCtxImpl<'_> {
|
||||
fn read<T: Decode>(&mut self) -> T { T::decode(&mut self.0) }
|
||||
async fn read<T: Decode>(&mut self) -> T { T::decode(Pin::new(&mut self.0)).await }
|
||||
fn is_empty(&self) -> bool { self.0.is_empty() }
|
||||
fn sys(&self) -> SysCtx { self.1.clone() }
|
||||
}
|
||||
@@ -228,7 +234,7 @@ pub trait OwnedAtom: Atomic<Variant = OwnedVariant> + Any + Clone + 'static {
|
||||
fn serialize(
|
||||
&self,
|
||||
ctx: SysCtx,
|
||||
write: &mut (impl Write + ?Sized),
|
||||
write: Pin<&mut (impl Write + ?Sized)>,
|
||||
) -> impl Future<Output = Self::Refs> {
|
||||
assert_serializable::<Self>();
|
||||
async { panic!("Either implement serialize or set Refs to Never for {}", type_name::<Self>()) }
|
||||
@@ -250,7 +256,7 @@ fn assert_serializable<T: OwnedAtom>() {
|
||||
pub trait DynOwnedAtom: 'static {
|
||||
fn atom_tid(&self) -> TypeId;
|
||||
fn as_any_ref(&self) -> &dyn Any;
|
||||
fn encode<'a>(&'a self, buffer: &'a mut dyn Write) -> LocalBoxFuture<'a, ()>;
|
||||
fn encode<'a>(&'a self, buffer: Pin<&'a mut dyn Write>) -> LocalBoxFuture<'a, ()>;
|
||||
fn dyn_call_ref(&self, ctx: SysCtx, arg: api::ExprTicket) -> LocalBoxFuture<'_, GExpr>;
|
||||
fn dyn_call(self: Box<Self>, ctx: SysCtx, arg: api::ExprTicket)
|
||||
-> LocalBoxFuture<'static, GExpr>;
|
||||
@@ -260,14 +266,14 @@ pub trait DynOwnedAtom: 'static {
|
||||
fn dyn_serialize<'a>(
|
||||
&'a self,
|
||||
ctx: SysCtx,
|
||||
sink: &'a mut dyn Write,
|
||||
sink: Pin<&'a mut dyn Write>,
|
||||
) -> LocalBoxFuture<'a, Option<Vec<Expr>>>;
|
||||
}
|
||||
impl<T: OwnedAtom> DynOwnedAtom for T {
|
||||
fn atom_tid(&self) -> TypeId { TypeId::of::<T>() }
|
||||
fn as_any_ref(&self) -> &dyn Any { self }
|
||||
fn encode<'a>(&'a self, buffer: &'a mut dyn Write) -> LocalBoxFuture<'a, ()> {
|
||||
async { self.val().await.as_ref().encode(buffer) }.boxed_local()
|
||||
fn encode<'a>(&'a self, buffer: Pin<&'a mut dyn Write>) -> LocalBoxFuture<'a, ()> {
|
||||
async { self.val().await.as_ref().encode(buffer).await }.boxed_local()
|
||||
}
|
||||
fn dyn_call_ref(&self, ctx: SysCtx, arg: api::ExprTicket) -> LocalBoxFuture<'_, GExpr> {
|
||||
self.call_ref(ExprHandle::from_args(ctx, arg)).boxed_local()
|
||||
@@ -289,7 +295,7 @@ impl<T: OwnedAtom> DynOwnedAtom for T {
|
||||
fn dyn_serialize<'a>(
|
||||
&'a self,
|
||||
ctx: SysCtx,
|
||||
sink: &'a mut dyn Write,
|
||||
sink: Pin<&'a mut dyn Write>,
|
||||
) -> LocalBoxFuture<'a, Option<Vec<Expr>>> {
|
||||
match TypeId::of::<Never>() == TypeId::of::<<Self as OwnedAtom>::Refs>() {
|
||||
true => ready(None).boxed_local(),
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
use std::any::{Any, TypeId, type_name};
|
||||
use std::future::Future;
|
||||
use std::io::Write;
|
||||
use std::pin::Pin;
|
||||
|
||||
use async_once_cell::OnceCell;
|
||||
use async_std::io::{Read, Write};
|
||||
use futures::FutureExt;
|
||||
use futures::future::LocalBoxFuture;
|
||||
use orchid_api_traits::{Coding, enc_vec};
|
||||
@@ -24,8 +25,8 @@ impl<A: ThinAtom + Atomic<Variant = ThinVariant>> AtomicFeaturesImpl<ThinVariant
|
||||
fn _factory(self) -> AtomFactory {
|
||||
AtomFactory::new(move |ctx| async move {
|
||||
let (id, _) = get_info::<A>(ctx.cted.inst().card());
|
||||
let mut buf = enc_vec(&id);
|
||||
self.encode(&mut buf);
|
||||
let mut buf = enc_vec(&id).await;
|
||||
self.encode(Pin::new(&mut buf)).await;
|
||||
api::Atom { drop: None, data: buf, owner: ctx.id }
|
||||
})
|
||||
}
|
||||
@@ -39,53 +40,58 @@ pub struct ThinAtomDynfo<T: ThinAtom> {
|
||||
}
|
||||
impl<T: ThinAtom> AtomDynfo for ThinAtomDynfo<T> {
|
||||
fn print<'a>(&self, AtomCtx(buf, _, ctx): AtomCtx<'a>) -> LocalBoxFuture<'a, String> {
|
||||
async move { T::decode(&mut &buf[..]).print(ctx).await }.boxed_local()
|
||||
async move { T::decode(Pin::new(&mut &buf[..])).await.print(ctx).await }.boxed_local()
|
||||
}
|
||||
fn tid(&self) -> TypeId { TypeId::of::<T>() }
|
||||
fn name(&self) -> &'static str { type_name::<T>() }
|
||||
fn decode(&self, AtomCtx(buf, ..): AtomCtx) -> Box<dyn Any> { Box::new(T::decode(&mut &buf[..])) }
|
||||
fn decode<'a>(&'a self, AtomCtx(buf, ..): AtomCtx<'a>) -> LocalBoxFuture<'a, Box<dyn Any>> {
|
||||
async { Box::new(T::decode(Pin::new(&mut &buf[..])).await) as Box<dyn Any> }.boxed_local()
|
||||
}
|
||||
fn call<'a>(
|
||||
&'a self,
|
||||
AtomCtx(buf, _, ctx): AtomCtx<'a>,
|
||||
arg: api::ExprTicket,
|
||||
) -> LocalBoxFuture<'a, GExpr> {
|
||||
async move { T::decode(&mut &buf[..]).call(ExprHandle::from_args(ctx, arg)).await }
|
||||
.boxed_local()
|
||||
Box::pin(async move {
|
||||
T::decode(Pin::new(&mut &buf[..])).await.call(ExprHandle::from_args(ctx, arg)).await
|
||||
})
|
||||
}
|
||||
fn call_ref<'a>(
|
||||
&'a self,
|
||||
AtomCtx(buf, _, ctx): AtomCtx<'a>,
|
||||
arg: api::ExprTicket,
|
||||
) -> LocalBoxFuture<'a, GExpr> {
|
||||
async move { T::decode(&mut &buf[..]).call(ExprHandle::from_args(ctx, arg)).await }
|
||||
.boxed_local()
|
||||
Box::pin(async move {
|
||||
T::decode(Pin::new(&mut &buf[..])).await.call(ExprHandle::from_args(ctx, arg)).await
|
||||
})
|
||||
}
|
||||
fn handle_req<'a, 'm1: 'a, 'm2: 'a>(
|
||||
&'a self,
|
||||
AtomCtx(buf, _, sys): AtomCtx<'a>,
|
||||
key: Sym,
|
||||
req: &'m1 mut dyn std::io::Read,
|
||||
rep: &'m2 mut dyn Write,
|
||||
req: Pin<&'m1 mut dyn Read>,
|
||||
rep: Pin<&'m2 mut dyn Write>,
|
||||
) -> LocalBoxFuture<'a, bool> {
|
||||
async move {
|
||||
Box::pin(async move {
|
||||
let ms = self.ms.get_or_init(self.msbuild.pack(sys.clone())).await;
|
||||
ms.dispatch(&T::decode(&mut &buf[..]), sys, key, req, rep).await
|
||||
}
|
||||
.boxed_local()
|
||||
ms.dispatch(&T::decode(Pin::new(&mut &buf[..])).await, sys, key, req, rep).await
|
||||
})
|
||||
}
|
||||
fn command<'a>(
|
||||
&'a self,
|
||||
AtomCtx(buf, _, ctx): AtomCtx<'a>,
|
||||
) -> LocalBoxFuture<'a, OrcRes<Option<GExpr>>> {
|
||||
async move { T::decode(&mut &buf[..]).command(ctx).await }.boxed_local()
|
||||
async move { T::decode(Pin::new(&mut &buf[..])).await.command(ctx).await }.boxed_local()
|
||||
}
|
||||
fn serialize<'a, 'b: 'a>(
|
||||
&'a self,
|
||||
ctx: AtomCtx<'a>,
|
||||
write: &'b mut dyn Write,
|
||||
write: Pin<&'b mut dyn Write>,
|
||||
) -> LocalBoxFuture<'a, Option<Vec<api::ExprTicket>>> {
|
||||
T::decode(&mut &ctx.0[..]).encode(write);
|
||||
async { Some(Vec::new()) }.boxed_local()
|
||||
Box::pin(async {
|
||||
T::decode(Pin::new(&mut &ctx.0[..])).await.encode(write).await;
|
||||
Some(Vec::new())
|
||||
})
|
||||
}
|
||||
fn deserialize<'a>(
|
||||
&'a self,
|
||||
@@ -94,11 +100,11 @@ impl<T: ThinAtom> AtomDynfo for ThinAtomDynfo<T> {
|
||||
refs: &'a [api::ExprTicket],
|
||||
) -> LocalBoxFuture<'a, api::Atom> {
|
||||
assert!(refs.is_empty(), "Refs found when deserializing thin atom");
|
||||
async { T::decode(&mut &data[..])._factory().build(ctx).await }.boxed_local()
|
||||
async { T::decode(Pin::new(&mut &data[..])).await._factory().build(ctx).await }.boxed_local()
|
||||
}
|
||||
fn drop<'a>(&'a self, AtomCtx(buf, _, ctx): AtomCtx<'a>) -> LocalBoxFuture<'a, ()> {
|
||||
async move {
|
||||
let string_self = T::decode(&mut &buf[..]).print(ctx.clone()).await;
|
||||
let string_self = T::decode(Pin::new(&mut &buf[..])).await.print(ctx.clone()).await;
|
||||
writeln!(ctx.logger, "Received drop signal for non-drop atom {string_self:?}");
|
||||
}
|
||||
.boxed_local()
|
||||
|
||||
@@ -35,7 +35,7 @@ impl<A: AtomicFeatures> TryFromExpr for TypAtom<'_, A> {
|
||||
async fn try_from_expr(expr: Expr) -> OrcRes<Self> {
|
||||
match expr.atom().await {
|
||||
Err(ex) => Err(err_not_atom(ex.data().await.pos.clone(), &ex.ctx().i).await.into()),
|
||||
Ok(f) => match downcast_atom(f) {
|
||||
Ok(f) => match downcast_atom(f).await {
|
||||
Ok(a) => Ok(a),
|
||||
Err(f) => Err(err_type(f.pos(), &f.ctx().i).await.into()),
|
||||
},
|
||||
|
||||
@@ -3,6 +3,7 @@ use std::future::Future;
|
||||
use std::io::Write;
|
||||
use std::mem;
|
||||
use std::num::NonZero;
|
||||
use std::pin::Pin;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
@@ -86,7 +87,7 @@ pub async fn with_atom_record<'a, F: Future<Output = SysCtx>, T>(
|
||||
let mut data = &atom.data[..];
|
||||
let ctx = get_sys_ctx(atom.owner, reqnot).await;
|
||||
let inst = ctx.cted.inst();
|
||||
let id = api::AtomId::decode(&mut data);
|
||||
let id = api::AtomId::decode(Pin::new(&mut data)).await;
|
||||
let atom_record = atom_by_idx(inst.card(), id).expect("Atom ID reserved");
|
||||
cb(atom_record, ctx, id, data).await
|
||||
}
|
||||
@@ -114,23 +115,30 @@ impl ExtPort for ExtensionOwner {
|
||||
fn send<'a>(&'a self, msg: &'a [u8]) -> LocalBoxFuture<'a, ()> {
|
||||
self.rn.receive(msg).boxed_local()
|
||||
}
|
||||
fn recv<'a, 's: 'a>(
|
||||
&'s self,
|
||||
cb: Box<dyn FnOnce(&[u8]) -> LocalBoxFuture<'a, ()> + 'a>,
|
||||
fn recv<'a>(
|
||||
&'a self,
|
||||
cb: Box<dyn FnOnce(&[u8]) -> LocalBoxFuture<'_, ()> + 'a>,
|
||||
) -> LocalBoxFuture<'a, ()> {
|
||||
async { cb(&self.out_recv.recv().await.unwrap()[..]).await }.boxed_local()
|
||||
async {
|
||||
let msg = self.out_recv.recv().await.unwrap();
|
||||
cb(&msg[..]).await
|
||||
}
|
||||
.boxed_local()
|
||||
}
|
||||
}
|
||||
|
||||
async fn extension_main_logic(data: ExtensionData, spawner: Rc<dyn LocalSpawn>) {
|
||||
let api::HostHeader { log_strategy } = api::HostHeader::decode(&mut std::io::stdin().lock());
|
||||
let api::HostHeader { log_strategy } =
|
||||
api::HostHeader::decode(Pin::new(&mut async_std::io::stdin())).await;
|
||||
let mut buf = Vec::new();
|
||||
let decls = (data.systems.iter().enumerate())
|
||||
.map(|(id, sys)| (u16::try_from(id).expect("more than u16max system ctors"), sys))
|
||||
.map(|(id, sys)| sys.decl(api::SysDeclId(NonZero::new(id + 1).unwrap())))
|
||||
.collect_vec();
|
||||
let systems = Rc::new(Mutex::new(HashMap::<api::SysId, SystemRecord>::new()));
|
||||
api::ExtensionHeader { name: data.name.to_string(), systems: decls.clone() }.encode(&mut buf);
|
||||
api::ExtensionHeader { name: data.name.to_string(), systems: decls.clone() }
|
||||
.encode(Pin::new(&mut buf))
|
||||
.await;
|
||||
std::io::stdout().write_all(&buf).unwrap();
|
||||
std::io::stdout().flush().unwrap();
|
||||
let exiting = Arc::new(AtomicBool::new(false));
|
||||
@@ -333,8 +341,8 @@ async fn extension_main_logic(data: ExtensionData, spawner: Rc<dyn LocalSpawn>)
|
||||
let actx = AtomCtx(buf, atom.drop, ctx.clone());
|
||||
match &atom_req {
|
||||
api::AtomReq::SerializeAtom(ser) => {
|
||||
let mut buf = enc_vec(&id);
|
||||
let refs_opt = nfo.serialize(actx, &mut buf).await;
|
||||
let mut buf = enc_vec(&id).await;
|
||||
let refs_opt = nfo.serialize(actx, Pin::<&mut Vec<_>>::new(&mut buf)).await;
|
||||
hand.handle(ser, &refs_opt.map(|refs| (buf, refs))).await
|
||||
},
|
||||
api::AtomReq::AtomPrint(print @ api::AtomPrint(_)) =>
|
||||
@@ -343,7 +351,14 @@ async fn extension_main_logic(data: ExtensionData, spawner: Rc<dyn LocalSpawn>)
|
||||
let api::Fwded(_, key, payload) = &fwded;
|
||||
let mut reply = Vec::new();
|
||||
let key = Sym::from_api(*key, &i).await;
|
||||
let some = nfo.handle_req(actx, key, &mut &payload[..], &mut reply).await;
|
||||
let some = nfo
|
||||
.handle_req(
|
||||
actx,
|
||||
key,
|
||||
Pin::<&mut &[u8]>::new(&mut &payload[..]),
|
||||
Pin::<&mut Vec<_>>::new(&mut reply),
|
||||
)
|
||||
.await;
|
||||
hand.handle(fwded, &some.then_some(reply)).await
|
||||
},
|
||||
api::AtomReq::CallRef(call @ api::CallRef(_, arg)) => {
|
||||
@@ -374,7 +389,7 @@ async fn extension_main_logic(data: ExtensionData, spawner: Rc<dyn LocalSpawn>)
|
||||
let api::DeserAtom(sys, buf, refs) = &deser;
|
||||
let mut read = &mut &buf[..];
|
||||
let ctx = mk_ctx(*sys, hand.reqnot()).await;
|
||||
let id = api::AtomId::decode(&mut read);
|
||||
let id = api::AtomId::decode(Pin::new(&mut read)).await;
|
||||
let inst = ctx.cted.inst();
|
||||
let nfo = atom_by_idx(inst.card(), id).expect("Deserializing atom with invalid ID");
|
||||
hand.handle(&deser, &nfo.deserialize(ctx.clone(), read, refs).await).await
|
||||
@@ -388,7 +403,7 @@ async fn extension_main_logic(data: ExtensionData, spawner: Rc<dyn LocalSpawn>)
|
||||
for (k, v) in params {
|
||||
ctx.args.insert(
|
||||
Tok::from_api(k, &i).await,
|
||||
mtreev_from_api(&v, &mut |_| panic!("No atom in macro prompt!"), &i).await,
|
||||
mtreev_from_api(&v, &i, &mut |_| panic!("No atom in macro prompt!")).await,
|
||||
);
|
||||
}
|
||||
let err_cascade = err_cascade(&i).await;
|
||||
|
||||
@@ -21,22 +21,16 @@ pub struct ExprHandle {
|
||||
impl ExprHandle {
|
||||
pub(crate) fn from_args(ctx: SysCtx, tk: api::ExprTicket) -> Self { Self { ctx, tk } }
|
||||
pub fn get_ctx(&self) -> SysCtx { self.ctx.clone() }
|
||||
pub async fn clone(&self) -> Self {
|
||||
self.ctx.reqnot.notify(api::Acquire(self.ctx.id, self.tk)).await;
|
||||
Self { ctx: self.ctx.clone(), tk: self.tk }
|
||||
}
|
||||
}
|
||||
impl fmt::Debug for ExprHandle {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "ExprHandle({})", self.tk.0)
|
||||
}
|
||||
}
|
||||
impl Clone for ExprHandle {
|
||||
fn clone(&self) -> Self {
|
||||
let SysCtx { reqnot, spawner, .. } = self.ctx.clone();
|
||||
let notif = api::Acquire(self.ctx.id, self.tk);
|
||||
if let Err(e) = spawner.spawn_local(async move { reqnot.notify(notif).await }) {
|
||||
panic!("Failed to schedule cloning notification, resource may not exist: {e}");
|
||||
}
|
||||
Self { ctx: self.ctx.clone(), tk: self.tk }
|
||||
}
|
||||
}
|
||||
impl Drop for ExprHandle {
|
||||
fn drop(&mut self) {
|
||||
let notif = api::Release(self.ctx.id, self.tk);
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use std::borrow::Cow;
|
||||
use std::collections::HashMap;
|
||||
use std::future::Future;
|
||||
use std::io;
|
||||
use std::pin::Pin;
|
||||
use std::rc::Rc;
|
||||
|
||||
use async_std::io::Write;
|
||||
use async_std::sync::Mutex;
|
||||
use futures::FutureExt;
|
||||
use futures::future::LocalBoxFuture;
|
||||
@@ -79,13 +80,13 @@ impl OwnedAtom for Fun {
|
||||
}
|
||||
}
|
||||
async fn call(self, arg: ExprHandle) -> GExpr { self.call_ref(arg).await }
|
||||
async fn serialize(&self, _: SysCtx, sink: &mut (impl io::Write + ?Sized)) -> Self::Refs {
|
||||
self.path.to_api().encode(sink);
|
||||
async fn serialize(&self, _: SysCtx, write: Pin<&mut (impl Write + ?Sized)>) -> Self::Refs {
|
||||
self.path.to_api().encode(write).await;
|
||||
self.args.clone()
|
||||
}
|
||||
async fn deserialize(ctx: impl DeserializeCtx, args: Self::Refs) -> Self {
|
||||
let sys = ctx.sys();
|
||||
let path = Sym::from_api(ctx.decode(), &sys.i).await;
|
||||
let path = Sym::from_api(ctx.decode().await, &sys.i).await;
|
||||
let (arity, fun) = FUNS.with(|f| f.clone()).lock().await.get(&path).unwrap().clone();
|
||||
Self { args, arity, path, fun }
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ impl<'a> RuleCtx<'a> {
|
||||
return Err(err_cascade(&self.sys.i).await.into());
|
||||
};
|
||||
static ATOM_MSG: &str = "Returned atom from Rule recursion";
|
||||
Ok(mtreev_from_api(&treev, &mut |_| panic!("{ATOM_MSG}"), &self.sys.i).await)
|
||||
Ok(mtreev_from_api(&treev, &self.sys.i, &mut |_| panic!("{ATOM_MSG}")).await)
|
||||
}
|
||||
pub fn getv(&mut self, key: &Tok<String>) -> Vec<MTree<'a, Never>> {
|
||||
self.args.remove(key).expect("Key not found")
|
||||
|
||||
@@ -2,10 +2,10 @@ use core::fmt;
|
||||
use std::any::TypeId;
|
||||
use std::future::Future;
|
||||
use std::num::NonZero;
|
||||
use std::pin::Pin;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
use futures::FutureExt;
|
||||
use futures::future::LocalBoxFuture;
|
||||
use futures::task::LocalSpawn;
|
||||
use hashbrown::HashMap;
|
||||
@@ -68,8 +68,11 @@ pub fn atom_by_idx(
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolv_atom(sys: &(impl DynSystemCard + ?Sized), atom: &api::Atom) -> Box<dyn AtomDynfo> {
|
||||
let tid = api::AtomId::decode(&mut &atom.data[..8]);
|
||||
pub async fn resolv_atom(
|
||||
sys: &(impl DynSystemCard + ?Sized),
|
||||
atom: &api::Atom,
|
||||
) -> Box<dyn AtomDynfo> {
|
||||
let tid = api::AtomId::decode(Pin::new(&mut &atom.data[..8])).await;
|
||||
atom_by_idx(sys, tid).expect("Value of nonexistent type found")
|
||||
}
|
||||
|
||||
@@ -102,21 +105,25 @@ impl<T: System> DynSystem for T {
|
||||
fn dyn_lexers(&self) -> Vec<LexerObj> { Self::lexers() }
|
||||
fn dyn_parsers(&self) -> Vec<ParserObj> { Self::parsers() }
|
||||
fn dyn_request<'a>(&self, hand: ExtReq<'a>, req: Vec<u8>) -> LocalBoxFuture<'a, Receipt<'a>> {
|
||||
Self::request(hand, <Self as SystemCard>::Req::decode(&mut &req[..])).boxed_local()
|
||||
Box::pin(async move {
|
||||
Self::request(hand, <Self as SystemCard>::Req::decode(Pin::new(&mut &req[..])).await).await
|
||||
})
|
||||
}
|
||||
fn card(&self) -> &dyn DynSystemCard { self }
|
||||
}
|
||||
|
||||
pub fn downcast_atom<A: AtomicFeatures>(foreign: ForeignAtom) -> Result<TypAtom<A>, ForeignAtom> {
|
||||
pub async fn downcast_atom<A>(foreign: ForeignAtom<'_>) -> Result<TypAtom<'_, A>, ForeignAtom<'_>>
|
||||
where A: AtomicFeatures {
|
||||
let mut data = &foreign.atom.data[..];
|
||||
let ctx = foreign.ctx.clone();
|
||||
let value = api::AtomId::decode(Pin::new(&mut data)).await;
|
||||
let info_ent = (ctx.cted.deps().find(|s| s.id() == foreign.atom.owner))
|
||||
.map(|sys| get_info::<A>(sys.get_card()))
|
||||
.filter(|(pos, _)| api::AtomId::decode(&mut data) == *pos);
|
||||
.filter(|(pos, _)| value == *pos);
|
||||
match info_ent {
|
||||
None => Err(foreign),
|
||||
Some((_, info)) => {
|
||||
let val = info.decode(AtomCtx(data, foreign.atom.drop, ctx));
|
||||
let val = info.decode(AtomCtx(data, foreign.atom.drop, ctx)).await;
|
||||
let value = *val.downcast::<A::Data>().expect("atom decode returned wrong type");
|
||||
Ok(TypAtom { value, data: foreign })
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user