Decided to eradicate Send/Sync dependence, broke everything as a result. Should resume from interner
This commit is contained in:
31
Cargo.lock
generated
31
Cargo.lock
generated
@@ -941,6 +941,7 @@ dependencies = [
|
|||||||
"ordered-float",
|
"ordered-float",
|
||||||
"rust-embed",
|
"rust-embed",
|
||||||
"rust_decimal",
|
"rust_decimal",
|
||||||
|
"some_executor 0.4.0",
|
||||||
"substack",
|
"substack",
|
||||||
"test_executors",
|
"test_executors",
|
||||||
"trait-set",
|
"trait-set",
|
||||||
@@ -951,6 +952,7 @@ name = "orchid-extension"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ahash 0.8.11",
|
"ahash 0.8.11",
|
||||||
|
"async-once-cell",
|
||||||
"async-std",
|
"async-std",
|
||||||
"derive_destructure",
|
"derive_destructure",
|
||||||
"dyn-clone",
|
"dyn-clone",
|
||||||
@@ -967,6 +969,7 @@ dependencies = [
|
|||||||
"orchid-base",
|
"orchid-base",
|
||||||
"ordered-float",
|
"ordered-float",
|
||||||
"paste",
|
"paste",
|
||||||
|
"some_executor 0.4.0",
|
||||||
"substack",
|
"substack",
|
||||||
"trait-set",
|
"trait-set",
|
||||||
]
|
]
|
||||||
@@ -1384,6 +1387,20 @@ dependencies = [
|
|||||||
"web-time",
|
"web-time",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "some_executor"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8df557f5c4423b8c7b5efa248bd911d3908c095f6a64a002df51230534fd7bdf"
|
||||||
|
dependencies = [
|
||||||
|
"atomic-waker",
|
||||||
|
"priority",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"wasm_thread",
|
||||||
|
"web-sys",
|
||||||
|
"web-time",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "stdio-perftest"
|
name = "stdio-perftest"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@@ -1448,7 +1465,7 @@ dependencies = [
|
|||||||
"blocking_semaphore",
|
"blocking_semaphore",
|
||||||
"logwise",
|
"logwise",
|
||||||
"priority",
|
"priority",
|
||||||
"some_executor",
|
"some_executor 0.3.0",
|
||||||
"test_executors_proc",
|
"test_executors_proc",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"web-time",
|
"web-time",
|
||||||
@@ -1663,6 +1680,18 @@ version = "0.2.99"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6"
|
checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm_thread"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b7516db7f32decdadb1c3b8deb1b7d78b9df7606c5cc2f6241737c2ab3a0258e"
|
||||||
|
dependencies = [
|
||||||
|
"futures",
|
||||||
|
"js-sys",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"web-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "web-sys"
|
name = "web-sys"
|
||||||
version = "0.3.76"
|
version = "0.3.76"
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ orchid-api-traits = { version = "0.1.0", path = "../orchid-api-traits" }
|
|||||||
ordered-float = "4.6.0"
|
ordered-float = "4.6.0"
|
||||||
rust-embed = "8.5.0"
|
rust-embed = "8.5.0"
|
||||||
rust_decimal = "1.36.0"
|
rust_decimal = "1.36.0"
|
||||||
|
some_executor = "0.4.0"
|
||||||
substack = "1.1.1"
|
substack = "1.1.1"
|
||||||
test_executors = "0.3.2"
|
test_executors = "0.3.2"
|
||||||
trait-set = "0.3.0"
|
trait-set = "0.3.0"
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use std::hash::BuildHasher as _;
|
use std::hash::BuildHasher as _;
|
||||||
|
use std::marker::PhantomData;
|
||||||
use std::num::NonZeroU64;
|
use std::num::NonZeroU64;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
|
use std::rc::Rc;
|
||||||
use std::sync::{Arc, Mutex, MutexGuard, atomic};
|
use std::sync::{Arc, Mutex, MutexGuard, atomic};
|
||||||
use std::{fmt, hash, mem};
|
use std::{fmt, hash, mem};
|
||||||
|
|
||||||
@@ -21,17 +23,17 @@ struct ForceSized<T>(T);
|
|||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Tok<T: Interned> {
|
pub struct Tok<T: Interned> {
|
||||||
data: Arc<T>,
|
data: Rc<T>,
|
||||||
marker: ForceSized<T::Marker>,
|
marker: ForceSized<T::Marker>,
|
||||||
}
|
}
|
||||||
impl<T: Interned> Tok<T> {
|
impl<T: Interned> Tok<T> {
|
||||||
pub fn new(data: Arc<T>, marker: T::Marker) -> Self { Self { data, marker: ForceSized(marker) } }
|
pub fn new(data: Rc<T>, marker: T::Marker) -> Self { Self { data, marker: ForceSized(marker) } }
|
||||||
pub fn to_api(&self) -> T::Marker { self.marker.0 }
|
pub fn to_api(&self) -> T::Marker { self.marker.0 }
|
||||||
pub async fn from_api<M>(marker: M) -> Self
|
pub async fn from_api<M>(marker: M, i: &mut Interner) -> Self
|
||||||
where M: InternMarker<Interned = T> {
|
where M: InternMarker<Interned = T> {
|
||||||
deintern(marker).await
|
i.deintern(marker).await
|
||||||
}
|
}
|
||||||
pub fn arc(&self) -> Arc<T> { self.data.clone() }
|
pub fn rc(&self) -> Rc<T> { self.data.clone() }
|
||||||
}
|
}
|
||||||
impl<T: Interned> Deref for Tok<T> {
|
impl<T: Interned> Deref for Tok<T> {
|
||||||
type Target = T;
|
type Target = T;
|
||||||
@@ -224,117 +226,65 @@ pub struct Interner {
|
|||||||
interners: TypedInterners,
|
interners: TypedInterners,
|
||||||
master: Option<Box<dyn DynRequester<Transfer = api::IntReq>>>,
|
master: Option<Box<dyn DynRequester<Transfer = api::IntReq>>>,
|
||||||
}
|
}
|
||||||
|
impl Interner {
|
||||||
static ID: atomic::AtomicU64 = atomic::AtomicU64::new(1);
|
pub fn new_master() -> Self { Self::default() }
|
||||||
static INTERNER: Mutex<Option<Interner>> = Mutex::new(None);
|
pub fn new_replica(req: impl DynRequester<Transfer = api::IntReq> + 'static) -> Self {
|
||||||
|
Self {
|
||||||
pub fn interner() -> impl DerefMut<Target = Interner> {
|
master: Some(Box::new(req)),
|
||||||
struct G(MutexGuard<'static, Option<Interner>>);
|
interners: TypedInterners { strings: Bimap::default(), vecs: Bimap::default() },
|
||||||
impl Deref for G {
|
|
||||||
type Target = Interner;
|
|
||||||
fn deref(&self) -> &Self::Target { self.0.as_ref().expect("Guard pre-initialized") }
|
|
||||||
}
|
|
||||||
impl DerefMut for G {
|
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
||||||
self.0.as_mut().expect("Guard pre-iniitialized")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut g = INTERNER.lock().unwrap();
|
pub async fn intern<T: Interned>(
|
||||||
g.get_or_insert_with(Interner::default);
|
&mut self,
|
||||||
G(g)
|
t: &(impl Internable<Interned = T> + ?Sized),
|
||||||
}
|
) -> Tok<T> {
|
||||||
|
let data = t.get_owned();
|
||||||
/// Initialize the interner in replica mode. No messages are sent at this point.
|
let job = format!("{t:?} in {}", if self.master.is_some() { "replica" } else { "master" });
|
||||||
pub fn init_replica(req: impl DynRequester<Transfer = api::IntReq> + 'static) {
|
eprintln!("Interning {job}");
|
||||||
let mut g = INTERNER.lock().unwrap();
|
let typed = T::bimap(&mut self.interners);
|
||||||
assert!(g.is_none(), "Attempted to initialize replica interner after first use");
|
if let Some(tok) = typed.by_value(&data) {
|
||||||
*g = Some(Interner {
|
return tok;
|
||||||
master: Some(Box::new(req)),
|
}
|
||||||
interners: TypedInterners { strings: Bimap::default(), vecs: Bimap::default() },
|
let marker = match &mut self.master {
|
||||||
})
|
Some(c) => data.clone().intern(&**c).await,
|
||||||
}
|
None =>
|
||||||
|
T::Marker::from_id(NonZeroU64::new(ID.fetch_add(1, atomic::Ordering::Relaxed)).unwrap()),
|
||||||
pub async fn intern<T: Interned>(t: &(impl Internable<Interned = T> + ?Sized)) -> Tok<T> {
|
};
|
||||||
let data = t.get_owned();
|
let tok = Tok::new(data, marker);
|
||||||
let mut g = interner();
|
T::bimap(&mut self.interners).insert(tok.clone());
|
||||||
let job = format!("{t:?} in {}", if g.master.is_some() { "replica" } else { "master" });
|
eprintln!("Interned {job}");
|
||||||
eprintln!("Interning {job}");
|
tok
|
||||||
let typed = T::bimap(&mut g.interners);
|
}
|
||||||
if let Some(tok) = typed.by_value(&data) {
|
async fn deintern<M: InternMarker>(&mut self, marker: M) -> Tok<M::Interned> {
|
||||||
return tok;
|
if let Some(tok) = M::Interned::bimap(&mut self.interners).by_marker(marker) {
|
||||||
|
return tok;
|
||||||
|
}
|
||||||
|
let master = self.master.as_mut().expect("ID not in local interner and this is master");
|
||||||
|
let token = marker.resolve(&**master).await;
|
||||||
|
M::Interned::bimap(&mut self.interners).insert(token.clone());
|
||||||
|
token
|
||||||
|
}
|
||||||
|
pub fn sweep_replica(&mut self) -> api::Retained {
|
||||||
|
assert!(self.master.is_some(), "Not a replica");
|
||||||
|
api::Retained {
|
||||||
|
strings: self.interners.strings.sweep_replica(),
|
||||||
|
vecs: self.interners.vecs.sweep_replica(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn sweep_master(&mut self, retained: api::Retained) {
|
||||||
|
assert!(self.master.is_none(), "Not master");
|
||||||
|
self.interners.strings.sweep_master(retained.strings.into_iter().collect());
|
||||||
|
self.interners.vecs.sweep_master(retained.vecs.into_iter().collect());
|
||||||
}
|
}
|
||||||
let marker = match &mut g.master {
|
|
||||||
Some(c) => data.clone().intern(&**c).await,
|
|
||||||
None =>
|
|
||||||
T::Marker::from_id(NonZeroU64::new(ID.fetch_add(1, atomic::Ordering::Relaxed)).unwrap()),
|
|
||||||
};
|
|
||||||
let tok = Tok::new(data, marker);
|
|
||||||
T::bimap(&mut g.interners).insert(tok.clone());
|
|
||||||
mem::drop(g);
|
|
||||||
eprintln!("Interned {job}");
|
|
||||||
tok
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn deintern<M: InternMarker>(marker: M) -> Tok<M::Interned> {
|
static ID: atomic::AtomicU64 = atomic::AtomicU64::new(1);
|
||||||
let mut g = interner();
|
|
||||||
if let Some(tok) = M::Interned::bimap(&mut g.interners).by_marker(marker) {
|
|
||||||
return tok;
|
|
||||||
}
|
|
||||||
let master = g.master.as_mut().expect("ID not in local interner and this is master");
|
|
||||||
let token = marker.resolve(&**master).await;
|
|
||||||
M::Interned::bimap(&mut g.interners).insert(token.clone());
|
|
||||||
token
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn merge_retained(into: &mut api::Retained, from: &api::Retained) {
|
pub fn merge_retained(into: &mut api::Retained, from: &api::Retained) {
|
||||||
into.strings = into.strings.iter().chain(&from.strings).copied().unique().collect();
|
into.strings = into.strings.iter().chain(&from.strings).copied().unique().collect();
|
||||||
into.vecs = into.vecs.iter().chain(&from.vecs).copied().unique().collect();
|
into.vecs = into.vecs.iter().chain(&from.vecs).copied().unique().collect();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sweep_replica() -> api::Retained {
|
|
||||||
let mut g = interner();
|
|
||||||
assert!(g.master.is_some(), "Not a replica");
|
|
||||||
api::Retained {
|
|
||||||
strings: g.interners.strings.sweep_replica(),
|
|
||||||
vecs: g.interners.vecs.sweep_replica(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a thread-local token instance and copy it. This ensures that the
|
|
||||||
/// interner will only be called the first time the expresion is executed,
|
|
||||||
/// and subsequent calls will just copy the token. Accepts a single static
|
|
||||||
/// expression (i.e. a literal).
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! intern {
|
|
||||||
($ty:ty : $expr:expr) => {{
|
|
||||||
use std::future::Future;
|
|
||||||
use std::ops::Deref as _;
|
|
||||||
use std::pin::Pin;
|
|
||||||
type Interned = <$ty as $crate::interner::Internable>::Interned;
|
|
||||||
type Output = $crate::interner::Tok<Interned>;
|
|
||||||
type InternFuture = Pin<Box<dyn Future<Output = Output>>>;
|
|
||||||
thread_local! {
|
|
||||||
static VALUE:
|
|
||||||
Pin<std::rc::Rc<$crate::async_once_cell::Lazy<Output, InternFuture>>> =
|
|
||||||
std::rc::Rc::pin($crate::async_once_cell::Lazy::new(Box::pin(async {
|
|
||||||
$crate::interner::intern::<Interned>($expr as &$ty).await
|
|
||||||
}) as InternFuture));
|
|
||||||
}
|
|
||||||
VALUE.with(|v| $crate::clone!(v; async move { v.as_ref().await.deref().clone() }))
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn scratch() -> String {
|
|
||||||
Arc::pin(Lazy::new(async { "foobar".to_string() })).as_ref().await.deref().clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn sweep_master(retained: api::Retained) {
|
|
||||||
let mut g = interner();
|
|
||||||
assert!(g.master.is_none(), "Not master");
|
|
||||||
g.interners.strings.sweep_master(retained.strings.into_iter().collect());
|
|
||||||
g.interners.vecs.sweep_master(retained.vecs.into_iter().collect());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use std::num::NonZero;
|
use std::num::NonZero;
|
||||||
|
|||||||
@@ -23,13 +23,14 @@ pub struct Receipt<'a>(PhantomData<&'a mut ()>);
|
|||||||
trait_set! {
|
trait_set! {
|
||||||
pub trait SendFn<T: MsgSet> =
|
pub trait SendFn<T: MsgSet> =
|
||||||
for<'a> FnMut(&'a [u8], ReqNot<T>) -> LocalBoxFuture<'a, ()>
|
for<'a> FnMut(&'a [u8], ReqNot<T>) -> LocalBoxFuture<'a, ()>
|
||||||
+ DynClone + Send + 'static;
|
+ DynClone + 'static;
|
||||||
pub trait ReqFn<T: MsgSet> = for<'a> FnMut(RequestHandle<'a, T>, <T::In as Channel>::Req)
|
pub trait ReqFn<T: MsgSet> =
|
||||||
-> LocalBoxFuture<'a, Receipt<'a>>
|
for<'a> FnMut(RequestHandle<'a, T>, <T::In as Channel>::Req)
|
||||||
+ DynClone + Send + Sync + 'static;
|
-> LocalBoxFuture<'a, Receipt<'a>>
|
||||||
|
+ DynClone + 'static;
|
||||||
pub trait NotifFn<T: MsgSet> =
|
pub trait NotifFn<T: MsgSet> =
|
||||||
FnMut(<T::In as Channel>::Notif, ReqNot<T>) -> LocalBoxFuture<'static, ()>
|
FnMut(<T::In as Channel>::Notif, ReqNot<T>) -> LocalBoxFuture<'static, ()>
|
||||||
+ DynClone + Send + Sync + 'static;
|
+ DynClone + 'static;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_id(message: &[u8]) -> (u64, &[u8]) {
|
fn get_id(message: &[u8]) -> (u64, &[u8]) {
|
||||||
@@ -145,15 +146,13 @@ impl<T: MsgSet> ReqNot<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait DynRequester: Send + Sync {
|
pub trait DynRequester {
|
||||||
type Transfer;
|
type Transfer;
|
||||||
/// Encode and send a request, then receive the response buffer.
|
/// Encode and send a request, then receive the response buffer.
|
||||||
fn raw_request(&self, data: Self::Transfer) -> LocalBoxFuture<'_, RawReply>;
|
fn raw_request(&self, data: Self::Transfer) -> LocalBoxFuture<'_, RawReply>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MappedRequester<'a, T: 'a>(
|
pub struct MappedRequester<'a, T: 'a>(Box<dyn Fn(T) -> LocalBoxFuture<'a, RawReply> + 'a>);
|
||||||
Box<dyn Fn(T) -> LocalBoxFuture<'a, RawReply> + Send + Sync + 'a>,
|
|
||||||
);
|
|
||||||
impl<'a, T> MappedRequester<'a, T> {
|
impl<'a, T> MappedRequester<'a, T> {
|
||||||
fn new<U: DynRequester + 'a>(req: U) -> Self
|
fn new<U: DynRequester + 'a>(req: U) -> Self
|
||||||
where T: Into<U::Transfer> {
|
where T: Into<U::Transfer> {
|
||||||
@@ -280,7 +279,9 @@ mod test {
|
|||||||
|_, _| panic!("Should not receive request"),
|
|_, _| panic!("Should not receive request"),
|
||||||
));
|
));
|
||||||
*receiver.lock().await = Some(ReqNot::new(
|
*receiver.lock().await = Some(ReqNot::new(
|
||||||
clone!(sender; move |d, _| clone!(sender; Box::pin(async move { sender.receive(d).await }))),
|
clone!(sender; move |d, _| clone!(sender; Box::pin(async move {
|
||||||
|
sender.receive(d).await
|
||||||
|
}))),
|
||||||
|_, _| panic!("Not receiving notifs"),
|
|_, _| panic!("Not receiving notifs"),
|
||||||
|hand, req| {
|
|hand, req| {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
ahash = "0.8.11"
|
ahash = "0.8.11"
|
||||||
|
async-once-cell = "0.5.4"
|
||||||
async-std = "1.13.0"
|
async-std = "1.13.0"
|
||||||
derive_destructure = "1.0.0"
|
derive_destructure = "1.0.0"
|
||||||
dyn-clone = "1.0.17"
|
dyn-clone = "1.0.17"
|
||||||
@@ -23,5 +24,6 @@ orchid-api-traits = { version = "0.1.0", path = "../orchid-api-traits" }
|
|||||||
orchid-base = { version = "0.1.0", path = "../orchid-base" }
|
orchid-base = { version = "0.1.0", path = "../orchid-base" }
|
||||||
ordered-float = "4.6.0"
|
ordered-float = "4.6.0"
|
||||||
paste = "1.0.15"
|
paste = "1.0.15"
|
||||||
|
some_executor = "0.4.0"
|
||||||
substack = "1.1.1"
|
substack = "1.1.1"
|
||||||
trait-set = "0.3.0"
|
trait-set = "0.3.0"
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
use std::any::{Any, TypeId, type_name};
|
use std::any::{Any, TypeId, type_name};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::future::Future;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::sync::{Arc, OnceLock};
|
use std::sync::Arc;
|
||||||
|
|
||||||
use dyn_clone::{DynClone, clone_box};
|
use dyn_clone::{DynClone, clone_box};
|
||||||
|
use futures::FutureExt;
|
||||||
|
use futures::future::LocalBoxFuture;
|
||||||
use orchid_api_traits::{Coding, Decode, Encode, Request, enc_vec};
|
use orchid_api_traits::{Coding, Decode, Encode, Request, enc_vec};
|
||||||
use orchid_base::error::{OrcErr, OrcRes, mk_err};
|
use orchid_base::error::{OrcErr, OrcRes, mk_err};
|
||||||
use orchid_base::intern;
|
use orchid_base::intern;
|
||||||
@@ -78,14 +81,14 @@ pub struct ForeignAtom<'a> {
|
|||||||
pub pos: Pos,
|
pub pos: Pos,
|
||||||
}
|
}
|
||||||
impl ForeignAtom<'_> {
|
impl ForeignAtom<'_> {
|
||||||
pub fn oex_opt(self) -> Option<Expr> {
|
pub fn ex_opt(self) -> Option<Expr> {
|
||||||
let (handle, pos) = (self.expr.as_ref()?.clone(), self.pos.clone());
|
let (handle, pos) = (self.expr.as_ref()?.clone(), self.pos.clone());
|
||||||
let data = ExprData { pos, kind: ExprKind::Atom(ForeignAtom { _life: PhantomData, ..self }) };
|
let data = ExprData { pos, kind: ExprKind::Atom(ForeignAtom { _life: PhantomData, ..self }) };
|
||||||
Some(Expr { handle: Some(handle), val: OnceLock::from(data) })
|
Some(Expr::new(handle, data))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl ForeignAtom<'static> {
|
impl ForeignAtom<'static> {
|
||||||
pub fn oex(self) -> Expr { self.oex_opt().unwrap() }
|
pub fn ex(self) -> Expr { self.ex_opt().unwrap() }
|
||||||
pub(crate) fn new(handle: Arc<ExprHandle>, atom: api::Atom, pos: Pos) -> Self {
|
pub(crate) fn new(handle: Arc<ExprHandle>, atom: api::Atom, pos: Pos) -> Self {
|
||||||
ForeignAtom { _life: PhantomData, atom, ctx: handle.ctx.clone(), expr: Some(handle), pos }
|
ForeignAtom { _life: PhantomData, atom, ctx: handle.ctx.clone(), expr: Some(handle), pos }
|
||||||
}
|
}
|
||||||
@@ -130,11 +133,16 @@ pub trait AtomMethod: Request {
|
|||||||
const NAME: &str;
|
const NAME: &str;
|
||||||
}
|
}
|
||||||
pub trait Supports<M: AtomMethod>: AtomCard {
|
pub trait Supports<M: AtomMethod>: AtomCard {
|
||||||
fn handle(&self, ctx: SysCtx, req: M) -> <M as Request>::Response;
|
fn handle(&self, ctx: SysCtx, req: M) -> LocalBoxFuture<'_, <M as Request>::Response>;
|
||||||
}
|
}
|
||||||
|
|
||||||
trait_set! {
|
trait_set! {
|
||||||
trait AtomReqCb<A> = Fn(&A, SysCtx, &mut dyn Read, &mut dyn Write) + Send + Sync
|
trait AtomReqCb<A> = for<'a> Fn(
|
||||||
|
&'a A,
|
||||||
|
SysCtx,
|
||||||
|
&'a mut dyn Read,
|
||||||
|
&'a mut dyn Write
|
||||||
|
) -> LocalBoxFuture<'a, ()> + Send + Sync
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AtomReqHandler<A: AtomCard> {
|
pub struct AtomReqHandler<A: AtomCard> {
|
||||||
@@ -153,26 +161,28 @@ impl<A: AtomCard> MethodSet<A> {
|
|||||||
self.handlers.push(AtomReqHandler {
|
self.handlers.push(AtomReqHandler {
|
||||||
key: Sym::parse(M::NAME).await.expect("AtomMethod::NAME cannoot be empty"),
|
key: Sym::parse(M::NAME).await.expect("AtomMethod::NAME cannoot be empty"),
|
||||||
cb: Box::new(move |a: &A, ctx: SysCtx, req: &mut dyn Read, rep: &mut dyn Write| {
|
cb: Box::new(move |a: &A, ctx: SysCtx, req: &mut dyn Read, rep: &mut dyn Write| {
|
||||||
Supports::<M>::handle(a, ctx, M::decode(req)).encode(rep);
|
async { Supports::<M>::handle(a, ctx, M::decode(req)).await.encode(rep) }.boxed_local()
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn dispatch(
|
pub(crate) fn dispatch<'a>(
|
||||||
&self,
|
&'a self,
|
||||||
atom: &A,
|
atom: &'a A,
|
||||||
ctx: SysCtx,
|
ctx: SysCtx,
|
||||||
key: Sym,
|
key: Sym,
|
||||||
req: &mut dyn Read,
|
req: &'a mut dyn Read,
|
||||||
rep: &mut dyn Write,
|
rep: &'a mut dyn Write,
|
||||||
) -> bool {
|
) -> impl Future<Output = bool> + 'a {
|
||||||
match self.handlers.iter().find(|h| h.key == key) {
|
async move {
|
||||||
None => false,
|
match self.handlers.iter().find(|h| h.key == key) {
|
||||||
Some(handler) => {
|
None => false,
|
||||||
(handler.cb)(atom, ctx, req, rep);
|
Some(handler) => {
|
||||||
true
|
(handler.cb)(atom, ctx, req, rep).await;
|
||||||
},
|
true
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -187,11 +197,11 @@ pub struct TypAtom<'a, A: AtomicFeatures> {
|
|||||||
pub value: A::Data,
|
pub value: A::Data,
|
||||||
}
|
}
|
||||||
impl<A: AtomicFeatures> TypAtom<'static, A> {
|
impl<A: AtomicFeatures> TypAtom<'static, A> {
|
||||||
pub fn downcast(expr: Arc<ExprHandle>) -> Result<Self, NotTypAtom> {
|
pub async fn downcast(expr: Arc<ExprHandle>) -> Result<Self, NotTypAtom> {
|
||||||
match Expr::new(expr).foreign_atom() {
|
match Expr::from_handle(expr).atom().await {
|
||||||
Err(oe) => Err(NotTypAtom(oe.get_data().pos.clone(), oe, Box::new(A::info()))),
|
Err(oe) => Err(NotTypAtom(oe.data().await.pos.clone(), oe, Box::new(A::info()))),
|
||||||
Ok(atm) => match downcast_atom::<A>(atm) {
|
Ok(atm) => match downcast_atom::<A>(atm) {
|
||||||
Err(fa) => Err(NotTypAtom(fa.pos.clone(), fa.oex(), Box::new(A::info()))),
|
Err(fa) => Err(NotTypAtom(fa.pos.clone(), fa.ex(), Box::new(A::info()))),
|
||||||
Ok(tatom) => Ok(tatom),
|
Ok(tatom) => Ok(tatom),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -222,25 +232,37 @@ pub trait AtomDynfo: Send + Sync + 'static {
|
|||||||
fn tid(&self) -> TypeId;
|
fn tid(&self) -> TypeId;
|
||||||
fn name(&self) -> &'static str;
|
fn name(&self) -> &'static str;
|
||||||
fn decode(&self, ctx: AtomCtx<'_>) -> Box<dyn Any>;
|
fn decode(&self, ctx: AtomCtx<'_>) -> Box<dyn Any>;
|
||||||
fn call(&self, ctx: AtomCtx<'_>, arg: api::ExprTicket) -> Expr;
|
fn call<'a>(&'a self, ctx: AtomCtx<'a>, arg: api::ExprTicket) -> LocalBoxFuture<'a, Expr>;
|
||||||
fn call_ref(&self, ctx: AtomCtx<'_>, arg: api::ExprTicket) -> Expr;
|
fn call_ref<'a>(&'a self, ctx: AtomCtx<'a>, arg: api::ExprTicket) -> LocalBoxFuture<'a, Expr>;
|
||||||
fn print(&self, ctx: AtomCtx<'_>) -> String;
|
fn print<'a>(&'a self, ctx: AtomCtx<'a>) -> LocalBoxFuture<'a, String>;
|
||||||
fn handle_req(&self, ctx: AtomCtx<'_>, key: Sym, req: &mut dyn Read, rep: &mut dyn Write)
|
fn handle_req<'a, 'b: 'a, 'c: 'a>(
|
||||||
-> bool;
|
&'a self,
|
||||||
fn command(&self, ctx: AtomCtx<'_>) -> OrcRes<Option<Expr>>;
|
ctx: AtomCtx<'a>,
|
||||||
fn serialize(&self, ctx: AtomCtx<'_>, write: &mut dyn Write) -> Option<Vec<api::ExprTicket>>;
|
key: Sym,
|
||||||
fn deserialize(&self, ctx: SysCtx, data: &[u8], refs: &[api::ExprTicket]) -> api::Atom;
|
req: &'b mut dyn Read,
|
||||||
fn drop(&self, ctx: AtomCtx<'_>);
|
rep: &'c mut dyn Write,
|
||||||
|
) -> LocalBoxFuture<'a, bool>;
|
||||||
|
fn command<'a>(&'a self, ctx: AtomCtx<'a>) -> LocalBoxFuture<'a, OrcRes<Option<Expr>>>;
|
||||||
|
fn serialize<'a, 'b: 'a>(
|
||||||
|
&'a self,
|
||||||
|
ctx: AtomCtx<'a>,
|
||||||
|
write: &'b mut dyn Write,
|
||||||
|
) -> LocalBoxFuture<'a, Option<Vec<api::ExprTicket>>>;
|
||||||
|
fn deserialize<'a>(
|
||||||
|
&'a self,
|
||||||
|
ctx: SysCtx,
|
||||||
|
data: &'a [u8],
|
||||||
|
refs: &'a [api::ExprTicket],
|
||||||
|
) -> LocalBoxFuture<'a, api::Atom>;
|
||||||
|
fn drop<'a>(&'a self, ctx: AtomCtx<'a>) -> LocalBoxFuture<'a, ()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
trait_set! {
|
trait_set! {
|
||||||
pub trait AtomFactoryFn = FnOnce(SysCtx) -> api::Atom + DynClone + Send + Sync;
|
pub trait AtomFactoryFn = FnOnce(SysCtx) -> api::Atom + DynClone;
|
||||||
}
|
}
|
||||||
pub struct AtomFactory(Box<dyn AtomFactoryFn>);
|
pub struct AtomFactory(Box<dyn AtomFactoryFn>);
|
||||||
impl AtomFactory {
|
impl AtomFactory {
|
||||||
pub fn new(f: impl FnOnce(SysCtx) -> api::Atom + Clone + Send + Sync + 'static) -> Self {
|
pub fn new(f: impl FnOnce(SysCtx) -> api::Atom + Clone + 'static) -> Self { Self(Box::new(f)) }
|
||||||
Self(Box::new(f))
|
|
||||||
}
|
|
||||||
pub fn build(self, ctx: SysCtx) -> api::Atom { (self.0)(ctx) }
|
pub fn build(self, ctx: SysCtx) -> api::Atom { (self.0)(ctx) }
|
||||||
}
|
}
|
||||||
impl Clone for AtomFactory {
|
impl Clone for AtomFactory {
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
use std::any::{Any, TypeId, type_name};
|
use std::any::{Any, TypeId, type_name};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
use std::future::Future;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use futures::FutureExt;
|
||||||
|
use futures::future::{LocalBoxFuture, ready};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use never::Never;
|
use never::Never;
|
||||||
use orchid_api_traits::{Decode, Encode, enc_vec};
|
use orchid_api_traits::{Decode, Encode, enc_vec};
|
||||||
|
use orchid_base::clone;
|
||||||
use orchid_base::error::OrcRes;
|
use orchid_base::error::OrcRes;
|
||||||
use orchid_base::id_store::{IdRecord, IdStore};
|
use orchid_base::id_store::{IdRecord, IdStore};
|
||||||
use orchid_base::name::Sym;
|
use orchid_base::name::Sym;
|
||||||
@@ -23,7 +27,7 @@ impl AtomicVariant for OwnedVariant {}
|
|||||||
impl<A: OwnedAtom + Atomic<Variant = OwnedVariant>> AtomicFeaturesImpl<OwnedVariant> for A {
|
impl<A: OwnedAtom + Atomic<Variant = OwnedVariant>> AtomicFeaturesImpl<OwnedVariant> for A {
|
||||||
fn _factory(self) -> AtomFactory {
|
fn _factory(self) -> AtomFactory {
|
||||||
AtomFactory::new(move |ctx| {
|
AtomFactory::new(move |ctx| {
|
||||||
let rec = OBJ_STORE.add(Box::new(self));
|
let rec = ctx.obj_store.add(Box::new(self));
|
||||||
let (id, _) = get_info::<A>(ctx.cted.inst().card());
|
let (id, _) = get_info::<A>(ctx.cted.inst().card());
|
||||||
let mut data = enc_vec(&id);
|
let mut data = enc_vec(&id);
|
||||||
rec.encode(&mut data);
|
rec.encode(&mut data);
|
||||||
@@ -34,57 +38,96 @@ impl<A: OwnedAtom + Atomic<Variant = OwnedVariant>> AtomicFeaturesImpl<OwnedVari
|
|||||||
type _Info = OwnedAtomDynfo<A>;
|
type _Info = OwnedAtomDynfo<A>;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_atom<U>(id: api::AtomId, f: impl FnOnce(IdRecord<'_, Box<dyn DynOwnedAtom>>) -> U) -> U {
|
fn with_atom<'a, U>(
|
||||||
f(OBJ_STORE.get(id.0).unwrap_or_else(|| panic!("Received invalid atom ID: {}", id.0)))
|
id: api::AtomId,
|
||||||
|
ctx: &'a SysCtx,
|
||||||
|
f: impl FnOnce(IdRecord<'a, Box<dyn DynOwnedAtom>>) -> U,
|
||||||
|
) -> U {
|
||||||
|
f(ctx.obj_store.get(id.0).unwrap_or_else(|| panic!("Received invalid atom ID: {}", id.0)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct OwnedAtomDynfo<T: OwnedAtom>(MethodSet<T>);
|
pub struct OwnedAtomDynfo<T: OwnedAtom>(MethodSet<T>);
|
||||||
impl<T: OwnedAtom> AtomDynfo for OwnedAtomDynfo<T> {
|
impl<T: OwnedAtom> AtomDynfo for OwnedAtomDynfo<T> {
|
||||||
fn print(&self, AtomCtx(_, id, ctx): AtomCtx<'_>) -> String {
|
|
||||||
with_atom(id.unwrap(), |a| a.dyn_print(ctx))
|
|
||||||
}
|
|
||||||
fn tid(&self) -> TypeId { TypeId::of::<T>() }
|
fn tid(&self) -> TypeId { TypeId::of::<T>() }
|
||||||
fn name(&self) -> &'static str { type_name::<T>() }
|
fn name(&self) -> &'static str { type_name::<T>() }
|
||||||
fn decode(&self, AtomCtx(data, ..): AtomCtx) -> Box<dyn Any> {
|
fn decode(&self, AtomCtx(data, ..): AtomCtx) -> Box<dyn Any> {
|
||||||
Box::new(<T as AtomCard>::Data::decode(&mut &data[..]))
|
Box::new(<T as AtomCard>::Data::decode(&mut &data[..]))
|
||||||
}
|
}
|
||||||
fn call(&self, AtomCtx(_, id, ctx): AtomCtx, arg: api::ExprTicket) -> Expr {
|
fn call(&self, AtomCtx(_, id, ctx): AtomCtx, arg: api::ExprTicket) -> LocalBoxFuture<'_, Expr> {
|
||||||
with_atom(id.unwrap(), |a| a.remove().dyn_call(ctx, arg))
|
with_atom(id.unwrap(), &ctx, |a| a.remove()).dyn_call(ctx.clone(), arg)
|
||||||
}
|
}
|
||||||
fn call_ref(&self, AtomCtx(_, id, ctx): AtomCtx, arg: api::ExprTicket) -> Expr {
|
fn call_ref<'a>(
|
||||||
with_atom(id.unwrap(), |a| a.dyn_call_ref(ctx, arg))
|
&'a self,
|
||||||
|
AtomCtx(_, id, ctx): AtomCtx<'a>,
|
||||||
|
arg: api::ExprTicket,
|
||||||
|
) -> LocalBoxFuture<'a, Expr> {
|
||||||
|
async move {
|
||||||
|
with_atom(id.unwrap(), &ctx, |a| clone!(ctx; async move { a.dyn_call_ref(ctx, arg).await }))
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
.boxed_local()
|
||||||
}
|
}
|
||||||
fn handle_req(
|
fn print(&self, AtomCtx(_, id, ctx): AtomCtx<'_>) -> LocalBoxFuture<'_, String> {
|
||||||
&self,
|
async move {
|
||||||
|
with_atom(id.unwrap(), &ctx, |a| clone!(ctx; async move { a.dyn_print(ctx).await })).await
|
||||||
|
}
|
||||||
|
.boxed_local()
|
||||||
|
}
|
||||||
|
fn handle_req<'a, 'b: 'a, 'c: 'a>(
|
||||||
|
&'a self,
|
||||||
AtomCtx(_, id, ctx): AtomCtx,
|
AtomCtx(_, id, ctx): AtomCtx,
|
||||||
key: Sym,
|
key: Sym,
|
||||||
req: &mut dyn Read,
|
req: &'b mut dyn Read,
|
||||||
rep: &mut dyn Write,
|
rep: &'c mut dyn Write,
|
||||||
) -> bool {
|
) -> LocalBoxFuture<'a, bool> {
|
||||||
with_atom(id.unwrap(), |a| {
|
async move {
|
||||||
self.0.dispatch(a.as_any_ref().downcast_ref().unwrap(), ctx, key, req, rep)
|
with_atom(id.unwrap(), &ctx, |a| {
|
||||||
})
|
clone!(ctx; async move {
|
||||||
|
self.0.dispatch(a.as_any_ref().downcast_ref().unwrap(), ctx, key, req, rep).await
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
.boxed_local()
|
||||||
}
|
}
|
||||||
fn command(&self, AtomCtx(_, id, ctx): AtomCtx<'_>) -> OrcRes<Option<Expr>> {
|
fn command<'a>(
|
||||||
with_atom(id.unwrap(), |a| a.remove().dyn_command(ctx))
|
&'a self,
|
||||||
|
AtomCtx(_, id, ctx): AtomCtx<'a>,
|
||||||
|
) -> LocalBoxFuture<'a, OrcRes<Option<Expr>>> {
|
||||||
|
async move { with_atom(id.unwrap(), &ctx, |a| a.remove().dyn_command(ctx.clone())).await }
|
||||||
|
.boxed_local()
|
||||||
}
|
}
|
||||||
fn drop(&self, AtomCtx(_, id, ctx): AtomCtx) {
|
fn drop(&self, AtomCtx(_, id, ctx): AtomCtx) -> LocalBoxFuture<'_, ()> {
|
||||||
with_atom(id.unwrap(), |a| a.remove().dyn_free(ctx))
|
async move { with_atom(id.unwrap(), &ctx, |a| a.remove().dyn_free(ctx.clone())).await }
|
||||||
|
.boxed_local()
|
||||||
}
|
}
|
||||||
fn serialize(
|
fn serialize<'a, 'b: 'a>(
|
||||||
&self,
|
&'a self,
|
||||||
AtomCtx(_, id, ctx): AtomCtx<'_>,
|
AtomCtx(_, id, ctx): AtomCtx<'a>,
|
||||||
write: &mut dyn Write,
|
write: &'b mut dyn Write,
|
||||||
) -> Option<Vec<api::ExprTicket>> {
|
) -> LocalBoxFuture<'a, Option<Vec<api::ExprTicket>>> {
|
||||||
let id = id.unwrap();
|
async move {
|
||||||
id.encode(write);
|
let id = id.unwrap();
|
||||||
with_atom(id, |a| a.dyn_serialize(ctx, write))
|
id.encode(write);
|
||||||
.map(|v| v.into_iter().map(|t| t.handle.unwrap().tk).collect_vec())
|
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().unwrap().tk).collect_vec())
|
||||||
|
}
|
||||||
|
.boxed_local()
|
||||||
}
|
}
|
||||||
fn deserialize(&self, ctx: SysCtx, data: &[u8], refs: &[api::ExprTicket]) -> orchid_api::Atom {
|
fn deserialize<'a>(
|
||||||
let refs = refs.iter().map(|tk| Expr::new(Arc::new(ExprHandle::from_args(ctx.clone(), *tk))));
|
&'a self,
|
||||||
let obj = T::deserialize(DeserCtxImpl(data, &ctx), T::Refs::from_iter(refs));
|
ctx: SysCtx,
|
||||||
obj._factory().build(ctx)
|
data: &'a [u8],
|
||||||
|
refs: &'a [api::ExprTicket],
|
||||||
|
) -> LocalBoxFuture<'a, api::Atom> {
|
||||||
|
async move {
|
||||||
|
let refs =
|
||||||
|
refs.iter().map(|tk| Expr::from_handle(Arc::new(ExprHandle::from_args(ctx.clone(), *tk))));
|
||||||
|
let obj = T::deserialize(DeserCtxImpl(data, &ctx), T::Refs::from_iter(refs)).await;
|
||||||
|
obj._factory().build(ctx)
|
||||||
|
}
|
||||||
|
.boxed_local()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,7 +183,7 @@ impl<const N: usize> RefSet for [Expr; N] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Atoms that have a [Drop]
|
/// Atoms that have a [Drop]
|
||||||
pub trait OwnedAtom: Atomic<Variant = OwnedVariant> + Send + Sync + Any + Clone + 'static {
|
pub trait OwnedAtom: Atomic<Variant = OwnedVariant> + Any + Clone + 'static {
|
||||||
/// If serializable, the collection that best stores subexpression references
|
/// If serializable, the collection that best stores subexpression references
|
||||||
/// for this atom.
|
/// for this atom.
|
||||||
///
|
///
|
||||||
@@ -152,66 +195,96 @@ pub trait OwnedAtom: Atomic<Variant = OwnedVariant> + Send + Sync + Any + Clone
|
|||||||
/// If this isn't `Never`, you must override the default, panicking
|
/// If this isn't `Never`, you must override the default, panicking
|
||||||
/// `serialize` and `deserialize` implementation
|
/// `serialize` and `deserialize` implementation
|
||||||
type Refs: RefSet;
|
type Refs: RefSet;
|
||||||
fn val(&self) -> Cow<'_, Self::Data>;
|
fn val(&self) -> impl Future<Output = Cow<'_, Self::Data>>;
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn call_ref(&self, arg: ExprHandle) -> Expr { bot([err_not_callable()]) }
|
fn call_ref(&self, arg: ExprHandle) -> impl Future<Output = Expr> {
|
||||||
fn call(self, arg: ExprHandle) -> Expr {
|
async { bot([err_not_callable().await]) }
|
||||||
let ctx = arg.get_ctx();
|
}
|
||||||
let gcl = self.call_ref(arg);
|
fn call(self, arg: ExprHandle) -> impl Future<Output = Expr> {
|
||||||
self.free(ctx);
|
async {
|
||||||
gcl
|
let ctx = arg.get_ctx();
|
||||||
|
let gcl = self.call_ref(arg).await;
|
||||||
|
self.free(ctx);
|
||||||
|
gcl
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn command(self, ctx: SysCtx) -> OrcRes<Option<Expr>> { Err(err_not_command().into()) }
|
fn command(self, ctx: SysCtx) -> impl Future<Output = OrcRes<Option<Expr>>> {
|
||||||
#[allow(unused_variables)]
|
async { Err(err_not_command().await.into()) }
|
||||||
fn free(self, ctx: SysCtx) {}
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
fn print(&self, ctx: SysCtx) -> String { format!("OwnedAtom({})", type_name::<Self>()) }
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
fn serialize(&self, ctx: SysCtx, write: &mut (impl Write + ?Sized)) -> Self::Refs {
|
|
||||||
assert!(
|
|
||||||
TypeId::of::<Self::Refs>() != TypeId::of::<Never>(),
|
|
||||||
"The extension scaffold is broken, this function should never be called on Never Refs"
|
|
||||||
);
|
|
||||||
panic!("Either implement serialize or set Refs to Never for {}", type_name::<Self>())
|
|
||||||
}
|
}
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn deserialize(ctx: impl DeserializeCtx, refs: Self::Refs) -> Self {
|
fn free(self, ctx: SysCtx) -> impl Future<Output = ()> { async {} }
|
||||||
assert!(
|
#[allow(unused_variables)]
|
||||||
TypeId::of::<Self::Refs>() != TypeId::of::<Never>(),
|
fn print(&self, ctx: SysCtx) -> impl Future<Output = String> {
|
||||||
"The extension scaffold is broken, this function should never be called on Never Refs"
|
async { format!("OwnedAtom({})", type_name::<Self>()) }
|
||||||
);
|
}
|
||||||
panic!("Either implement deserialize or set Refs to Never for {}", type_name::<Self>())
|
#[allow(unused_variables)]
|
||||||
|
fn serialize(
|
||||||
|
&self,
|
||||||
|
ctx: SysCtx,
|
||||||
|
write: &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>()) }
|
||||||
|
}
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn deserialize(ctx: impl DeserializeCtx, refs: Self::Refs) -> impl Future<Output = Self> {
|
||||||
|
assert_serializable::<Self>();
|
||||||
|
async {
|
||||||
|
panic!("Either implement deserialize or set Refs to Never for {}", type_name::<Self>())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub trait DynOwnedAtom: Send + Sync + 'static {
|
|
||||||
|
fn assert_serializable<T: OwnedAtom>() {
|
||||||
|
static MSG: &str = "The extension scaffold is broken, Never Refs should prevent serialization";
|
||||||
|
assert_ne!(TypeId::of::<T::Refs>(), TypeId::of::<Never>(), "{MSG}");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait DynOwnedAtom: 'static {
|
||||||
fn atom_tid(&self) -> TypeId;
|
fn atom_tid(&self) -> TypeId;
|
||||||
fn as_any_ref(&self) -> &dyn Any;
|
fn as_any_ref(&self) -> &dyn Any;
|
||||||
fn encode(&self, buffer: &mut dyn Write);
|
fn encode<'a>(&'a self, buffer: &'a mut dyn Write) -> LocalBoxFuture<'a, ()>;
|
||||||
fn dyn_call_ref(&self, ctx: SysCtx, arg: api::ExprTicket) -> Expr;
|
fn dyn_call_ref(&self, ctx: SysCtx, arg: api::ExprTicket) -> LocalBoxFuture<'_, Expr>;
|
||||||
fn dyn_call(self: Box<Self>, ctx: SysCtx, arg: api::ExprTicket) -> Expr;
|
fn dyn_call(self: Box<Self>, ctx: SysCtx, arg: api::ExprTicket) -> LocalBoxFuture<'static, Expr>;
|
||||||
fn dyn_command(self: Box<Self>, ctx: SysCtx) -> OrcRes<Option<Expr>>;
|
fn dyn_command(self: Box<Self>, ctx: SysCtx) -> LocalBoxFuture<'static, OrcRes<Option<Expr>>>;
|
||||||
fn dyn_free(self: Box<Self>, ctx: SysCtx);
|
fn dyn_free(self: Box<Self>, ctx: SysCtx) -> LocalBoxFuture<'static, ()>;
|
||||||
fn dyn_print(&self, ctx: SysCtx) -> String;
|
fn dyn_print(&self, ctx: SysCtx) -> LocalBoxFuture<'_, String>;
|
||||||
fn dyn_serialize(&self, ctx: SysCtx, sink: &mut dyn Write) -> Option<Vec<Expr>>;
|
fn dyn_serialize<'a>(
|
||||||
|
&'a self,
|
||||||
|
ctx: SysCtx,
|
||||||
|
sink: &'a mut dyn Write,
|
||||||
|
) -> LocalBoxFuture<'a, Option<Vec<Expr>>>;
|
||||||
}
|
}
|
||||||
impl<T: OwnedAtom> DynOwnedAtom for T {
|
impl<T: OwnedAtom> DynOwnedAtom for T {
|
||||||
fn atom_tid(&self) -> TypeId { TypeId::of::<T>() }
|
fn atom_tid(&self) -> TypeId { TypeId::of::<T>() }
|
||||||
fn as_any_ref(&self) -> &dyn Any { self }
|
fn as_any_ref(&self) -> &dyn Any { self }
|
||||||
fn encode(&self, buffer: &mut dyn Write) { self.val().as_ref().encode(buffer) }
|
fn encode<'a>(&'a self, buffer: &'a mut dyn Write) -> LocalBoxFuture<'a, ()> {
|
||||||
fn dyn_call_ref(&self, ctx: SysCtx, arg: api::ExprTicket) -> Expr {
|
async { self.val().await.as_ref().encode(buffer) }.boxed_local()
|
||||||
self.call_ref(ExprHandle::from_args(ctx, arg))
|
|
||||||
}
|
}
|
||||||
fn dyn_call(self: Box<Self>, ctx: SysCtx, arg: api::ExprTicket) -> Expr {
|
fn dyn_call_ref(&self, ctx: SysCtx, arg: api::ExprTicket) -> LocalBoxFuture<'_, Expr> {
|
||||||
self.call(ExprHandle::from_args(ctx, arg))
|
self.call_ref(ExprHandle::from_args(ctx, arg)).boxed_local()
|
||||||
}
|
}
|
||||||
fn dyn_command(self: Box<Self>, ctx: SysCtx) -> OrcRes<Option<Expr>> { self.command(ctx) }
|
fn dyn_call(self: Box<Self>, ctx: SysCtx, arg: api::ExprTicket) -> LocalBoxFuture<'static, Expr> {
|
||||||
fn dyn_free(self: Box<Self>, ctx: SysCtx) { self.free(ctx) }
|
self.call(ExprHandle::from_args(ctx, arg)).boxed_local()
|
||||||
fn dyn_print(&self, ctx: SysCtx) -> String { self.print(ctx) }
|
}
|
||||||
fn dyn_serialize(&self, ctx: SysCtx, sink: &mut dyn Write) -> Option<Vec<Expr>> {
|
fn dyn_command(self: Box<Self>, ctx: SysCtx) -> LocalBoxFuture<'static, OrcRes<Option<Expr>>> {
|
||||||
(TypeId::of::<Never>() != TypeId::of::<<Self as OwnedAtom>::Refs>())
|
self.command(ctx).boxed_local()
|
||||||
.then(|| self.serialize(ctx, sink).to_vec())
|
}
|
||||||
|
fn dyn_free(self: Box<Self>, ctx: SysCtx) -> LocalBoxFuture<'static, ()> {
|
||||||
|
self.free(ctx).boxed_local()
|
||||||
|
}
|
||||||
|
fn dyn_print(&self, ctx: SysCtx) -> LocalBoxFuture<'_, String> { self.print(ctx).boxed_local() }
|
||||||
|
fn dyn_serialize<'a>(
|
||||||
|
&'a self,
|
||||||
|
ctx: SysCtx,
|
||||||
|
sink: &'a mut dyn Write,
|
||||||
|
) -> LocalBoxFuture<'a, Option<Vec<Expr>>> {
|
||||||
|
match TypeId::of::<Never>() == TypeId::of::<<Self as OwnedAtom>::Refs>() {
|
||||||
|
true => ready(None).boxed_local(),
|
||||||
|
false => async { Some(self.serialize(ctx, sink).await.to_vec()) }.boxed_local(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) static OBJ_STORE: IdStore<Box<dyn DynOwnedAtom>> = IdStore::new();
|
pub type ObjStore = Arc<IdStore<Box<dyn DynOwnedAtom>>>;
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
use std::any::{Any, TypeId, type_name};
|
use std::any::{Any, TypeId, type_name};
|
||||||
|
use std::future::Future;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
|
use futures::FutureExt;
|
||||||
|
use futures::future::LocalBoxFuture;
|
||||||
use orchid_api_traits::{Coding, enc_vec};
|
use orchid_api_traits::{Coding, enc_vec};
|
||||||
use orchid_base::error::OrcRes;
|
use orchid_base::error::OrcRes;
|
||||||
use orchid_base::name::Sym;
|
use orchid_base::name::Sym;
|
||||||
@@ -30,41 +33,67 @@ impl<A: ThinAtom + Atomic<Variant = ThinVariant>> AtomicFeaturesImpl<ThinVariant
|
|||||||
|
|
||||||
pub struct ThinAtomDynfo<T: ThinAtom>(MethodSet<T>);
|
pub struct ThinAtomDynfo<T: ThinAtom>(MethodSet<T>);
|
||||||
impl<T: ThinAtom> AtomDynfo for ThinAtomDynfo<T> {
|
impl<T: ThinAtom> AtomDynfo for ThinAtomDynfo<T> {
|
||||||
fn print(&self, AtomCtx(buf, _, ctx): AtomCtx<'_>) -> String {
|
fn print<'a>(&self, AtomCtx(buf, _, ctx): AtomCtx<'a>) -> LocalBoxFuture<'a, String> {
|
||||||
T::decode(&mut &buf[..]).print(ctx)
|
async move { T::decode(&mut &buf[..]).print(ctx).await }.boxed_local()
|
||||||
}
|
}
|
||||||
fn tid(&self) -> TypeId { TypeId::of::<T>() }
|
fn tid(&self) -> TypeId { TypeId::of::<T>() }
|
||||||
fn name(&self) -> &'static str { type_name::<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(&self, AtomCtx(buf, ..): AtomCtx) -> Box<dyn Any> { Box::new(T::decode(&mut &buf[..])) }
|
||||||
fn call(&self, AtomCtx(buf, _, ctx): AtomCtx, arg: api::ExprTicket) -> Expr {
|
fn call<'a>(
|
||||||
T::decode(&mut &buf[..]).call(ExprHandle::from_args(ctx, arg))
|
&'a self,
|
||||||
|
AtomCtx(buf, _, ctx): AtomCtx<'a>,
|
||||||
|
arg: api::ExprTicket,
|
||||||
|
) -> LocalBoxFuture<'a, Expr> {
|
||||||
|
async move { T::decode(&mut &buf[..]).call(ExprHandle::from_args(ctx, arg)).await }
|
||||||
|
.boxed_local()
|
||||||
}
|
}
|
||||||
fn call_ref(&self, AtomCtx(buf, _, ctx): AtomCtx, arg: api::ExprTicket) -> Expr {
|
fn call_ref<'a>(
|
||||||
T::decode(&mut &buf[..]).call(ExprHandle::from_args(ctx, arg))
|
&'a self,
|
||||||
|
AtomCtx(buf, _, ctx): AtomCtx<'a>,
|
||||||
|
arg: api::ExprTicket,
|
||||||
|
) -> LocalBoxFuture<'a, Expr> {
|
||||||
|
async move { T::decode(&mut &buf[..]).call(ExprHandle::from_args(ctx, arg)).await }
|
||||||
|
.boxed_local()
|
||||||
}
|
}
|
||||||
fn handle_req(
|
fn handle_req<'a, 'm1: 'a, 'm2: 'a>(
|
||||||
&self,
|
&'a self,
|
||||||
AtomCtx(buf, _, sys): AtomCtx,
|
AtomCtx(buf, _, sys): AtomCtx<'a>,
|
||||||
key: Sym,
|
key: Sym,
|
||||||
req: &mut dyn std::io::Read,
|
req: &'m1 mut dyn std::io::Read,
|
||||||
rep: &mut dyn Write,
|
rep: &'m2 mut dyn Write,
|
||||||
) -> bool {
|
) -> LocalBoxFuture<'a, bool> {
|
||||||
self.0.dispatch(&T::decode(&mut &buf[..]), sys, key, req, rep)
|
async move { self.0.dispatch(&T::decode(&mut &buf[..]), sys, key, req, rep).await }
|
||||||
|
.boxed_local()
|
||||||
}
|
}
|
||||||
fn command(&self, AtomCtx(buf, _, ctx): AtomCtx<'_>) -> OrcRes<Option<Expr>> {
|
fn command<'a>(
|
||||||
T::decode(&mut &buf[..]).command(ctx)
|
&'a self,
|
||||||
|
AtomCtx(buf, _, ctx): AtomCtx<'a>,
|
||||||
|
) -> LocalBoxFuture<'a, OrcRes<Option<Expr>>> {
|
||||||
|
async move { T::decode(&mut &buf[..]).command(ctx).await }.boxed_local()
|
||||||
}
|
}
|
||||||
fn serialize(&self, actx: AtomCtx<'_>, write: &mut dyn Write) -> Option<Vec<api::ExprTicket>> {
|
fn serialize<'a, 'b: 'a>(
|
||||||
T::decode(&mut &actx.0[..]).encode(write);
|
&'a self,
|
||||||
Some(Vec::new())
|
ctx: AtomCtx<'a>,
|
||||||
|
write: &'b mut dyn Write,
|
||||||
|
) -> LocalBoxFuture<'a, Option<Vec<api::ExprTicket>>> {
|
||||||
|
T::decode(&mut &ctx.0[..]).encode(write);
|
||||||
|
async { Some(Vec::new()) }.boxed_local()
|
||||||
}
|
}
|
||||||
fn deserialize(&self, ctx: SysCtx, data: &[u8], refs: &[api::ExprTicket]) -> api::Atom {
|
fn deserialize<'a>(
|
||||||
|
&'a self,
|
||||||
|
ctx: SysCtx,
|
||||||
|
data: &'a [u8],
|
||||||
|
refs: &'a [api::ExprTicket],
|
||||||
|
) -> LocalBoxFuture<'a, api::Atom> {
|
||||||
assert!(refs.is_empty(), "Refs found when deserializing thin atom");
|
assert!(refs.is_empty(), "Refs found when deserializing thin atom");
|
||||||
T::decode(&mut &data[..])._factory().build(ctx)
|
async { T::decode(&mut &data[..])._factory().build(ctx) }.boxed_local()
|
||||||
}
|
}
|
||||||
fn drop(&self, AtomCtx(buf, _, ctx): AtomCtx) {
|
fn drop<'a>(&'a self, AtomCtx(buf, _, ctx): AtomCtx<'a>) -> LocalBoxFuture<'a, ()> {
|
||||||
let string_self = T::decode(&mut &buf[..]).print(ctx.clone());
|
async move {
|
||||||
writeln!(ctx.logger, "Received drop signal for non-drop atom {string_self:?}");
|
let string_self = T::decode(&mut &buf[..]).print(ctx.clone()).await;
|
||||||
|
writeln!(ctx.logger, "Received drop signal for non-drop atom {string_self:?}");
|
||||||
|
}
|
||||||
|
.boxed_local()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,9 +101,15 @@ pub trait ThinAtom:
|
|||||||
AtomCard<Data = Self> + Atomic<Variant = ThinVariant> + Coding + Send + Sync + 'static
|
AtomCard<Data = Self> + Atomic<Variant = ThinVariant> + Coding + Send + Sync + 'static
|
||||||
{
|
{
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn call(&self, arg: ExprHandle) -> Expr { bot([err_not_callable()]) }
|
fn call(&self, arg: ExprHandle) -> impl Future<Output = Expr> {
|
||||||
|
async { bot([err_not_callable().await]) }
|
||||||
|
}
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn command(&self, ctx: SysCtx) -> OrcRes<Option<Expr>> { Err(err_not_command().into()) }
|
fn command(&self, ctx: SysCtx) -> impl Future<Output = OrcRes<Option<Expr>>> {
|
||||||
|
async { Err(err_not_command().await.into()) }
|
||||||
|
}
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn print(&self, ctx: SysCtx) -> String { format!("ThinAtom({})", type_name::<Self>()) }
|
fn print(&self, ctx: SysCtx) -> impl Future<Output = String> {
|
||||||
|
async { format!("ThinAtom({})", type_name::<Self>()) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use std::future::Future;
|
||||||
|
|
||||||
use orchid_base::error::{OrcErr, OrcRes, mk_err};
|
use orchid_base::error::{OrcErr, OrcRes, mk_err};
|
||||||
use orchid_base::intern;
|
use orchid_base::intern;
|
||||||
use orchid_base::location::Pos;
|
use orchid_base::location::Pos;
|
||||||
@@ -7,16 +9,16 @@ use crate::expr::{Expr, atom, bot};
|
|||||||
use crate::system::downcast_atom;
|
use crate::system::downcast_atom;
|
||||||
|
|
||||||
pub trait TryFromExpr: Sized {
|
pub trait TryFromExpr: Sized {
|
||||||
fn try_from_expr(expr: Expr) -> OrcRes<Self>;
|
fn try_from_expr(expr: Expr) -> impl Future<Output = OrcRes<Self>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFromExpr for Expr {
|
impl TryFromExpr for Expr {
|
||||||
fn try_from_expr(expr: Expr) -> OrcRes<Self> { Ok(expr) }
|
async fn try_from_expr(expr: Expr) -> OrcRes<Self> { Ok(expr) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: TryFromExpr, U: TryFromExpr> TryFromExpr for (T, U) {
|
impl<T: TryFromExpr, U: TryFromExpr> TryFromExpr for (T, U) {
|
||||||
fn try_from_expr(expr: Expr) -> OrcRes<Self> {
|
async fn try_from_expr(expr: Expr) -> OrcRes<Self> {
|
||||||
Ok((T::try_from_expr(expr.clone())?, U::try_from_expr(expr)?))
|
Ok((T::try_from_expr(expr.clone()).await?, U::try_from_expr(expr).await?))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,9 +34,12 @@ async fn err_type(pos: Pos) -> OrcErr {
|
|||||||
|
|
||||||
impl<A: AtomicFeatures> TryFromExpr for TypAtom<'_, A> {
|
impl<A: AtomicFeatures> TryFromExpr for TypAtom<'_, A> {
|
||||||
async fn try_from_expr(expr: Expr) -> OrcRes<Self> {
|
async fn try_from_expr(expr: Expr) -> OrcRes<Self> {
|
||||||
match expr.foreign_atom() {
|
match expr.atom().await {
|
||||||
Err(ex) => Err(err_not_atom(ex.pos.clone()).await.into()),
|
Err(ex) => Err(err_not_atom(ex.data().await.pos.clone()).await.into()),
|
||||||
Ok(f) => match downcast_atom(f) \.map_err(|f| err_type(f.pos).into()),
|
Ok(f) => match downcast_atom(f) {
|
||||||
|
Ok(a) => Ok(a),
|
||||||
|
Err(f) => Err(err_type(f.pos).await.into()),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use async_std::channel::{Receiver, Sender};
|
|||||||
use async_std::sync::Mutex;
|
use async_std::sync::Mutex;
|
||||||
use futures::FutureExt;
|
use futures::FutureExt;
|
||||||
use futures::future::LocalBoxFuture;
|
use futures::future::LocalBoxFuture;
|
||||||
|
use futures::task::LocalSpawn;
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use orchid_api_traits::{Decode, Encode, enc_vec};
|
use orchid_api_traits::{Decode, Encode, enc_vec};
|
||||||
@@ -25,7 +26,7 @@ use substack::Substack;
|
|||||||
|
|
||||||
use crate::api;
|
use crate::api;
|
||||||
use crate::atom::{AtomCtx, AtomDynfo};
|
use crate::atom::{AtomCtx, AtomDynfo};
|
||||||
use crate::atom_owned::OBJ_STORE;
|
use crate::atom_owned::ObjStore;
|
||||||
use crate::fs::VirtFS;
|
use crate::fs::VirtFS;
|
||||||
use crate::lexer::{LexContext, err_cascade, err_not_applicable};
|
use crate::lexer::{LexContext, err_cascade, err_not_applicable};
|
||||||
use crate::macros::{RuleCtx, apply_rule};
|
use crate::macros::{RuleCtx, apply_rule};
|
||||||
@@ -45,11 +46,11 @@ impl ExtensionData {
|
|||||||
pub fn new(name: &'static str, systems: &'static [&'static dyn DynSystemCtor]) -> Self {
|
pub fn new(name: &'static str, systems: &'static [&'static dyn DynSystemCtor]) -> Self {
|
||||||
Self { name, systems }
|
Self { name, systems }
|
||||||
}
|
}
|
||||||
pub fn main(self) { extension_main(self) }
|
// pub fn main(self) { extension_main(self) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum MemberRecord {
|
pub enum MemberRecord {
|
||||||
Gen(Sym, LazyMemberFactory),
|
Gen(Vec<Tok<String>>, LazyMemberFactory),
|
||||||
Res,
|
Res,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,12 +65,7 @@ pub async fn with_atom_record<T>(
|
|||||||
get_sys_ctx: &impl Fn(api::SysId, ReqNot<api::ExtMsgSet>) -> SysCtx,
|
get_sys_ctx: &impl Fn(api::SysId, ReqNot<api::ExtMsgSet>) -> SysCtx,
|
||||||
reqnot: ReqNot<api::ExtMsgSet>,
|
reqnot: ReqNot<api::ExtMsgSet>,
|
||||||
atom: &api::Atom,
|
atom: &api::Atom,
|
||||||
cb: impl for<'c> FnOnce(
|
cb: impl for<'c> FnOnce(Box<dyn AtomDynfo>, SysCtx, api::AtomId, &'c [u8]) -> LocalBoxFuture<'c, T>,
|
||||||
Box<dyn AtomDynfo>,
|
|
||||||
SysCtx,
|
|
||||||
api::AtomId,
|
|
||||||
&'c [u8],
|
|
||||||
) -> LocalBoxFuture<'c, T>,
|
|
||||||
) -> T {
|
) -> T {
|
||||||
let mut data = &atom.data[..];
|
let mut data = &atom.data[..];
|
||||||
let ctx = get_sys_ctx(atom.owner, reqnot);
|
let ctx = get_sys_ctx(atom.owner, reqnot);
|
||||||
@@ -79,17 +75,18 @@ pub async fn with_atom_record<T>(
|
|||||||
cb(atom_record, ctx, id, data).await
|
cb(atom_record, ctx, id, data).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extension_main(data: ExtensionData) {
|
// pub fn extension_main(data: ExtensionData) {
|
||||||
if thread::Builder::new()
|
|
||||||
.name(format!("ext-main:{}", data.name))
|
// if thread::Builder::new()
|
||||||
.spawn(|| extension_main_logic(data))
|
// .name(format!("ext-main:{}", data.name))
|
||||||
.unwrap()
|
// .spawn(|| extension_main_logic(data))
|
||||||
.join()
|
// .unwrap()
|
||||||
.is_err()
|
// .join()
|
||||||
{
|
// .is_err()
|
||||||
process::exit(-1)
|
// {
|
||||||
}
|
// process::exit(-1)
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
pub struct ExtensionOwner {
|
pub struct ExtensionOwner {
|
||||||
rn: ReqNot<api::ExtMsgSet>,
|
rn: ReqNot<api::ExtMsgSet>,
|
||||||
@@ -109,7 +106,7 @@ impl ExtPort for ExtensionOwner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extension_main_logic(data: ExtensionData) {
|
async fn extension_main_logic(data: ExtensionData, spawner: Arc<dyn LocalSpawn>) {
|
||||||
let api::HostHeader { log_strategy } = api::HostHeader::decode(&mut std::io::stdin().lock());
|
let api::HostHeader { log_strategy } = api::HostHeader::decode(&mut std::io::stdin().lock());
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
let decls = (data.systems.iter().enumerate())
|
let decls = (data.systems.iter().enumerate())
|
||||||
@@ -122,11 +119,12 @@ fn extension_main_logic(data: ExtensionData) {
|
|||||||
std::io::stdout().flush().unwrap();
|
std::io::stdout().flush().unwrap();
|
||||||
let exiting = Arc::new(AtomicBool::new(false));
|
let exiting = Arc::new(AtomicBool::new(false));
|
||||||
let logger = Arc::new(Logger::new(log_strategy));
|
let logger = Arc::new(Logger::new(log_strategy));
|
||||||
|
let obj_store = ObjStore::default();
|
||||||
let mk_ctx = clone!(
|
let mk_ctx = clone!(
|
||||||
logger, systems;
|
logger, systems;
|
||||||
move |id: api::SysId, reqnot: ReqNot<api::ExtMsgSet>| async {
|
move |id: api::SysId, reqnot: ReqNot<api::ExtMsgSet>| async {
|
||||||
let cted = systems.lock().await[&id].cted.clone();
|
let cted = systems.lock().await[&id].cted.clone();
|
||||||
SysCtx { id, cted, logger: logger.clone(), reqnot }
|
SysCtx { id, cted, logger, reqnot, spawner, obj_store }
|
||||||
}.boxed_local()
|
}.boxed_local()
|
||||||
);
|
);
|
||||||
let rn = ReqNot::<api::ExtMsgSet>::new(
|
let rn = ReqNot::<api::ExtMsgSet>::new(
|
||||||
@@ -140,200 +138,209 @@ fn extension_main_logic(data: ExtensionData) {
|
|||||||
api::HostExtNotif::SystemDrop(api::SystemDrop(sys_id)) =>
|
api::HostExtNotif::SystemDrop(api::SystemDrop(sys_id)) =>
|
||||||
mem::drop(systems.lock().await.remove(&sys_id)),
|
mem::drop(systems.lock().await.remove(&sys_id)),
|
||||||
api::HostExtNotif::AtomDrop(api::AtomDrop(sys_id, atom)) =>
|
api::HostExtNotif::AtomDrop(api::AtomDrop(sys_id, atom)) =>
|
||||||
OBJ_STORE.get(atom.0).unwrap().remove().dyn_free(mk_ctx(sys_id, reqnot).await),
|
obj_store.get(atom.0).unwrap().remove().dyn_free(mk_ctx(sys_id, reqnot).await).await,
|
||||||
}
|
}
|
||||||
}.boxed_local()),
|
}.boxed_local()),
|
||||||
{
|
{
|
||||||
let systems = systems.clone();
|
let systems = systems.clone();
|
||||||
let logger = logger.clone();
|
let logger = logger.clone();
|
||||||
(move|hand,req|async {
|
(move |hand, req| {
|
||||||
let receipt:Receipt = match req {
|
async {
|
||||||
api::HostExtReq::Ping(ping@api::Ping) => hand.handle(&ping, &()).await,
|
let receipt: Receipt = match req {
|
||||||
api::HostExtReq::Sweep(sweep@api::Sweep) => hand.handle(&sweep, &sweep_replica()).await,
|
api::HostExtReq::Ping(ping @ api::Ping) => hand.handle(&ping, &()).await,
|
||||||
api::HostExtReq::SysReq(api::SysReq::NewSystem(new_sys)) => {
|
_ => panic!(),
|
||||||
let i = decls.iter().enumerate().find(|(_,s)|s.id==new_sys.system).unwrap().0;
|
// api::HostExtReq::Sweep(sweep@api::Sweep) => hand.handle(&sweep,
|
||||||
let cted = data.systems[i].new_system(&new_sys);
|
// &sweep_replica()).await,
|
||||||
let mut vfses = HashMap::new();
|
// api::HostExtReq::SysReq(api::SysReq::NewSystem(new_sys)) => {
|
||||||
let lex_filter = cted.inst().dyn_lexers().iter().fold(api::CharFilter(vec![]), |cf,lx|{
|
// let i = decls.iter().enumerate().find(|(_,s)|s.id==new_sys.system).unwrap().0;
|
||||||
let lxcf = mk_char_filter(lx.char_filter().iter().cloned());
|
// let cted = data.systems[i].new_system(&new_sys);
|
||||||
char_filter_union(&cf, &lxcf)
|
// let mut vfses = HashMap::new();
|
||||||
});
|
// let lex_filter = cted.inst().dyn_lexers().iter().fold(api::CharFilter(vec![]),
|
||||||
let mut lazy_mems = HashMap::new();
|
// |cf,lx|{ let lxcf = mk_char_filter(lx.char_filter().iter().cloned());
|
||||||
let ctx = SysCtx {
|
// char_filter_union(&cf, &lxcf)
|
||||||
cted:cted.clone(),id:new_sys.id,logger:logger.clone(),reqnot:hand.reqnot()
|
// });
|
||||||
};
|
// let mut lazy_mems = HashMap::new();
|
||||||
let mut tia_ctx = TIACtxImpl {
|
// let ctx = SysCtx {
|
||||||
lazy: &mut lazy_mems,sys:ctx.clone(),basepath: &[],path:Substack::Bottom,
|
// cted:cted.clone(),id:new_sys.id,logger:logger.clone(),reqnot:hand.reqnot()
|
||||||
};
|
// };
|
||||||
let const_root = (cted.inst().dyn_env().into_iter()).map(|(k,v)|(k.to_api(),v.into_api(&mut tia_ctx))).collect();
|
// let mut tia_ctx = TIACtxImpl {
|
||||||
systems.lock().unwrap().insert(new_sys.id,SystemRecord {
|
// lazy: &mut lazy_mems,sys:ctx.clone(),basepath: &[],path:Substack::Bottom,
|
||||||
declfs:cted.inst().dyn_vfs().to_api_rec(&mut vfses),vfses,cted,lazy_members:lazy_mems
|
// };
|
||||||
});
|
// let const_root =
|
||||||
hand.handle(&new_sys, &api::SystemInst {
|
// (cted.inst().dyn_env().into_iter()).map(|(k,v)|(k.to_api(),v.into_api(&mut
|
||||||
lex_filter,const_root,line_types:vec![]
|
// tia_ctx))).collect(); systems.lock().unwrap().insert(new_sys.id,
|
||||||
}).await
|
// SystemRecord { declfs:cted.inst().dyn_vfs().to_api_rec(&mut
|
||||||
}
|
// vfses),vfses,cted,lazy_members:lazy_mems });
|
||||||
api::HostExtReq::GetMember(get_tree@api::GetMember(sys_id,tree_id)) => {
|
// hand.handle(&new_sys, &api::SystemInst {
|
||||||
let mut systems_g = systems.lock().unwrap();
|
// lex_filter,const_root,line_types:vec![]
|
||||||
let sys = systems_g.get_mut(&sys_id).expect("System not found");
|
// }).await
|
||||||
let lazy = &mut sys.lazy_members;
|
// }
|
||||||
let(path,cb) = match lazy.insert(tree_id,MemberRecord::Res){
|
// api::HostExtReq::GetMember(get_tree@api::GetMember(sys_id,tree_id)) => {
|
||||||
None => panic!("Tree for ID not found"),
|
// let mut systems_g = systems.lock().unwrap();
|
||||||
Some(MemberRecord::Res) => panic!("This tree has already been transmitted"),
|
// let sys = systems_g.get_mut(&sys_id).expect("System not found");
|
||||||
Some(MemberRecord::Gen(path,cb)) => (path,cb),
|
// let lazy = &mut sys.lazy_members;
|
||||||
|
// let(path,cb) = match lazy.insert(tree_id,MemberRecord::Res){
|
||||||
|
// None => panic!("Tree for ID not found"),
|
||||||
|
// Some(MemberRecord::Res) => panic!("This tree has already been transmitted"),
|
||||||
|
// Some(MemberRecord::Gen(path,cb)) => (path,cb),
|
||||||
|
|
||||||
};
|
// };
|
||||||
let tree = cb.build(path.clone());
|
// let tree = cb.build(path.clone());
|
||||||
hand.handle(&get_tree, &tree.into_api(&mut TIACtxImpl {
|
// hand.handle(&get_tree, &tree.into_api(&mut TIACtxImpl {
|
||||||
sys:SysCtx::new(sys_id, &sys.cted, &logger,hand.reqnot()),path:Substack::Bottom,basepath: &path,lazy,
|
// sys:SysCtx::new(sys_id, &sys.cted,
|
||||||
})).await
|
// &logger,hand.reqnot()),path:Substack::Bottom,basepath: &path,lazy,
|
||||||
}
|
// })).await
|
||||||
api::HostExtReq::VfsReq(api::VfsReq::GetVfs(get_vfs@api::GetVfs(sys_id))) => {
|
// }
|
||||||
let systems_g = systems.lock().unwrap();
|
// api::HostExtReq::VfsReq(api::VfsReq::GetVfs(get_vfs@api::GetVfs(sys_id))) => {
|
||||||
hand.handle(&get_vfs, &systems_g[&sys_id].declfs).await
|
// let systems_g = systems.lock().unwrap();
|
||||||
}
|
// hand.handle(&get_vfs, &systems_g[&sys_id].declfs).await
|
||||||
api::HostExtReq::SysReq(api::SysReq::SysFwded(fwd)) => {
|
// }
|
||||||
let api::SysFwded(sys_id,payload) = fwd;
|
// api::HostExtReq::SysReq(api::SysReq::SysFwded(fwd)) => {
|
||||||
let ctx = mk_ctx(sys_id,hand.reqnot());
|
// let api::SysFwded(sys_id,payload) = fwd;
|
||||||
let sys = ctx.cted.inst();
|
// let ctx = mk_ctx(sys_id,hand.reqnot());
|
||||||
sys.dyn_request(hand,payload)
|
// let sys = ctx.cted.inst();
|
||||||
}
|
// sys.dyn_request(hand,payload)
|
||||||
api::HostExtReq::VfsReq(api::VfsReq::VfsRead(vfs_read)) => {
|
// }
|
||||||
let api::VfsRead(sys_id,vfs_id,path) = &vfs_read;
|
// api::HostExtReq::VfsReq(api::VfsReq::VfsRead(vfs_read)) => {
|
||||||
let systems_g = systems.lock().unwrap();
|
// let api::VfsRead(sys_id,vfs_id,path) = &vfs_read;
|
||||||
let path = path.iter().map(|t|Tok::from_api(*t)).collect_vec();
|
// let systems_g = systems.lock().unwrap();
|
||||||
hand.handle(&vfs_read, &systems_g[sys_id].vfses[vfs_id].load(PathSlice::new(&path))).await
|
// let path = path.iter().map(|t|Tok::from_api(*t)).collect_vec();
|
||||||
}
|
// hand.handle(&vfs_read,
|
||||||
api::HostExtReq::LexExpr(lex@api::LexExpr {
|
// &systems_g[sys_id].vfses[vfs_id].load(PathSlice::new(&path))).await }
|
||||||
sys,text,pos,id
|
// api::HostExtReq::LexExpr(lex@api::LexExpr {
|
||||||
}) => {
|
// sys,text,pos,id
|
||||||
let systems_g = systems.lock().unwrap();
|
// }) => {
|
||||||
let lexers = systems_g[&sys].cted.inst().dyn_lexers();
|
// let systems_g = systems.lock().unwrap();
|
||||||
mem::drop(systems_g);
|
// let lexers = systems_g[&sys].cted.inst().dyn_lexers();
|
||||||
let text = Tok::from_api(text);
|
// mem::drop(systems_g);
|
||||||
let ctx = LexContext {
|
// let text = Tok::from_api(text);
|
||||||
sys,id,pos,reqnot:hand.reqnot(),text: &text
|
// let ctx = LexContext {
|
||||||
};
|
// sys,id,pos,reqnot:hand.reqnot(),text: &text
|
||||||
let trigger_char = text.await.chars().nth(pos as usize).unwrap();
|
// };
|
||||||
for lx in lexers.iter().filter(|l|char_filter_match(l.char_filter(),trigger_char)){
|
// let trigger_char = text.await.chars().nth(pos as usize).unwrap();
|
||||||
match lx.lex(&text[pos as usize..], &ctx){
|
// for lx in
|
||||||
Err(e)if e.any(|e| *e==err_not_applicable()) => continue,
|
// lexers.iter().filter(|l|char_filter_match(l.char_filter(),trigger_char)){
|
||||||
Err(e) => {
|
// match lx.lex(&text[pos as usize..], &ctx){
|
||||||
let eopt = e.keep_only(|e| *e!=err_cascade()).map(|e|Err(e.to_api()));
|
// Err(e)if e.any(|e| *e==err_not_applicable()) => continue,
|
||||||
return hand.handle(&lex, &eopt)
|
// Err(e) => {
|
||||||
},
|
// let eopt = e.keep_only(|e|
|
||||||
Ok((s,expr)) => {
|
// *e!=err_cascade()).map(|e|Err(e.to_api())); return
|
||||||
let ctx = mk_ctx(sys,hand.reqnot());
|
// hand.handle(&lex, &eopt) },
|
||||||
let expr = expr.to_api(&mut |f,r|do_extra(f,r,ctx.clone()));
|
// Ok((s,expr)) => {
|
||||||
let pos = (text.len()-s.len())as u32;
|
// let ctx = mk_ctx(sys,hand.reqnot());
|
||||||
return hand.handle(&lex, &Some(Ok(api::LexedExpr {
|
// let expr = expr.to_api(&mut |f,r|do_extra(f,r,ctx.clone()));
|
||||||
pos,expr
|
// let pos = (text.len()-s.len())as u32;
|
||||||
})))
|
// return hand.handle(&lex, &Some(Ok(api::LexedExpr {
|
||||||
}
|
// pos,expr
|
||||||
|
// })))
|
||||||
|
// }
|
||||||
|
|
||||||
}
|
// }
|
||||||
}writeln!(logger,"Got notified about n/a character '{trigger_char}'");
|
// }writeln!(logger,"Got notified about n/a character '{trigger_char}'");
|
||||||
hand.handle(&lex, &None).await
|
// hand.handle(&lex, &None).await
|
||||||
},
|
// },
|
||||||
api::HostExtReq::ParseLine(pline) => {
|
// api::HostExtReq::ParseLine(pline) => {
|
||||||
let api::ParseLine {
|
// let api::ParseLine {
|
||||||
exported,comments,sys,line
|
// exported,comments,sys,line
|
||||||
} = &pline;
|
// } = &pline;
|
||||||
let mut ctx = mk_ctx(*sys,hand.reqnot());
|
// let mut ctx = mk_ctx(*sys,hand.reqnot());
|
||||||
let parsers = ctx.cted.inst().dyn_parsers();
|
// let parsers = ctx.cted.inst().dyn_parsers();
|
||||||
let comments = comments.iter().map(Comment::from_api).collect();
|
// let comments = comments.iter().map(Comment::from_api).collect();
|
||||||
let line:Vec<GenTokTree> = ttv_from_api(line, &mut ctx);
|
// let line:Vec<GenTokTree> = ttv_from_api(line, &mut ctx);
|
||||||
let snip = Snippet::new(line.first().expect("Empty line"), &line);
|
// let snip = Snippet::new(line.first().expect("Empty line"), &line);
|
||||||
let(head,tail) = snip.pop_front().unwrap();
|
// let(head,tail) = snip.pop_front().unwrap();
|
||||||
let name = if let GenTok::Name(n) = &head.tok {
|
// let name = if let GenTok::Name(n) = &head.tok {
|
||||||
n
|
// n
|
||||||
}else {
|
// }else {
|
||||||
panic!("No line head")
|
// panic!("No line head")
|
||||||
};
|
// };
|
||||||
let parser = parsers.iter().find(|p|p.line_head()== **name).expect("No parser candidate");
|
// let parser = parsers.iter().find(|p|p.line_head()== **name).expect("No parser
|
||||||
let o_line = match parser.parse(*exported,comments,tail){
|
// candidate"); let o_line = match parser.parse(*exported,comments,tail){
|
||||||
Err(e) => Err(e.to_api()),
|
// Err(e) => Err(e.to_api()),
|
||||||
Ok(t) => Ok(ttv_to_api(t, &mut |f,range|{
|
// Ok(t) => Ok(ttv_to_api(t, &mut |f,range|{
|
||||||
api::TokenTree {
|
// api::TokenTree {
|
||||||
range,token:api::Token::Atom(f.clone().build(ctx.clone()))
|
// range,token:api::Token::Atom(f.clone().build(ctx.clone()))
|
||||||
}
|
// }
|
||||||
})),
|
// })),
|
||||||
|
|
||||||
};
|
// };
|
||||||
hand.handle(&pline, &o_line).await
|
// hand.handle(&pline, &o_line).await
|
||||||
}
|
// }
|
||||||
api::HostExtReq::AtomReq(atom_req) => {
|
// api::HostExtReq::AtomReq(atom_req) => {
|
||||||
let atom = atom_req.get_atom();
|
// let atom = atom_req.get_atom();
|
||||||
with_atom_record(&mk_ctx,hand.reqnot(),atom, |nfo,ctx,id,buf|async {
|
// with_atom_record(&mk_ctx,hand.reqnot(),atom, |nfo,ctx,id,buf|async {
|
||||||
let actx = AtomCtx(buf,atom.drop,ctx.clone());
|
// let actx = AtomCtx(buf,atom.drop,ctx.clone());
|
||||||
match&atom_req {
|
// match&atom_req {
|
||||||
api::AtomReq::SerializeAtom(ser) => {
|
// api::AtomReq::SerializeAtom(ser) => {
|
||||||
let mut buf = enc_vec(&id);
|
// let mut buf = enc_vec(&id);
|
||||||
let refs_opt = nfo.serialize(actx, &mut buf);
|
// let refs_opt = nfo.serialize(actx, &mut buf);
|
||||||
hand.handle(ser, &refs_opt.map(|refs|(buf,refs))),await
|
// hand.handle(ser, &refs_opt.map(|refs|(buf,refs))),await
|
||||||
}
|
// }
|
||||||
api::AtomReq::AtomPrint(print@api::AtomPrint(_)) => hand.handle(print, &nfo.print(actx)).await,
|
// api::AtomReq::AtomPrint(print@api::AtomPrint(_)) => hand.handle(print,
|
||||||
api::AtomReq::Fwded(fwded) => {
|
// &nfo.print(actx)).await, api::AtomReq::Fwded(fwded) => {
|
||||||
let api::Fwded(_,key,payload) = &fwded;
|
// let api::Fwded(_,key,payload) = &fwded;
|
||||||
let mut reply = Vec::new();
|
// let mut reply = Vec::new();
|
||||||
let some = nfo.handle_req(actx,Sym::from_api(*key), &mut &payload[..], &mut reply);
|
// let some = nfo.handle_req(actx,Sym::from_api(*key), &mut
|
||||||
hand.handle(fwded, &some.then_some(reply)).await
|
// &payload[..], &mut reply); hand.handle(fwded,
|
||||||
}
|
// &some.then_some(reply)).await }
|
||||||
api::AtomReq::CallRef(call@api::CallRef(_,arg)) => {
|
// api::AtomReq::CallRef(call@api::CallRef(_,arg)) => {
|
||||||
let ret = nfo.call_ref(actx, *arg);
|
// let ret = nfo.call_ref(actx, *arg);
|
||||||
hand.handle(call, &ret.api_return(ctx.clone(), &mut |h|hand.defer_drop(h))).await
|
// hand.handle(call, &ret.api_return(ctx.clone(), &mut
|
||||||
},
|
// |h|hand.defer_drop(h))).await },
|
||||||
api::AtomReq::FinalCall(call@api::FinalCall(_,arg)) => {
|
// api::AtomReq::FinalCall(call@api::FinalCall(_,arg)) => {
|
||||||
let ret = nfo.call(actx, *arg);
|
// let ret = nfo.call(actx, *arg);
|
||||||
hand.handle(call, &ret.api_return(ctx.clone(), &mut |h|hand.defer_drop(h))).await
|
// hand.handle(call, &ret.api_return(ctx.clone(), &mut
|
||||||
}
|
// |h|hand.defer_drop(h))).await }
|
||||||
api::AtomReq::Command(cmd@api::Command(_)) => {
|
// api::AtomReq::Command(cmd@api::Command(_)) => {
|
||||||
hand.handle(cmd, &match nfo.command(actx){
|
// hand.handle(cmd, &match nfo.command(actx){
|
||||||
Err(e) => Err(e.to_api()),
|
// Err(e) => Err(e.to_api()),
|
||||||
Ok(opt) => Ok(match opt {
|
// Ok(opt) => Ok(match opt {
|
||||||
None => api::NextStep::Halt,
|
// None => api::NextStep::Halt,
|
||||||
Some(cont) => api::NextStep::Continue(cont.api_return(ctx.clone(), &mut |h|hand.defer_drop(h))),
|
// Some(cont) =>
|
||||||
|
// api::NextStep::Continue(cont.api_return(ctx.clone(), &mut |h|hand.defer_drop(h))),
|
||||||
|
|
||||||
})
|
// })
|
||||||
|
|
||||||
}).await
|
// }).await
|
||||||
}
|
// }
|
||||||
|
|
||||||
}
|
// }
|
||||||
}).await
|
// }).await
|
||||||
},
|
// },
|
||||||
api::HostExtReq::DeserAtom(deser) => {
|
// api::HostExtReq::DeserAtom(deser) => {
|
||||||
let api::DeserAtom(sys,buf,refs) = &deser;
|
// let api::DeserAtom(sys,buf,refs) = &deser;
|
||||||
let mut read = &mut &buf[..];
|
// let mut read = &mut &buf[..];
|
||||||
let ctx = mk_ctx(*sys,hand.reqnot());
|
// let ctx = mk_ctx(*sys,hand.reqnot());
|
||||||
let id = api::AtomId::decode(&mut read);
|
// let id = api::AtomId::decode(&mut read);
|
||||||
let inst = ctx.cted.inst();
|
// let inst = ctx.cted.inst();
|
||||||
let nfo = atom_by_idx(inst.card(),id).expect("Deserializing atom with invalid ID");
|
// let nfo = atom_by_idx(inst.card(),id).expect("Deserializing atom with invalid
|
||||||
hand.handle(&deser, &nfo.deserialize(ctx.clone(),read,refs)).await
|
// ID"); hand.handle(&deser, &nfo.deserialize(ctx.clone(),read,refs)).await
|
||||||
},
|
// },
|
||||||
orchid_api::HostExtReq::ApplyMacro(am) => {
|
// orchid_api::HostExtReq::ApplyMacro(am) => {
|
||||||
let tok = hand.will_handle_as(&am);
|
// let tok = hand.will_handle_as(&am);
|
||||||
let sys_ctx = mk_ctx(am.sys,hand.reqnot());
|
// let sys_ctx = mk_ctx(am.sys,hand.reqnot());
|
||||||
let ctx = RuleCtx {
|
// let ctx = RuleCtx {
|
||||||
args:(am.params.into_iter()).map(|(k,v)|(Tok::from_api(k),mtreev_from_api(&v, &mut |_|panic!("No atom in macro prompt!")))).collect(),run_id:am.run_id,sys:sys_ctx.clone(),
|
// args:(am.params.into_iter()).map(|(k,v)|(Tok::from_api(k),mtreev_from_api(&v,
|
||||||
};
|
// &mut |_|panic!("No atom in macro
|
||||||
hand.handle_as(tok, &match apply_rule(am.id,ctx){
|
// prompt!")))).collect(),run_id:am.run_id,sys:sys_ctx.clone(), };
|
||||||
Err(e) => e.keep_only(|e| *e!=err_cascade()).map(|e|Err(e.to_api())),
|
// hand.handle_as(tok, &match apply_rule(am.id,ctx){
|
||||||
Ok(t) => Some(Ok(mtreev_to_api(&t, &mut |a|{
|
// Err(e) => e.keep_only(|e| *e!=err_cascade()).map(|e|Err(e.to_api())),
|
||||||
api::MacroToken::Atom(a.clone().build(sys_ctx.clone()))
|
// Ok(t) => Some(Ok(mtreev_to_api(&t, &mut |a|{
|
||||||
}))),
|
// api::MacroToken::Atom(a.clone().build(sys_ctx.clone()))
|
||||||
|
// }))),
|
||||||
|
|
||||||
}).await
|
// }).await
|
||||||
}
|
// }
|
||||||
|
};
|
||||||
};
|
receipt
|
||||||
receipt
|
}
|
||||||
}.boxed_local())
|
.boxed_local()
|
||||||
},
|
})
|
||||||
|
},
|
||||||
);
|
);
|
||||||
init_replica(rn.clone().map());
|
init_replica(rn.clone().map());
|
||||||
while !exiting.load(Ordering::Relaxed) {
|
while !exiting.load(Ordering::Relaxed) {
|
||||||
let rcvd = recv_parent_msg().unwrap();
|
let rcvd = recv_parent_msg().await.unwrap();
|
||||||
rn.receive(&rcvd)
|
rn.receive(&rcvd).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ops::Deref;
|
use std::sync::Arc;
|
||||||
use std::sync::{Arc, OnceLock};
|
|
||||||
|
|
||||||
|
use async_once_cell::OnceCell;
|
||||||
use derive_destructure::destructure;
|
use derive_destructure::destructure;
|
||||||
|
use futures::task::LocalSpawnExt;
|
||||||
use orchid_base::error::{OrcErr, OrcErrv};
|
use orchid_base::error::{OrcErr, OrcErrv};
|
||||||
use orchid_base::interner::Tok;
|
use orchid_base::interner::Tok;
|
||||||
use orchid_base::location::Pos;
|
use orchid_base::location::Pos;
|
||||||
@@ -35,33 +36,44 @@ impl Clone for ExprHandle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Drop for ExprHandle {
|
impl Drop for ExprHandle {
|
||||||
fn drop(&mut self) { self.ctx.reqnot.notify(api::Release(self.ctx.id, self.tk)) }
|
fn drop(&mut self) {
|
||||||
|
let notif = api::Release(self.ctx.id, self.tk);
|
||||||
|
let SysCtx { reqnot, spawner, logger, .. } = self.ctx.clone();
|
||||||
|
if let Err(e) = spawner.spawn_local(async move { reqnot.notify(notif).await }) {
|
||||||
|
writeln!(logger, "Failed to schedule notification about resource release: {e}");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, destructure)]
|
#[derive(Clone, Debug, destructure)]
|
||||||
pub struct Expr {
|
pub struct Expr {
|
||||||
pub handle: Option<Arc<ExprHandle>>,
|
handle: Option<Arc<ExprHandle>>,
|
||||||
pub val: OnceLock<ExprData>,
|
data: Arc<OnceCell<ExprData>>,
|
||||||
}
|
}
|
||||||
impl Expr {
|
impl Expr {
|
||||||
pub fn new(hand: Arc<ExprHandle>) -> Self { Self { handle: Some(hand), val: OnceLock::new() } }
|
pub fn new(h: Arc<ExprHandle>, d: ExprData) -> Self {
|
||||||
pub fn from_data(val: ExprData) -> Self { Self { handle: None, val: OnceLock::from(val) } }
|
Self { handle: Some(h), data: Arc::new(OnceCell::from(d)) }
|
||||||
pub fn get_data(&self) -> &ExprData {
|
}
|
||||||
self.val.get_or_init(|| {
|
pub fn from_handle(h: Arc<ExprHandle>) -> Self { Self { handle: Some(h), data: Arc::default() } }
|
||||||
|
pub fn from_data(d: ExprData) -> Self { Self { handle: None, data: Arc::new(OnceCell::from(d)) } }
|
||||||
|
|
||||||
|
pub async fn data(&self) -> &ExprData {
|
||||||
|
(self.data.get_or_init(async {
|
||||||
let handle = self.handle.as_ref().expect("Either the value or the handle must be set");
|
let handle = self.handle.as_ref().expect("Either the value or the handle must be set");
|
||||||
let details = handle.ctx.reqnot.request(api::Inspect { target: handle.tk });
|
let details = handle.ctx.reqnot.request(api::Inspect { target: handle.tk }).await;
|
||||||
let pos = Pos::from_api(&details.location);
|
let pos = Pos::from_api(&details.location).await;
|
||||||
let kind = match details.kind {
|
let kind = match details.kind {
|
||||||
api::InspectedKind::Atom(a) =>
|
api::InspectedKind::Atom(a) =>
|
||||||
ExprKind::Atom(ForeignAtom::new(handle.clone(), a, pos.clone())),
|
ExprKind::Atom(ForeignAtom::new(handle.clone(), a, pos.clone())),
|
||||||
api::InspectedKind::Bottom(b) => ExprKind::Bottom(OrcErrv::from_api(&b)),
|
api::InspectedKind::Bottom(b) => ExprKind::Bottom(OrcErrv::from_api(&b).await),
|
||||||
api::InspectedKind::Opaque => ExprKind::Opaque,
|
api::InspectedKind::Opaque => ExprKind::Opaque,
|
||||||
};
|
};
|
||||||
ExprData { pos, kind }
|
ExprData { pos, kind }
|
||||||
})
|
}))
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
pub fn foreign_atom(self) -> Result<ForeignAtom<'static>, Self> {
|
pub async fn atom(self) -> Result<ForeignAtom<'static>, Self> {
|
||||||
match (self.get_data(), &self.handle) {
|
match (self.data().await, &self.handle) {
|
||||||
(ExprData { kind: ExprKind::Atom(atom), .. }, Some(_)) => Ok(atom.clone()),
|
(ExprData { kind: ExprKind::Atom(atom), .. }, Some(_)) => Ok(atom.clone()),
|
||||||
_ => Err(self),
|
_ => Err(self),
|
||||||
}
|
}
|
||||||
@@ -75,15 +87,12 @@ impl Expr {
|
|||||||
do_slot(h.clone());
|
do_slot(h.clone());
|
||||||
api::Expression { location: api::Location::SlotTarget, kind: api::ExpressionKind::Slot(h.tk) }
|
api::Expression { location: api::Location::SlotTarget, kind: api::ExpressionKind::Slot(h.tk) }
|
||||||
} else {
|
} else {
|
||||||
self.val.into_inner().expect("Either value or handle must be set").api_return(ctx, do_slot)
|
let data = self.data.get().expect("Either value or handle must be set");
|
||||||
|
data.clone().api_return(ctx, do_slot)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn handle(&self) -> Option<Arc<ExprHandle>> { self.handle.clone() }
|
pub fn handle(&self) -> Option<Arc<ExprHandle>> { self.handle.clone() }
|
||||||
}
|
}
|
||||||
impl Deref for Expr {
|
|
||||||
type Target = ExprData;
|
|
||||||
fn deref(&self) -> &Self::Target { self.get_data() }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct ExprData {
|
pub struct ExprData {
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
|
use std::future::{Future, ready};
|
||||||
use std::num::NonZero;
|
use std::num::NonZero;
|
||||||
|
|
||||||
|
use futures::FutureExt;
|
||||||
|
use futures::future::{join, join_all};
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use orchid_base::interner::intern;
|
use orchid_base::interner::intern;
|
||||||
use orchid_base::name::PathSlice;
|
use orchid_base::name::PathSlice;
|
||||||
@@ -15,17 +18,27 @@ pub enum DeclFs {
|
|||||||
Mod(&'static [(&'static str, DeclFs)]),
|
Mod(&'static [(&'static str, DeclFs)]),
|
||||||
}
|
}
|
||||||
impl DeclFs {
|
impl DeclFs {
|
||||||
pub fn to_api_rec(&self, vfses: &mut HashMap<api::VfsId, &'static dyn VirtFS>) -> api::EagerVfs {
|
pub fn to_api_rec(
|
||||||
|
&self,
|
||||||
|
vfses: &mut HashMap<api::VfsId, &'static dyn VirtFS>,
|
||||||
|
) -> impl Future<Output = api::EagerVfs> + '_ {
|
||||||
match self {
|
match self {
|
||||||
DeclFs::Lazy(fs) => {
|
DeclFs::Lazy(fs) => {
|
||||||
let vfsc: u16 = vfses.len().try_into().expect("too many vfses (more than u16::MAX)");
|
let vfsc: u16 = vfses.len().try_into().expect("too many vfses (more than u16::MAX)");
|
||||||
let id = api::VfsId(NonZero::new(vfsc + 1).unwrap());
|
let id = api::VfsId(NonZero::new(vfsc + 1).unwrap());
|
||||||
vfses.insert(id, *fs);
|
vfses.insert(id, *fs);
|
||||||
api::EagerVfs::Lazy(id)
|
ready(api::EagerVfs::Lazy(id)).boxed_local()
|
||||||
|
},
|
||||||
|
DeclFs::Mod(children) => {
|
||||||
|
let promises: Vec<_> =
|
||||||
|
children.iter().map(|(k, v)| join(intern(*k), v.to_api_rec(vfses))).collect();
|
||||||
|
async {
|
||||||
|
api::EagerVfs::Eager(
|
||||||
|
join_all(promises).await.into_iter().map(|(k, v)| (k.to_api(), v)).collect(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.boxed_local()
|
||||||
},
|
},
|
||||||
DeclFs::Mod(children) => api::EagerVfs::Eager(
|
|
||||||
children.iter().map(|(k, v)| (intern(*k).to_api(), v.to_api_rec(vfses))).collect(),
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,17 @@
|
|||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::future::Future;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
|
use futures::FutureExt;
|
||||||
|
use futures::future::LocalBoxFuture;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use never::Never;
|
use never::Never;
|
||||||
use orchid_api_traits::Encode;
|
use orchid_api_traits::Encode;
|
||||||
|
use orchid_base::clone;
|
||||||
use orchid_base::error::OrcRes;
|
use orchid_base::error::OrcRes;
|
||||||
use orchid_base::interner::Tok;
|
|
||||||
use orchid_base::name::Sym;
|
use orchid_base::name::Sym;
|
||||||
use trait_set::trait_set;
|
use trait_set::trait_set;
|
||||||
|
|
||||||
@@ -19,12 +22,12 @@ use crate::expr::{Expr, ExprHandle};
|
|||||||
use crate::system::SysCtx;
|
use crate::system::SysCtx;
|
||||||
|
|
||||||
trait_set! {
|
trait_set! {
|
||||||
trait FunCB = Fn(Vec<Expr>) -> OrcRes<Expr> + Send + Sync + 'static;
|
trait FunCB = Fn(Vec<Expr>) -> LocalBoxFuture<'static, OrcRes<Expr>> + Send + Sync + 'static;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ExprFunc<I, O>: Clone + Send + Sync + 'static {
|
pub trait ExprFunc<I, O>: Clone + Send + Sync + 'static {
|
||||||
const ARITY: u8;
|
const ARITY: u8;
|
||||||
fn apply(&self, v: Vec<Expr>) -> OrcRes<Expr>;
|
fn apply(&self, v: Vec<Expr>) -> impl Future<Output = OrcRes<Expr>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
@@ -49,7 +52,7 @@ impl Fun {
|
|||||||
let fun = if let Some(x) = fung.get(&path) {
|
let fun = if let Some(x) = fung.get(&path) {
|
||||||
x.1.clone()
|
x.1.clone()
|
||||||
} else {
|
} else {
|
||||||
let fun = Arc::new(move |v| f.apply(v));
|
let fun = Arc::new(move |v| clone!(f; async move { f.apply(v).await }.boxed_local()));
|
||||||
fung.insert(path.clone(), (F::ARITY, fun.clone()));
|
fung.insert(path.clone(), (F::ARITY, fun.clone()));
|
||||||
fun
|
fun
|
||||||
};
|
};
|
||||||
@@ -63,23 +66,24 @@ impl Atomic for Fun {
|
|||||||
}
|
}
|
||||||
impl OwnedAtom for Fun {
|
impl OwnedAtom for Fun {
|
||||||
type Refs = Vec<Expr>;
|
type Refs = Vec<Expr>;
|
||||||
fn val(&self) -> Cow<'_, Self::Data> { Cow::Owned(()) }
|
async fn val(&self) -> Cow<'_, Self::Data> { Cow::Owned(()) }
|
||||||
fn call_ref(&self, arg: ExprHandle) -> Expr {
|
async fn call_ref(&self, arg: ExprHandle) -> Expr {
|
||||||
let new_args = self.args.iter().cloned().chain([Expr::new(Arc::new(arg))]).collect_vec();
|
let new_args =
|
||||||
|
self.args.iter().cloned().chain([Expr::from_handle(Arc::new(arg))]).collect_vec();
|
||||||
if new_args.len() == self.arity.into() {
|
if new_args.len() == self.arity.into() {
|
||||||
(self.fun)(new_args).to_expr()
|
(self.fun)(new_args).await.to_expr()
|
||||||
} else {
|
} else {
|
||||||
Self { args: new_args, arity: self.arity, fun: self.fun.clone(), path: self.path.clone() }
|
Self { args: new_args, arity: self.arity, fun: self.fun.clone(), path: self.path.clone() }
|
||||||
.to_expr()
|
.to_expr()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn call(self, arg: ExprHandle) -> Expr { self.call_ref(arg) }
|
async fn call(self, arg: ExprHandle) -> Expr { self.call_ref(arg).await }
|
||||||
fn serialize(&self, _: SysCtx, sink: &mut (impl io::Write + ?Sized)) -> Self::Refs {
|
async fn serialize(&self, _: SysCtx, sink: &mut (impl io::Write + ?Sized)) -> Self::Refs {
|
||||||
self.path.encode(sink);
|
self.path.to_api().encode(sink);
|
||||||
self.args.clone()
|
self.args.clone()
|
||||||
}
|
}
|
||||||
fn deserialize(ctx: impl DeserializeCtx, args: Self::Refs) -> Self {
|
async fn deserialize(ctx: impl DeserializeCtx, args: Self::Refs) -> Self {
|
||||||
let path = Sym::new(ctx.decode::<Vec<Tok<String>>>()).unwrap();
|
let path = Sym::from_api(ctx.decode()).await;
|
||||||
let (arity, fun) = FUNS.lock().unwrap().get(&path).unwrap().clone();
|
let (arity, fun) = FUNS.lock().unwrap().get(&path).unwrap().clone();
|
||||||
Self { args, arity, path, fun }
|
Self { args, arity, path, fun }
|
||||||
}
|
}
|
||||||
@@ -97,7 +101,7 @@ pub struct Lambda {
|
|||||||
}
|
}
|
||||||
impl Lambda {
|
impl Lambda {
|
||||||
pub fn new<I, O, F: ExprFunc<I, O>>(f: F) -> Self {
|
pub fn new<I, O, F: ExprFunc<I, O>>(f: F) -> Self {
|
||||||
let fun = Arc::new(move |v| f.apply(v));
|
let fun = Arc::new(move |v| clone!(f; async move { f.apply(v).await }.boxed_local()));
|
||||||
Self { args: vec![], arity: F::ARITY, fun }
|
Self { args: vec![], arity: F::ARITY, fun }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -108,16 +112,17 @@ impl Atomic for Lambda {
|
|||||||
}
|
}
|
||||||
impl OwnedAtom for Lambda {
|
impl OwnedAtom for Lambda {
|
||||||
type Refs = Never;
|
type Refs = Never;
|
||||||
fn val(&self) -> Cow<'_, Self::Data> { Cow::Owned(()) }
|
async fn val(&self) -> Cow<'_, Self::Data> { Cow::Owned(()) }
|
||||||
fn call_ref(&self, arg: ExprHandle) -> Expr {
|
async fn call_ref(&self, arg: ExprHandle) -> Expr {
|
||||||
let new_args = self.args.iter().cloned().chain([Expr::new(Arc::new(arg))]).collect_vec();
|
let new_args =
|
||||||
|
self.args.iter().cloned().chain([Expr::from_handle(Arc::new(arg))]).collect_vec();
|
||||||
if new_args.len() == self.arity.into() {
|
if new_args.len() == self.arity.into() {
|
||||||
(self.fun)(new_args).to_expr()
|
(self.fun)(new_args).await.to_expr()
|
||||||
} else {
|
} else {
|
||||||
Self { args: new_args, arity: self.arity, fun: self.fun.clone() }.to_expr()
|
Self { args: new_args, arity: self.arity, fun: self.fun.clone() }.to_expr()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn call(self, arg: ExprHandle) -> Expr { self.call_ref(arg) }
|
async fn call(self, arg: ExprHandle) -> Expr { self.call_ref(arg).await }
|
||||||
}
|
}
|
||||||
|
|
||||||
mod expr_func_derives {
|
mod expr_func_derives {
|
||||||
@@ -136,10 +141,10 @@ mod expr_func_derives {
|
|||||||
Func: Fn($($t,)*) -> Out + Clone + Send + Sync + 'static
|
Func: Fn($($t,)*) -> Out + Clone + Send + Sync + 'static
|
||||||
> ExprFunc<($($t,)*), Out> for Func {
|
> ExprFunc<($($t,)*), Out> for Func {
|
||||||
const ARITY: u8 = $arity;
|
const ARITY: u8 = $arity;
|
||||||
fn apply(&self, v: Vec<Expr>) -> OrcRes<Expr> {
|
async fn apply(&self, v: Vec<Expr>) -> OrcRes<Expr> {
|
||||||
assert_eq!(v.len(), Self::ARITY.into(), "Arity mismatch");
|
assert_eq!(v.len(), Self::ARITY.into(), "Arity mismatch");
|
||||||
let [$([< $t:lower >],)*] = v.try_into().unwrap_or_else(|_| panic!("Checked above"));
|
let [$([< $t:lower >],)*] = v.try_into().unwrap_or_else(|_| panic!("Checked above"));
|
||||||
Ok(self($($t::try_from_expr([< $t:lower >])?,)*).to_expr())
|
Ok(self($($t::try_from_expr([< $t:lower >]).await?,)*).to_expr())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,10 +36,11 @@ pub struct LexContext<'a> {
|
|||||||
pub reqnot: ReqNot<api::ExtMsgSet>,
|
pub reqnot: ReqNot<api::ExtMsgSet>,
|
||||||
}
|
}
|
||||||
impl<'a> LexContext<'a> {
|
impl<'a> LexContext<'a> {
|
||||||
pub fn recurse(&self, tail: &'a str) -> OrcRes<(&'a str, GenTokTree<'a>)> {
|
pub async fn recurse(&self, tail: &'a str) -> OrcRes<(&'a str, GenTokTree<'a>)> {
|
||||||
let start = self.pos(tail);
|
let start = self.pos(tail);
|
||||||
let lx =
|
let Some(lx) = self.reqnot.request(api::SubLex { pos: start, id: self.id }).await else {
|
||||||
self.reqnot.request(api::SubLex { pos: start, id: self.id }).ok_or_else(err_cascade)?;
|
return Err(err_cascade().await.into());
|
||||||
|
};
|
||||||
Ok((&self.text[lx.pos as usize..], GenTok::Slot(TokHandle::new(lx.ticket)).at(start..lx.pos)))
|
Ok((&self.text[lx.pos as usize..], GenTok::Slot(TokHandle::new(lx.ticket)).at(start..lx.pos)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ use std::num::NonZero;
|
|||||||
use std::sync::RwLock;
|
use std::sync::RwLock;
|
||||||
|
|
||||||
use ahash::HashMap;
|
use ahash::HashMap;
|
||||||
|
use futures::future::join_all;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use never::Never;
|
use never::Never;
|
||||||
use orchid_base::error::OrcRes;
|
use orchid_base::error::OrcRes;
|
||||||
@@ -40,12 +41,13 @@ pub struct RuleCtx<'a> {
|
|||||||
pub(crate) sys: SysCtx,
|
pub(crate) sys: SysCtx,
|
||||||
}
|
}
|
||||||
impl<'a> RuleCtx<'a> {
|
impl<'a> RuleCtx<'a> {
|
||||||
pub fn recurse(&mut self, tree: &[MTree<'a, Never>]) -> OrcRes<Vec<MTree<'a, Never>>> {
|
pub async fn recurse(&mut self, tree: &[MTree<'a, Never>]) -> OrcRes<Vec<MTree<'a, Never>>> {
|
||||||
let req =
|
let req =
|
||||||
api::RunMacros { run_id: self.run_id, query: mtreev_to_api(tree, &mut |b| match *b {}) };
|
api::RunMacros { run_id: self.run_id, query: mtreev_to_api(tree, &mut |b| match *b {}) };
|
||||||
Ok(mtreev_from_api(&self.sys.reqnot.request(req).ok_or_else(err_cascade)?, &mut |_| {
|
let Some(treev) = self.sys.reqnot.request(req).await else {
|
||||||
panic!("Returned atom from Rule recursion")
|
return Err(err_cascade().await.into());
|
||||||
}))
|
};
|
||||||
|
Ok(mtreev_from_api(&treev, &mut |_| panic!("Returned atom from Rule recursion")).await)
|
||||||
}
|
}
|
||||||
pub fn getv(&mut self, key: &Tok<String>) -> Vec<MTree<'a, Never>> {
|
pub fn getv(&mut self, key: &Tok<String>) -> Vec<MTree<'a, Never>> {
|
||||||
self.args.remove(key).expect("Key not found")
|
self.args.remove(key).expect("Key not found")
|
||||||
@@ -86,7 +88,7 @@ impl Rule {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rule_cmt<'a>(
|
pub async fn rule_cmt<'a>(
|
||||||
cmt: impl IntoIterator<Item = &'a str>,
|
cmt: impl IntoIterator<Item = &'a str>,
|
||||||
pattern: Vec<MTree<'static, Never>>,
|
pattern: Vec<MTree<'static, Never>>,
|
||||||
apply: impl RuleCB + 'static,
|
apply: impl RuleCB + 'static,
|
||||||
@@ -94,12 +96,15 @@ pub fn rule_cmt<'a>(
|
|||||||
let mut rules = RULES.write().unwrap();
|
let mut rules = RULES.write().unwrap();
|
||||||
let id = api::MacroId(NonZero::new(rules.len() as u64 + 1).unwrap());
|
let id = api::MacroId(NonZero::new(rules.len() as u64 + 1).unwrap());
|
||||||
rules.insert(id, Box::new(apply));
|
rules.insert(id, Box::new(apply));
|
||||||
let comments = cmt.into_iter().map(|s| Comment { pos: Pos::Inherit, text: intern(s) }).collect();
|
let comments = join_all(
|
||||||
|
cmt.into_iter().map(|s| async { Comment { pos: Pos::Inherit, text: intern(s).await } }),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
Rule { comments, pattern, id }
|
Rule { comments, pattern, id }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rule(pattern: Vec<MTree<'static, Never>>, apply: impl RuleCB + 'static) -> Rule {
|
pub async fn rule(pattern: Vec<MTree<'static, Never>>, apply: impl RuleCB + 'static) -> Rule {
|
||||||
rule_cmt([], pattern, apply)
|
rule_cmt([], pattern, apply).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn apply_rule(
|
pub(crate) fn apply_rule(
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
thread 'main' panicked at /rust/deps/annotate-snippets-0.9.2/src/display_list/from_snippet.rs:275:9:
|
|
||||||
SourceAnnotation range `(100, 102)` is bigger than source length `101`
|
|
||||||
stack backtrace:
|
|
||||||
0: 0x7b98e2f6d725 - std::backtrace::Backtrace::create::hea54461184d28e5c
|
|
||||||
1: 0x7b98e14e0cb5 - std::backtrace::Backtrace::force_capture::h50ac56ebac4f2900
|
|
||||||
2: 0x7b98e065b0e0 - std[dd93a93a14cc3e06]::panicking::update_hook::<alloc[634825797b513591]::boxed::Box<rustc_driver_impl[c64f1141ed92455f]::install_ice_hook::{closure#1}>>::{closure#0}
|
|
||||||
3: 0x7b98e14f9623 - std::panicking::rust_panic_with_hook::hdfd8e9403702a2d1
|
|
||||||
4: 0x7b98e14f931a - std::panicking::begin_panic_handler::{{closure}}::h47998eb7cec3c619
|
|
||||||
5: 0x7b98e14f6ce9 - std::sys::backtrace::__rust_end_short_backtrace::h51610b4899330428
|
|
||||||
6: 0x7b98e14f8fdd - rust_begin_unwind
|
|
||||||
7: 0x7b98de1a6b10 - core::panicking::panic_fmt::h76c97b2053f3e171
|
|
||||||
8: 0x5a2f48927da0 - <annotate_snippets[7516fd2ac470cd96]::display_list::structs::DisplayList as core[369bcca9ba44f16b]::convert::From<annotate_snippets[7516fd2ac470cd96]::snippet::Snippet>>::from
|
|
||||||
9: 0x5a2f48753db4 - <rustfmt_nightly[fdba9bd7d028ddaf]::format_report_formatter::FormatReportFormatter as core[369bcca9ba44f16b]::fmt::Display>::fmt
|
|
||||||
10: 0x7b98e1c12d66 - core::fmt::write::hbdbaf54d653bfdc0
|
|
||||||
11: 0x7b98e14ea90e - <&std::io::stdio::Stderr as std::io::Write>::write_fmt::h297671288300128f
|
|
||||||
12: 0x7b98e14eb2d8 - std::io::stdio::_eprint::hc00582a539350b14
|
|
||||||
13: 0x5a2f4864df33 - rustfmt[d1e716a5735454ec]::format_and_emit_report::<std[dd93a93a14cc3e06]::io::stdio::Stdout>
|
|
||||||
14: 0x5a2f4864c99f - rustfmt[d1e716a5735454ec]::execute
|
|
||||||
15: 0x5a2f48647943 - rustfmt[d1e716a5735454ec]::main
|
|
||||||
16: 0x5a2f4863be73 - std[dd93a93a14cc3e06]::sys::backtrace::__rust_begin_short_backtrace::<fn(), ()>
|
|
||||||
17: 0x5a2f4863c3f9 - std[dd93a93a14cc3e06]::rt::lang_start::<()>::{closure#0}
|
|
||||||
18: 0x7b98e2a77ade - std::rt::lang_start_internal::h1d6a430fc18f5497
|
|
||||||
19: 0x5a2f4864ef98 - main
|
|
||||||
20: 0x7b98dce34e08 - <unknown>
|
|
||||||
21: 0x7b98dce34ecc - __libc_start_main
|
|
||||||
22: 0x5a2f4862f6c9 - <unknown>
|
|
||||||
23: 0x0 - <unknown>
|
|
||||||
|
|
||||||
|
|
||||||
rustc version: 1.86.0-nightly (419b3e2d3 2025-01-15)
|
|
||||||
platform: x86_64-unknown-linux-gnu
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
thread 'main' panicked at /rust/deps/annotate-snippets-0.9.2/src/display_list/from_snippet.rs:275:9:
|
|
||||||
SourceAnnotation range `(100, 102)` is bigger than source length `101`
|
|
||||||
stack backtrace:
|
|
||||||
0: 0x7769ba36d725 - std::backtrace::Backtrace::create::hea54461184d28e5c
|
|
||||||
1: 0x7769b88e0cb5 - std::backtrace::Backtrace::force_capture::h50ac56ebac4f2900
|
|
||||||
2: 0x7769b7a5b0e0 - std[dd93a93a14cc3e06]::panicking::update_hook::<alloc[634825797b513591]::boxed::Box<rustc_driver_impl[c64f1141ed92455f]::install_ice_hook::{closure#1}>>::{closure#0}
|
|
||||||
3: 0x7769b88f9623 - std::panicking::rust_panic_with_hook::hdfd8e9403702a2d1
|
|
||||||
4: 0x7769b88f931a - std::panicking::begin_panic_handler::{{closure}}::h47998eb7cec3c619
|
|
||||||
5: 0x7769b88f6ce9 - std::sys::backtrace::__rust_end_short_backtrace::h51610b4899330428
|
|
||||||
6: 0x7769b88f8fdd - rust_begin_unwind
|
|
||||||
7: 0x7769b55a6b10 - core::panicking::panic_fmt::h76c97b2053f3e171
|
|
||||||
8: 0x5c922ea84da0 - <annotate_snippets[7516fd2ac470cd96]::display_list::structs::DisplayList as core[369bcca9ba44f16b]::convert::From<annotate_snippets[7516fd2ac470cd96]::snippet::Snippet>>::from
|
|
||||||
9: 0x5c922e8b0db4 - <rustfmt_nightly[fdba9bd7d028ddaf]::format_report_formatter::FormatReportFormatter as core[369bcca9ba44f16b]::fmt::Display>::fmt
|
|
||||||
10: 0x7769b9012d66 - core::fmt::write::hbdbaf54d653bfdc0
|
|
||||||
11: 0x7769b88ea90e - <&std::io::stdio::Stderr as std::io::Write>::write_fmt::h297671288300128f
|
|
||||||
12: 0x7769b88eb2d8 - std::io::stdio::_eprint::hc00582a539350b14
|
|
||||||
13: 0x5c922e7aaf33 - rustfmt[d1e716a5735454ec]::format_and_emit_report::<std[dd93a93a14cc3e06]::io::stdio::Stdout>
|
|
||||||
14: 0x5c922e7a999f - rustfmt[d1e716a5735454ec]::execute
|
|
||||||
15: 0x5c922e7a4943 - rustfmt[d1e716a5735454ec]::main
|
|
||||||
16: 0x5c922e798e73 - std[dd93a93a14cc3e06]::sys::backtrace::__rust_begin_short_backtrace::<fn(), ()>
|
|
||||||
17: 0x5c922e7993f9 - std[dd93a93a14cc3e06]::rt::lang_start::<()>::{closure#0}
|
|
||||||
18: 0x7769b9e77ade - std::rt::lang_start_internal::h1d6a430fc18f5497
|
|
||||||
19: 0x5c922e7abf98 - main
|
|
||||||
20: 0x7769b4145e08 - <unknown>
|
|
||||||
21: 0x7769b4145ecc - __libc_start_main
|
|
||||||
22: 0x5c922e78c6c9 - <unknown>
|
|
||||||
23: 0x0 - <unknown>
|
|
||||||
|
|
||||||
|
|
||||||
rustc version: 1.86.0-nightly (419b3e2d3 2025-01-15)
|
|
||||||
platform: x86_64-unknown-linux-gnu
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
thread 'main' panicked at /rust/deps/annotate-snippets-0.9.2/src/display_list/from_snippet.rs:275:9:
|
|
||||||
SourceAnnotation range `(100, 102)` is bigger than source length `101`
|
|
||||||
stack backtrace:
|
|
||||||
0: 0x75c3f976d725 - std::backtrace::Backtrace::create::hea54461184d28e5c
|
|
||||||
1: 0x75c3f7ce0cb5 - std::backtrace::Backtrace::force_capture::h50ac56ebac4f2900
|
|
||||||
2: 0x75c3f6e5b0e0 - std[dd93a93a14cc3e06]::panicking::update_hook::<alloc[634825797b513591]::boxed::Box<rustc_driver_impl[c64f1141ed92455f]::install_ice_hook::{closure#1}>>::{closure#0}
|
|
||||||
3: 0x75c3f7cf9623 - std::panicking::rust_panic_with_hook::hdfd8e9403702a2d1
|
|
||||||
4: 0x75c3f7cf931a - std::panicking::begin_panic_handler::{{closure}}::h47998eb7cec3c619
|
|
||||||
5: 0x75c3f7cf6ce9 - std::sys::backtrace::__rust_end_short_backtrace::h51610b4899330428
|
|
||||||
6: 0x75c3f7cf8fdd - rust_begin_unwind
|
|
||||||
7: 0x75c3f49a6b10 - core::panicking::panic_fmt::h76c97b2053f3e171
|
|
||||||
8: 0x630acd2a0da0 - <annotate_snippets[7516fd2ac470cd96]::display_list::structs::DisplayList as core[369bcca9ba44f16b]::convert::From<annotate_snippets[7516fd2ac470cd96]::snippet::Snippet>>::from
|
|
||||||
9: 0x630acd0ccdb4 - <rustfmt_nightly[fdba9bd7d028ddaf]::format_report_formatter::FormatReportFormatter as core[369bcca9ba44f16b]::fmt::Display>::fmt
|
|
||||||
10: 0x75c3f8412d66 - core::fmt::write::hbdbaf54d653bfdc0
|
|
||||||
11: 0x75c3f7cea90e - <&std::io::stdio::Stderr as std::io::Write>::write_fmt::h297671288300128f
|
|
||||||
12: 0x75c3f7ceb2d8 - std::io::stdio::_eprint::hc00582a539350b14
|
|
||||||
13: 0x630accfc6f33 - rustfmt[d1e716a5735454ec]::format_and_emit_report::<std[dd93a93a14cc3e06]::io::stdio::Stdout>
|
|
||||||
14: 0x630accfc599f - rustfmt[d1e716a5735454ec]::execute
|
|
||||||
15: 0x630accfc0943 - rustfmt[d1e716a5735454ec]::main
|
|
||||||
16: 0x630accfb4e73 - std[dd93a93a14cc3e06]::sys::backtrace::__rust_begin_short_backtrace::<fn(), ()>
|
|
||||||
17: 0x630accfb53f9 - std[dd93a93a14cc3e06]::rt::lang_start::<()>::{closure#0}
|
|
||||||
18: 0x75c3f9277ade - std::rt::lang_start_internal::h1d6a430fc18f5497
|
|
||||||
19: 0x630accfc7f98 - main
|
|
||||||
20: 0x75c3f3634e08 - <unknown>
|
|
||||||
21: 0x75c3f3634ecc - __libc_start_main
|
|
||||||
22: 0x630accfa86c9 - <unknown>
|
|
||||||
23: 0x0 - <unknown>
|
|
||||||
|
|
||||||
|
|
||||||
rustc version: 1.86.0-nightly (419b3e2d3 2025-01-15)
|
|
||||||
platform: x86_64-unknown-linux-gnu
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
thread 'main' panicked at /rust/deps/annotate-snippets-0.9.2/src/display_list/from_snippet.rs:275:9:
|
|
||||||
SourceAnnotation range `(100, 102)` is bigger than source length `101`
|
|
||||||
stack backtrace:
|
|
||||||
0: 0x76753116d725 - std::backtrace::Backtrace::create::hea54461184d28e5c
|
|
||||||
1: 0x76752f6e0cb5 - std::backtrace::Backtrace::force_capture::h50ac56ebac4f2900
|
|
||||||
2: 0x76752e85b0e0 - std[dd93a93a14cc3e06]::panicking::update_hook::<alloc[634825797b513591]::boxed::Box<rustc_driver_impl[c64f1141ed92455f]::install_ice_hook::{closure#1}>>::{closure#0}
|
|
||||||
3: 0x76752f6f9623 - std::panicking::rust_panic_with_hook::hdfd8e9403702a2d1
|
|
||||||
4: 0x76752f6f931a - std::panicking::begin_panic_handler::{{closure}}::h47998eb7cec3c619
|
|
||||||
5: 0x76752f6f6ce9 - std::sys::backtrace::__rust_end_short_backtrace::h51610b4899330428
|
|
||||||
6: 0x76752f6f8fdd - rust_begin_unwind
|
|
||||||
7: 0x76752c3a6b10 - core::panicking::panic_fmt::h76c97b2053f3e171
|
|
||||||
8: 0x5750f6273da0 - <annotate_snippets[7516fd2ac470cd96]::display_list::structs::DisplayList as core[369bcca9ba44f16b]::convert::From<annotate_snippets[7516fd2ac470cd96]::snippet::Snippet>>::from
|
|
||||||
9: 0x5750f609fdb4 - <rustfmt_nightly[fdba9bd7d028ddaf]::format_report_formatter::FormatReportFormatter as core[369bcca9ba44f16b]::fmt::Display>::fmt
|
|
||||||
10: 0x76752fe12d66 - core::fmt::write::hbdbaf54d653bfdc0
|
|
||||||
11: 0x76752f6ea90e - <&std::io::stdio::Stderr as std::io::Write>::write_fmt::h297671288300128f
|
|
||||||
12: 0x76752f6eb2d8 - std::io::stdio::_eprint::hc00582a539350b14
|
|
||||||
13: 0x5750f5f99f33 - rustfmt[d1e716a5735454ec]::format_and_emit_report::<std[dd93a93a14cc3e06]::io::stdio::Stdout>
|
|
||||||
14: 0x5750f5f9899f - rustfmt[d1e716a5735454ec]::execute
|
|
||||||
15: 0x5750f5f93943 - rustfmt[d1e716a5735454ec]::main
|
|
||||||
16: 0x5750f5f87e73 - std[dd93a93a14cc3e06]::sys::backtrace::__rust_begin_short_backtrace::<fn(), ()>
|
|
||||||
17: 0x5750f5f883f9 - std[dd93a93a14cc3e06]::rt::lang_start::<()>::{closure#0}
|
|
||||||
18: 0x767530c77ade - std::rt::lang_start_internal::h1d6a430fc18f5497
|
|
||||||
19: 0x5750f5f9af98 - main
|
|
||||||
20: 0x76752aef0e08 - <unknown>
|
|
||||||
21: 0x76752aef0ecc - __libc_start_main
|
|
||||||
22: 0x5750f5f7b6c9 - <unknown>
|
|
||||||
23: 0x0 - <unknown>
|
|
||||||
|
|
||||||
|
|
||||||
rustc version: 1.86.0-nightly (419b3e2d3 2025-01-15)
|
|
||||||
platform: x86_64-unknown-linux-gnu
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
thread 'main' panicked at /rust/deps/annotate-snippets-0.9.2/src/display_list/from_snippet.rs:275:9:
|
|
||||||
SourceAnnotation range `(100, 102)` is bigger than source length `101`
|
|
||||||
stack backtrace:
|
|
||||||
0: 0x7fbe8296d725 - std::backtrace::Backtrace::create::hea54461184d28e5c
|
|
||||||
1: 0x7fbe80ee0cb5 - std::backtrace::Backtrace::force_capture::h50ac56ebac4f2900
|
|
||||||
2: 0x7fbe8005b0e0 - std[dd93a93a14cc3e06]::panicking::update_hook::<alloc[634825797b513591]::boxed::Box<rustc_driver_impl[c64f1141ed92455f]::install_ice_hook::{closure#1}>>::{closure#0}
|
|
||||||
3: 0x7fbe80ef9623 - std::panicking::rust_panic_with_hook::hdfd8e9403702a2d1
|
|
||||||
4: 0x7fbe80ef931a - std::panicking::begin_panic_handler::{{closure}}::h47998eb7cec3c619
|
|
||||||
5: 0x7fbe80ef6ce9 - std::sys::backtrace::__rust_end_short_backtrace::h51610b4899330428
|
|
||||||
6: 0x7fbe80ef8fdd - rust_begin_unwind
|
|
||||||
7: 0x7fbe7dba6b10 - core::panicking::panic_fmt::h76c97b2053f3e171
|
|
||||||
8: 0x645d8f426da0 - <annotate_snippets[7516fd2ac470cd96]::display_list::structs::DisplayList as core[369bcca9ba44f16b]::convert::From<annotate_snippets[7516fd2ac470cd96]::snippet::Snippet>>::from
|
|
||||||
9: 0x645d8f252db4 - <rustfmt_nightly[fdba9bd7d028ddaf]::format_report_formatter::FormatReportFormatter as core[369bcca9ba44f16b]::fmt::Display>::fmt
|
|
||||||
10: 0x7fbe81612d66 - core::fmt::write::hbdbaf54d653bfdc0
|
|
||||||
11: 0x7fbe80eea90e - <&std::io::stdio::Stderr as std::io::Write>::write_fmt::h297671288300128f
|
|
||||||
12: 0x7fbe80eeb2d8 - std::io::stdio::_eprint::hc00582a539350b14
|
|
||||||
13: 0x645d8f14cf33 - rustfmt[d1e716a5735454ec]::format_and_emit_report::<std[dd93a93a14cc3e06]::io::stdio::Stdout>
|
|
||||||
14: 0x645d8f14b99f - rustfmt[d1e716a5735454ec]::execute
|
|
||||||
15: 0x645d8f146943 - rustfmt[d1e716a5735454ec]::main
|
|
||||||
16: 0x645d8f13ae73 - std[dd93a93a14cc3e06]::sys::backtrace::__rust_begin_short_backtrace::<fn(), ()>
|
|
||||||
17: 0x645d8f13b3f9 - std[dd93a93a14cc3e06]::rt::lang_start::<()>::{closure#0}
|
|
||||||
18: 0x7fbe82477ade - std::rt::lang_start_internal::h1d6a430fc18f5497
|
|
||||||
19: 0x645d8f14df98 - main
|
|
||||||
20: 0x7fbe7c745e08 - <unknown>
|
|
||||||
21: 0x7fbe7c745ecc - __libc_start_main
|
|
||||||
22: 0x645d8f12e6c9 - <unknown>
|
|
||||||
23: 0x0 - <unknown>
|
|
||||||
|
|
||||||
|
|
||||||
rustc version: 1.86.0-nightly (419b3e2d3 2025-01-15)
|
|
||||||
platform: x86_64-unknown-linux-gnu
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
thread 'main' panicked at /rust/deps/annotate-snippets-0.9.2/src/display_list/from_snippet.rs:275:9:
|
|
||||||
SourceAnnotation range `(100, 102)` is bigger than source length `101`
|
|
||||||
stack backtrace:
|
|
||||||
0: 0x7ae58e56d725 - std::backtrace::Backtrace::create::hea54461184d28e5c
|
|
||||||
1: 0x7ae58cae0cb5 - std::backtrace::Backtrace::force_capture::h50ac56ebac4f2900
|
|
||||||
2: 0x7ae58bc5b0e0 - std[dd93a93a14cc3e06]::panicking::update_hook::<alloc[634825797b513591]::boxed::Box<rustc_driver_impl[c64f1141ed92455f]::install_ice_hook::{closure#1}>>::{closure#0}
|
|
||||||
3: 0x7ae58caf9623 - std::panicking::rust_panic_with_hook::hdfd8e9403702a2d1
|
|
||||||
4: 0x7ae58caf931a - std::panicking::begin_panic_handler::{{closure}}::h47998eb7cec3c619
|
|
||||||
5: 0x7ae58caf6ce9 - std::sys::backtrace::__rust_end_short_backtrace::h51610b4899330428
|
|
||||||
6: 0x7ae58caf8fdd - rust_begin_unwind
|
|
||||||
7: 0x7ae5897a6b10 - core::panicking::panic_fmt::h76c97b2053f3e171
|
|
||||||
8: 0x59f3f1d86da0 - <annotate_snippets[7516fd2ac470cd96]::display_list::structs::DisplayList as core[369bcca9ba44f16b]::convert::From<annotate_snippets[7516fd2ac470cd96]::snippet::Snippet>>::from
|
|
||||||
9: 0x59f3f1bb2db4 - <rustfmt_nightly[fdba9bd7d028ddaf]::format_report_formatter::FormatReportFormatter as core[369bcca9ba44f16b]::fmt::Display>::fmt
|
|
||||||
10: 0x7ae58d212d66 - core::fmt::write::hbdbaf54d653bfdc0
|
|
||||||
11: 0x7ae58caea90e - <&std::io::stdio::Stderr as std::io::Write>::write_fmt::h297671288300128f
|
|
||||||
12: 0x7ae58caeb2d8 - std::io::stdio::_eprint::hc00582a539350b14
|
|
||||||
13: 0x59f3f1aacf33 - rustfmt[d1e716a5735454ec]::format_and_emit_report::<std[dd93a93a14cc3e06]::io::stdio::Stdout>
|
|
||||||
14: 0x59f3f1aab99f - rustfmt[d1e716a5735454ec]::execute
|
|
||||||
15: 0x59f3f1aa6943 - rustfmt[d1e716a5735454ec]::main
|
|
||||||
16: 0x59f3f1a9ae73 - std[dd93a93a14cc3e06]::sys::backtrace::__rust_begin_short_backtrace::<fn(), ()>
|
|
||||||
17: 0x59f3f1a9b3f9 - std[dd93a93a14cc3e06]::rt::lang_start::<()>::{closure#0}
|
|
||||||
18: 0x7ae58e077ade - std::rt::lang_start_internal::h1d6a430fc18f5497
|
|
||||||
19: 0x59f3f1aadf98 - main
|
|
||||||
20: 0x7ae588345e08 - <unknown>
|
|
||||||
21: 0x7ae588345ecc - __libc_start_main
|
|
||||||
22: 0x59f3f1a8e6c9 - <unknown>
|
|
||||||
23: 0x0 - <unknown>
|
|
||||||
|
|
||||||
|
|
||||||
rustc version: 1.86.0-nightly (419b3e2d3 2025-01-15)
|
|
||||||
platform: x86_64-unknown-linux-gnu
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
thread 'main' panicked at /rust/deps/annotate-snippets-0.9.2/src/display_list/from_snippet.rs:275:9:
|
|
||||||
SourceAnnotation range `(100, 102)` is bigger than source length `101`
|
|
||||||
stack backtrace:
|
|
||||||
0: 0x7306aa96d725 - std::backtrace::Backtrace::create::hea54461184d28e5c
|
|
||||||
1: 0x7306a8ee0cb5 - std::backtrace::Backtrace::force_capture::h50ac56ebac4f2900
|
|
||||||
2: 0x7306a805b0e0 - std[dd93a93a14cc3e06]::panicking::update_hook::<alloc[634825797b513591]::boxed::Box<rustc_driver_impl[c64f1141ed92455f]::install_ice_hook::{closure#1}>>::{closure#0}
|
|
||||||
3: 0x7306a8ef9623 - std::panicking::rust_panic_with_hook::hdfd8e9403702a2d1
|
|
||||||
4: 0x7306a8ef931a - std::panicking::begin_panic_handler::{{closure}}::h47998eb7cec3c619
|
|
||||||
5: 0x7306a8ef6ce9 - std::sys::backtrace::__rust_end_short_backtrace::h51610b4899330428
|
|
||||||
6: 0x7306a8ef8fdd - rust_begin_unwind
|
|
||||||
7: 0x7306a5ba6b10 - core::panicking::panic_fmt::h76c97b2053f3e171
|
|
||||||
8: 0x646d10ca5da0 - <annotate_snippets[7516fd2ac470cd96]::display_list::structs::DisplayList as core[369bcca9ba44f16b]::convert::From<annotate_snippets[7516fd2ac470cd96]::snippet::Snippet>>::from
|
|
||||||
9: 0x646d10ad1db4 - <rustfmt_nightly[fdba9bd7d028ddaf]::format_report_formatter::FormatReportFormatter as core[369bcca9ba44f16b]::fmt::Display>::fmt
|
|
||||||
10: 0x7306a9612d66 - core::fmt::write::hbdbaf54d653bfdc0
|
|
||||||
11: 0x7306a8eea90e - <&std::io::stdio::Stderr as std::io::Write>::write_fmt::h297671288300128f
|
|
||||||
12: 0x7306a8eeb2d8 - std::io::stdio::_eprint::hc00582a539350b14
|
|
||||||
13: 0x646d109cbf33 - rustfmt[d1e716a5735454ec]::format_and_emit_report::<std[dd93a93a14cc3e06]::io::stdio::Stdout>
|
|
||||||
14: 0x646d109ca99f - rustfmt[d1e716a5735454ec]::execute
|
|
||||||
15: 0x646d109c5943 - rustfmt[d1e716a5735454ec]::main
|
|
||||||
16: 0x646d109b9e73 - std[dd93a93a14cc3e06]::sys::backtrace::__rust_begin_short_backtrace::<fn(), ()>
|
|
||||||
17: 0x646d109ba3f9 - std[dd93a93a14cc3e06]::rt::lang_start::<()>::{closure#0}
|
|
||||||
18: 0x7306aa477ade - std::rt::lang_start_internal::h1d6a430fc18f5497
|
|
||||||
19: 0x646d109ccf98 - main
|
|
||||||
20: 0x7306a4745e08 - <unknown>
|
|
||||||
21: 0x7306a4745ecc - __libc_start_main
|
|
||||||
22: 0x646d109ad6c9 - <unknown>
|
|
||||||
23: 0x0 - <unknown>
|
|
||||||
|
|
||||||
|
|
||||||
rustc version: 1.86.0-nightly (419b3e2d3 2025-01-15)
|
|
||||||
platform: x86_64-unknown-linux-gnu
|
|
||||||
@@ -1,16 +1,22 @@
|
|||||||
use std::any::TypeId;
|
use std::any::TypeId;
|
||||||
|
use std::future::Future;
|
||||||
use std::num::NonZero;
|
use std::num::NonZero;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use futures::FutureExt;
|
||||||
|
use futures::future::LocalBoxFuture;
|
||||||
|
use futures::task::LocalSpawn;
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use orchid_api_traits::{Coding, Decode};
|
use orchid_api_traits::{Coding, Decode};
|
||||||
use orchid_base::boxed_iter::BoxedIter;
|
use orchid_base::boxed_iter::BoxedIter;
|
||||||
|
use orchid_base::id_store::IdStore;
|
||||||
use orchid_base::interner::Tok;
|
use orchid_base::interner::Tok;
|
||||||
use orchid_base::logging::Logger;
|
use orchid_base::logging::Logger;
|
||||||
use orchid_base::reqnot::{Receipt, ReqNot};
|
use orchid_base::reqnot::{Receipt, ReqNot};
|
||||||
|
|
||||||
use crate::api;
|
use crate::api;
|
||||||
use crate::atom::{AtomCtx, AtomDynfo, AtomicFeatures, ForeignAtom, TypAtom, get_info};
|
use crate::atom::{AtomCtx, AtomDynfo, AtomicFeatures, ForeignAtom, TypAtom, get_info};
|
||||||
|
use crate::atom_owned::{DynOwnedAtom, ObjStore};
|
||||||
use crate::entrypoint::ExtReq;
|
use crate::entrypoint::ExtReq;
|
||||||
use crate::fs::DeclFs;
|
use crate::fs::DeclFs;
|
||||||
use crate::func_atom::Fun;
|
use crate::func_atom::Fun;
|
||||||
@@ -77,7 +83,7 @@ pub trait System: Send + Sync + SystemCard + 'static {
|
|||||||
fn vfs() -> DeclFs;
|
fn vfs() -> DeclFs;
|
||||||
fn lexers() -> Vec<LexerObj>;
|
fn lexers() -> Vec<LexerObj>;
|
||||||
fn parsers() -> Vec<ParserObj>;
|
fn parsers() -> Vec<ParserObj>;
|
||||||
fn request(hand: ExtReq, req: Self::Req) -> Receipt;
|
fn request<'a>(hand: ExtReq<'a>, req: Self::Req) -> impl Future<Output = Receipt<'a>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait DynSystem: Send + Sync + DynSystemCard + 'static {
|
pub trait DynSystem: Send + Sync + DynSystemCard + 'static {
|
||||||
@@ -85,7 +91,7 @@ pub trait DynSystem: Send + Sync + DynSystemCard + 'static {
|
|||||||
fn dyn_vfs(&self) -> DeclFs;
|
fn dyn_vfs(&self) -> DeclFs;
|
||||||
fn dyn_lexers(&self) -> Vec<LexerObj>;
|
fn dyn_lexers(&self) -> Vec<LexerObj>;
|
||||||
fn dyn_parsers(&self) -> Vec<ParserObj>;
|
fn dyn_parsers(&self) -> Vec<ParserObj>;
|
||||||
fn dyn_request(&self, hand: ExtReq, req: Vec<u8>) -> Receipt;
|
fn dyn_request<'a>(&'a self, hand: ExtReq<'a>, req: Vec<u8>) -> LocalBoxFuture<'a, Receipt<'a>>;
|
||||||
fn card(&self) -> &dyn DynSystemCard;
|
fn card(&self) -> &dyn DynSystemCard;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,8 +100,8 @@ impl<T: System> DynSystem for T {
|
|||||||
fn dyn_vfs(&self) -> DeclFs { Self::vfs() }
|
fn dyn_vfs(&self) -> DeclFs { Self::vfs() }
|
||||||
fn dyn_lexers(&self) -> Vec<LexerObj> { Self::lexers() }
|
fn dyn_lexers(&self) -> Vec<LexerObj> { Self::lexers() }
|
||||||
fn dyn_parsers(&self) -> Vec<ParserObj> { Self::parsers() }
|
fn dyn_parsers(&self) -> Vec<ParserObj> { Self::parsers() }
|
||||||
fn dyn_request(&self, hand: ExtReq, req: Vec<u8>) -> Receipt {
|
fn dyn_request<'a>(&'a self, hand: ExtReq<'a>, req: Vec<u8>) -> LocalBoxFuture<'a, Receipt<'a>> {
|
||||||
Self::request(hand, <Self as SystemCard>::Req::decode(&mut &req[..]))
|
Self::request(hand, <Self as SystemCard>::Req::decode(&mut &req[..])).boxed_local()
|
||||||
}
|
}
|
||||||
fn card(&self) -> &dyn DynSystemCard { self }
|
fn card(&self) -> &dyn DynSystemCard { self }
|
||||||
}
|
}
|
||||||
@@ -119,17 +125,9 @@ pub fn downcast_atom<A: AtomicFeatures>(foreign: ForeignAtom) -> Result<TypAtom<
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SysCtx {
|
pub struct SysCtx {
|
||||||
pub reqnot: ReqNot<api::ExtMsgSet>,
|
pub reqnot: ReqNot<api::ExtMsgSet>,
|
||||||
|
pub spawner: Arc<dyn LocalSpawn>,
|
||||||
pub id: api::SysId,
|
pub id: api::SysId,
|
||||||
pub cted: CtedObj,
|
pub cted: CtedObj,
|
||||||
pub logger: Arc<Logger>,
|
pub logger: Arc<Logger>,
|
||||||
}
|
pub obj_store: ObjStore,
|
||||||
impl SysCtx {
|
|
||||||
pub fn new(
|
|
||||||
id: api::SysId,
|
|
||||||
cted: &CtedObj,
|
|
||||||
logger: &Arc<Logger>,
|
|
||||||
reqnot: ReqNot<api::ExtMsgSet>,
|
|
||||||
) -> Self {
|
|
||||||
Self { cted: cted.clone(), id, logger: logger.clone(), reqnot }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
|
use std::future::Future;
|
||||||
use std::num::NonZero;
|
use std::num::NonZero;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
|
||||||
use dyn_clone::{DynClone, clone_box};
|
use dyn_clone::{DynClone, clone_box};
|
||||||
|
use futures::FutureExt;
|
||||||
|
use futures::future::{LocalBoxFuture, join_all};
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use orchid_base::interner::{Tok, intern};
|
use orchid_base::interner::{Tok, intern};
|
||||||
@@ -56,19 +59,19 @@ impl GenItem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cnst(public: bool, name: &str, value: impl ToExpr) -> Vec<GenItem> {
|
pub async fn cnst(public: bool, name: &str, value: impl ToExpr) -> Vec<GenItem> {
|
||||||
with_export(GenMember { name: intern(name), kind: MemKind::Const(value.to_expr()) }, public)
|
with_export(GenMember { name: intern(name).await, kind: MemKind::Const(value.to_expr()) }, public)
|
||||||
}
|
}
|
||||||
pub fn module(
|
pub async fn module(
|
||||||
public: bool,
|
public: bool,
|
||||||
name: &str,
|
name: &str,
|
||||||
imports: impl IntoIterator<Item = Sym>,
|
imports: impl IntoIterator<Item = Sym>,
|
||||||
items: impl IntoIterator<Item = Vec<GenItem>>,
|
items: impl IntoIterator<Item = Vec<GenItem>>,
|
||||||
) -> Vec<GenItem> {
|
) -> Vec<GenItem> {
|
||||||
let (name, kind) = root_mod(name, imports, items);
|
let (name, kind) = root_mod(name, imports, items).await;
|
||||||
with_export(GenMember { name, kind }, public)
|
with_export(GenMember { name, kind }, public)
|
||||||
}
|
}
|
||||||
pub fn root_mod(
|
pub async fn root_mod(
|
||||||
name: &str,
|
name: &str,
|
||||||
imports: impl IntoIterator<Item = Sym>,
|
imports: impl IntoIterator<Item = Sym>,
|
||||||
items: impl IntoIterator<Item = Vec<GenItem>>,
|
items: impl IntoIterator<Item = Vec<GenItem>>,
|
||||||
@@ -77,37 +80,44 @@ pub fn root_mod(
|
|||||||
imports: imports.into_iter().collect(),
|
imports: imports.into_iter().collect(),
|
||||||
items: items.into_iter().flatten().collect(),
|
items: items.into_iter().flatten().collect(),
|
||||||
};
|
};
|
||||||
(intern(name), kind)
|
(intern(name).await, kind)
|
||||||
}
|
}
|
||||||
pub fn fun<I, O>(exported: bool, name: &str, xf: impl ExprFunc<I, O>) -> Vec<GenItem> {
|
pub async fn fun<I, O>(exported: bool, name: &str, xf: impl ExprFunc<I, O>) -> Vec<GenItem> {
|
||||||
let fac = LazyMemberFactory::new(move |sym| MemKind::Const(Fun::new(sym, xf).to_expr()));
|
let fac =
|
||||||
with_export(GenMember { name: intern(name), kind: MemKind::Lazy(fac) }, exported)
|
LazyMemberFactory::new(move |sym| async { MemKind::Const(Fun::new(sym, xf).to_expr()) });
|
||||||
|
with_export(GenMember { name: intern(name).await, kind: MemKind::Lazy(fac) }, exported)
|
||||||
}
|
}
|
||||||
pub fn macro_block(prio: Option<f64>, rules: impl IntoIterator<Item = Rule>) -> Vec<GenItem> {
|
pub fn macro_block(prio: Option<f64>, rules: impl IntoIterator<Item = Rule>) -> Vec<GenItem> {
|
||||||
let prio = prio.map(|p| NotNan::new(p).unwrap());
|
let prio = prio.map(|p| NotNan::new(p).unwrap());
|
||||||
vec![GenItemKind::Macro(prio, rules.into_iter().collect_vec()).gen()]
|
vec![GenItemKind::Macro(prio, rules.into_iter().collect_vec()).gen()]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn comments<'a>(
|
pub async fn comments<'a>(
|
||||||
cmts: impl IntoIterator<Item = &'a str> + Clone,
|
cmts: impl IntoIterator<Item = &'a str>,
|
||||||
mut val: Vec<GenItem>,
|
mut val: Vec<GenItem>,
|
||||||
) -> Vec<GenItem> {
|
) -> Vec<GenItem> {
|
||||||
|
let cmts = join_all(
|
||||||
|
cmts.into_iter().map(|c| async { Comment { text: intern(c).await, pos: Pos::Inherit } }),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
for v in val.iter_mut() {
|
for v in val.iter_mut() {
|
||||||
v.comments
|
v.comments.extend(cmts.iter().cloned());
|
||||||
.extend(cmts.clone().into_iter().map(|c| Comment { text: intern(c), pos: Pos::Inherit }));
|
|
||||||
}
|
}
|
||||||
val
|
val
|
||||||
}
|
}
|
||||||
|
|
||||||
trait_set! {
|
trait_set! {
|
||||||
trait LazyMemberCallback = FnOnce(Sym) -> MemKind + Send + Sync + DynClone
|
trait LazyMemberCallback =
|
||||||
|
FnOnce(Sym) -> LocalBoxFuture<'static, MemKind> + Send + Sync + DynClone
|
||||||
}
|
}
|
||||||
pub struct LazyMemberFactory(Box<dyn LazyMemberCallback>);
|
pub struct LazyMemberFactory(Box<dyn LazyMemberCallback>);
|
||||||
impl LazyMemberFactory {
|
impl LazyMemberFactory {
|
||||||
pub fn new(cb: impl FnOnce(Sym) -> MemKind + Send + Sync + Clone + 'static) -> Self {
|
pub fn new<F: Future<Output = MemKind> + 'static>(
|
||||||
Self(Box::new(cb))
|
cb: impl FnOnce(Sym) -> F + Send + Sync + Clone + 'static,
|
||||||
|
) -> Self {
|
||||||
|
Self(Box::new(|s| cb(s).boxed_local()))
|
||||||
}
|
}
|
||||||
pub fn build(self, path: Sym) -> MemKind { (self.0)(path) }
|
pub async fn build(self, path: Sym) -> MemKind { (self.0)(path).await }
|
||||||
}
|
}
|
||||||
impl Clone for LazyMemberFactory {
|
impl Clone for LazyMemberFactory {
|
||||||
fn clone(&self) -> Self { Self(clone_box(&*self.0)) }
|
fn clone(&self) -> Self { Self(clone_box(&*self.0)) }
|
||||||
@@ -187,7 +197,7 @@ impl<'a, 'b> TreeIntoApiCtx for TIACtxImpl<'a, 'b> {
|
|||||||
}
|
}
|
||||||
fn with_lazy(&mut self, fac: LazyMemberFactory) -> api::TreeId {
|
fn with_lazy(&mut self, fac: LazyMemberFactory) -> api::TreeId {
|
||||||
let id = api::TreeId(NonZero::new((self.lazy.len() + 2) as u64).unwrap());
|
let id = api::TreeId(NonZero::new((self.lazy.len() + 2) as u64).unwrap());
|
||||||
let path = Sym::new(self.basepath.iter().cloned().chain(self.path.unreverse())).unwrap();
|
let path = self.basepath.iter().cloned().chain(self.path.unreverse()).collect_vec();
|
||||||
self.lazy.insert(id, MemberRecord::Gen(path, fac));
|
self.lazy.insert(id, MemberRecord::Gen(path, fac));
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ style_edition = "2024"
|
|||||||
tab_spaces = 2
|
tab_spaces = 2
|
||||||
hard_tabs = true
|
hard_tabs = true
|
||||||
max_width = 100
|
max_width = 100
|
||||||
error_on_line_overflow = true
|
# error_on_line_overflow = true
|
||||||
error_on_unformatted = true
|
error_on_unformatted = true
|
||||||
format_macro_matchers = true
|
format_macro_matchers = true
|
||||||
newline_style = "Unix"
|
newline_style = "Unix"
|
||||||
|
|||||||
Reference in New Issue
Block a user