72 lines
2.4 KiB
Rust
72 lines
2.4 KiB
Rust
use std::fmt::Debug;
|
|
use std::future::Future;
|
|
use std::rc::Rc;
|
|
|
|
use futures::FutureExt;
|
|
use futures::future::LocalBoxFuture;
|
|
use orchid_base::{Receipt, ReqHandle, ReqReader, ReqReaderExt, Sym};
|
|
use task_local::task_local;
|
|
|
|
use crate::tree::GenMember;
|
|
use crate::{Cted, CtedObj, DynSystemCard, LexerObj, ParserObj, SystemCard, SystemCtor, api};
|
|
|
|
pub type CardForSystem<T> = <<T as System>::Ctor as SystemCtor>::Card;
|
|
pub type ReqForSystem<T> = <CardForSystem<T> as SystemCard>::Req;
|
|
|
|
/// System as defined by author
|
|
pub trait System: Debug + 'static {
|
|
type Ctor: SystemCtor<Instance = Self>;
|
|
fn prelude(&self) -> impl Future<Output = Vec<Sym>> { futures::future::ready(Vec::new()) }
|
|
fn env(&self) -> impl Future<Output = Vec<GenMember>> { futures::future::ready(Vec::new()) }
|
|
fn lexers(&self) -> Vec<LexerObj> { Vec::new() }
|
|
fn parsers(&self) -> Vec<ParserObj> { Vec::new() }
|
|
fn request(
|
|
&self,
|
|
hand: Box<dyn ReqHandle>,
|
|
req: ReqForSystem<Self>,
|
|
) -> impl Future<Output = Receipt>;
|
|
}
|
|
|
|
pub trait DynSystem: Debug + 'static {
|
|
fn dyn_prelude(&self) -> LocalBoxFuture<'_, Vec<Sym>>;
|
|
fn dyn_env(&self) -> LocalBoxFuture<'_, Vec<GenMember>>;
|
|
fn dyn_lexers(&self) -> Vec<LexerObj>;
|
|
fn dyn_parsers(&self) -> Vec<ParserObj>;
|
|
fn dyn_request<'a, 'b: 'a>(&'a self, hand: Box<dyn ReqReader>) -> LocalBoxFuture<'a, Receipt>;
|
|
fn card(&self) -> Box<dyn DynSystemCard>;
|
|
}
|
|
|
|
impl<T: System> DynSystem for T {
|
|
fn dyn_prelude(&self) -> LocalBoxFuture<'_, Vec<Sym>> { Box::pin(self.prelude()) }
|
|
fn dyn_env(&self) -> LocalBoxFuture<'_, Vec<GenMember>> { self.env().boxed_local() }
|
|
fn dyn_lexers(&self) -> Vec<LexerObj> { self.lexers() }
|
|
fn dyn_parsers(&self) -> Vec<ParserObj> { self.parsers() }
|
|
fn dyn_request<'a, 'b: 'a>(
|
|
&'a self,
|
|
mut hand: Box<dyn ReqReader>,
|
|
) -> LocalBoxFuture<'a, Receipt> {
|
|
Box::pin(async move {
|
|
let value = hand.read_req().await.unwrap();
|
|
self.request(hand.finish().await, value).await
|
|
})
|
|
}
|
|
fn card(&self) -> Box<dyn DynSystemCard> { Box::new(CardForSystem::<Self>::default()) }
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub(crate) struct SysCtx(pub api::SysId, pub CtedObj);
|
|
|
|
task_local! {
|
|
static SYS_CTX: SysCtx;
|
|
}
|
|
|
|
pub(crate) async fn with_sys<F: Future>(sys: SysCtx, fut: F) -> F::Output {
|
|
SYS_CTX.scope(sys, fut).await
|
|
}
|
|
|
|
pub fn sys_id() -> api::SysId { SYS_CTX.with(|cx| cx.0) }
|
|
pub fn dyn_cted() -> CtedObj { SYS_CTX.with(|cx| cx.1.clone()) }
|
|
pub fn cted<C: SystemCtor>() -> Cted<C> {
|
|
Rc::downcast::<Cted<C>>(dyn_cted().as_any()).unwrap().as_ref().clone()
|
|
}
|