for a moment, everything works
This commit is contained in:
@@ -42,6 +42,13 @@ pub trait AtomicVariant {}
|
||||
pub trait Atomic: 'static + Sized {
|
||||
type Variant: AtomicVariant;
|
||||
type Data: Clone + Coding + Sized + 'static;
|
||||
/// Register handlers for IPC calls. If this atom implements [Supports], you
|
||||
/// should register your implementations here. If this atom doesn't
|
||||
/// participate in IPC at all, use the below body.
|
||||
/// ```
|
||||
/// MethodSetBuilder::new()
|
||||
/// ```
|
||||
// this method isn't default-implemented to prevent bugs from forgetting to register IPC requests.
|
||||
fn reg_reqs() -> MethodSetBuilder<Self>;
|
||||
}
|
||||
impl<A: Atomic> AtomCard for A {
|
||||
@@ -106,9 +113,9 @@ impl ForeignAtom<'static> {
|
||||
ForeignAtom { _life: PhantomData, atom, ctx: handle.ctx.clone(), expr: Some(handle), pos }
|
||||
}
|
||||
pub async fn request<M: AtomMethod>(&self, m: M) -> Option<M::Response> {
|
||||
let rep = (self.ctx.reqnot.request(api::Fwd(
|
||||
let rep = (self.ctx.reqnot().request(api::Fwd(
|
||||
self.atom.clone(),
|
||||
Sym::parse(M::NAME, &self.ctx.i).await.unwrap().tok().to_api(),
|
||||
Sym::parse(M::NAME, self.ctx.i()).await.unwrap().tok().to_api(),
|
||||
enc_vec(&m).await,
|
||||
)))
|
||||
.await?;
|
||||
@@ -125,7 +132,7 @@ impl fmt::Debug for ForeignAtom<'_> {
|
||||
}
|
||||
impl Format for ForeignAtom<'_> {
|
||||
async fn print<'a>(&'a self, _c: &'a (impl FmtCtx + ?Sized + 'a)) -> FmtUnit {
|
||||
FmtUnit::from_api(&self.ctx.reqnot.request(api::ExtAtomPrint(self.atom.clone())).await)
|
||||
FmtUnit::from_api(&self.ctx.reqnot().request(api::ExtAtomPrint(self.atom.clone())).await)
|
||||
}
|
||||
}
|
||||
impl AtomRepr for ForeignAtom<'_> {
|
||||
@@ -145,7 +152,7 @@ pub struct NotTypAtom {
|
||||
impl NotTypAtom {
|
||||
pub async fn mk_err(&self) -> OrcErr {
|
||||
mk_err(
|
||||
self.ctx.i.i("Not the expected type").await,
|
||||
self.ctx.i().i("Not the expected type").await,
|
||||
format!("This expression is not a {}", self.typ.name()),
|
||||
[self.pos.clone().into()],
|
||||
)
|
||||
@@ -192,7 +199,7 @@ impl<A: AtomCard> MethodSetBuilder<A> {
|
||||
handlers: stream::from_iter(self.handlers.iter())
|
||||
.then(|(k, v)| {
|
||||
clone!(ctx; async move {
|
||||
(Sym::parse(k, &ctx.i).await.unwrap(), v.clone())
|
||||
(Sym::parse(k, ctx.i()).await.unwrap(), v.clone())
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
@@ -257,9 +264,9 @@ impl<A: AtomicFeatures> TypAtom<'_, A> {
|
||||
pub async fn request<M: AtomMethod>(&self, req: M) -> M::Response
|
||||
where A: Supports<M> {
|
||||
M::Response::decode(Pin::new(
|
||||
&mut &(self.data.ctx.reqnot.request(api::Fwd(
|
||||
&mut &(self.data.ctx.reqnot().request(api::Fwd(
|
||||
self.data.atom.clone(),
|
||||
Sym::parse(M::NAME, &self.data.ctx.i).await.unwrap().tok().to_api(),
|
||||
Sym::parse(M::NAME, self.data.ctx.i()).await.unwrap().tok().to_api(),
|
||||
enc_vec(&req).await,
|
||||
)))
|
||||
.await
|
||||
@@ -275,7 +282,7 @@ impl<A: AtomicFeatures> Deref for TypAtom<'_, A> {
|
||||
|
||||
pub struct AtomCtx<'a>(pub &'a [u8], pub Option<api::AtomId>, pub SysCtx);
|
||||
impl FmtCtx for AtomCtx<'_> {
|
||||
fn i(&self) -> &Interner { &self.2.i }
|
||||
fn i(&self) -> &Interner { self.2.i() }
|
||||
}
|
||||
|
||||
pub trait AtomDynfo: 'static {
|
||||
|
||||
@@ -28,20 +28,23 @@ use crate::atom::{
|
||||
};
|
||||
use crate::expr::{Expr, ExprHandle};
|
||||
use crate::gen_expr::{GExpr, bot};
|
||||
use crate::system::SysCtx;
|
||||
use crate::system::{SysCtx, SysCtxEntry};
|
||||
use crate::system_ctor::CtedObj;
|
||||
|
||||
pub struct OwnedVariant;
|
||||
impl AtomicVariant for OwnedVariant {}
|
||||
impl<A: OwnedAtom + Atomic<Variant = OwnedVariant>> AtomicFeaturesImpl<OwnedVariant> for A {
|
||||
fn _factory(self) -> AtomFactory {
|
||||
AtomFactory::new(move |ctx| async move {
|
||||
let serial = ctx.obj_store.0.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
||||
let serial =
|
||||
ctx.get_or_default::<ObjStore>().next_id.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
||||
let atom_id = api::AtomId(NonZero::new(serial + 1).unwrap());
|
||||
let (typ_id, _) = get_info::<A>(ctx.cted.inst().card());
|
||||
let (typ_id, _) = get_info::<A>(ctx.get::<CtedObj>().inst().card());
|
||||
let mut data = enc_vec(&typ_id).await;
|
||||
self.encode(Pin::<&mut Vec<u8>>::new(&mut data)).await;
|
||||
ctx.obj_store.1.read().await.insert(atom_id, Box::new(self));
|
||||
api::Atom { drop: Some(atom_id), data, owner: ctx.id }
|
||||
ctx.get_or_default::<ObjStore>().objects.read().await.insert(atom_id, Box::new(self));
|
||||
eprintln!("Created atom {:?} of type {}", atom_id, type_name::<A>());
|
||||
api::Atom { drop: Some(atom_id), data, owner: ctx.sys_id() }
|
||||
})
|
||||
}
|
||||
fn _info() -> Self::_Info { OwnedAtomDynfo { msbuild: A::reg_reqs(), ms: OnceCell::new() } }
|
||||
@@ -55,8 +58,9 @@ pub(crate) struct AtomReadGuard<'a> {
|
||||
}
|
||||
impl<'a> AtomReadGuard<'a> {
|
||||
async fn new(id: api::AtomId, ctx: &'a SysCtx) -> Self {
|
||||
let guard = ctx.obj_store.1.read().await;
|
||||
assert!(guard.get(&id).is_some(), "Received invalid atom ID: {}", id.0);
|
||||
let guard = ctx.get_or_default::<ObjStore>().objects.read().await;
|
||||
let valid = guard.iter().map(|i| i.0).collect_vec();
|
||||
assert!(guard.get(&id).is_some(), "Received invalid atom ID: {:?} not in {:?}", id, valid);
|
||||
Self { id, guard }
|
||||
}
|
||||
}
|
||||
@@ -66,7 +70,7 @@ impl Deref for AtomReadGuard<'_> {
|
||||
}
|
||||
|
||||
pub(crate) async fn take_atom(id: api::AtomId, ctx: &SysCtx) -> Box<dyn DynOwnedAtom> {
|
||||
let mut g = ctx.obj_store.1.write().await;
|
||||
let mut g = ctx.get_or_default::<ObjStore>().objects.write().await;
|
||||
g.remove(&id).unwrap_or_else(|| panic!("Received invalid atom ID: {}", id.0))
|
||||
}
|
||||
|
||||
@@ -219,7 +223,7 @@ pub trait OwnedAtom: Atomic<Variant = OwnedVariant> + Any + Clone + 'static {
|
||||
fn val(&self) -> impl Future<Output = Cow<'_, Self::Data>>;
|
||||
#[allow(unused_variables)]
|
||||
fn call_ref(&self, arg: ExprHandle) -> impl Future<Output = GExpr> {
|
||||
async move { bot([err_not_callable(&arg.ctx.i).await]) }
|
||||
async move { bot([err_not_callable(arg.ctx.i()).await]) }
|
||||
}
|
||||
fn call(self, arg: ExprHandle) -> impl Future<Output = GExpr> {
|
||||
async {
|
||||
@@ -231,7 +235,7 @@ pub trait OwnedAtom: Atomic<Variant = OwnedVariant> + Any + Clone + 'static {
|
||||
}
|
||||
#[allow(unused_variables)]
|
||||
fn command(self, ctx: SysCtx) -> impl Future<Output = OrcRes<Option<GExpr>>> {
|
||||
async move { Err(err_not_command(&ctx.i).await.into()) }
|
||||
async move { Err(err_not_command(ctx.i()).await.into()) }
|
||||
}
|
||||
#[allow(unused_variables)]
|
||||
fn free(self, ctx: SysCtx) -> impl Future<Output = ()> { async {} }
|
||||
@@ -313,4 +317,9 @@ impl<T: OwnedAtom> DynOwnedAtom for T {
|
||||
}
|
||||
}
|
||||
|
||||
pub type ObjStore = Rc<(AtomicU64, RwLock<MemoMap<api::AtomId, Box<dyn DynOwnedAtom>>>)>;
|
||||
#[derive(Default)]
|
||||
struct ObjStore {
|
||||
next_id: AtomicU64,
|
||||
objects: RwLock<MemoMap<api::AtomId, Box<dyn DynOwnedAtom>>>,
|
||||
}
|
||||
impl SysCtxEntry for ObjStore {}
|
||||
|
||||
@@ -19,16 +19,17 @@ use crate::atom::{
|
||||
use crate::expr::ExprHandle;
|
||||
use crate::gen_expr::{GExpr, bot};
|
||||
use crate::system::SysCtx;
|
||||
use crate::system_ctor::CtedObj;
|
||||
|
||||
pub struct ThinVariant;
|
||||
impl AtomicVariant for ThinVariant {}
|
||||
impl<A: ThinAtom + Atomic<Variant = ThinVariant>> AtomicFeaturesImpl<ThinVariant> for A {
|
||||
fn _factory(self) -> AtomFactory {
|
||||
AtomFactory::new(move |ctx| async move {
|
||||
let (id, _) = get_info::<A>(ctx.cted.inst().card());
|
||||
let (id, _) = get_info::<A>(ctx.get::<CtedObj>().inst().card());
|
||||
let mut buf = enc_vec(&id).await;
|
||||
self.encode(Pin::new(&mut buf)).await;
|
||||
api::Atom { drop: None, data: buf, owner: ctx.id }
|
||||
api::Atom { drop: None, data: buf, owner: ctx.sys_id() }
|
||||
})
|
||||
}
|
||||
fn _info() -> Self::_Info { ThinAtomDynfo { msbuild: Self::reg_reqs(), ms: OnceCell::new() } }
|
||||
@@ -106,7 +107,7 @@ impl<T: ThinAtom> AtomDynfo for ThinAtomDynfo<T> {
|
||||
fn drop<'a>(&'a self, AtomCtx(buf, _, ctx): AtomCtx<'a>) -> LocalBoxFuture<'a, ()> {
|
||||
async move {
|
||||
let string_self = T::decode(Pin::new(&mut &buf[..])).await.print(ctx.clone()).await;
|
||||
writeln!(ctx.logger, "Received drop signal for non-drop atom {string_self:?}");
|
||||
writeln!(ctx.logger(), "Received drop signal for non-drop atom {string_self:?}");
|
||||
}
|
||||
.boxed_local()
|
||||
}
|
||||
@@ -117,11 +118,11 @@ pub trait ThinAtom:
|
||||
{
|
||||
#[allow(unused_variables)]
|
||||
fn call(&self, arg: ExprHandle) -> impl Future<Output = GExpr> {
|
||||
async move { bot([err_not_callable(&arg.ctx.i).await]) }
|
||||
async move { bot([err_not_callable(arg.ctx.i()).await]) }
|
||||
}
|
||||
#[allow(unused_variables)]
|
||||
fn command(&self, ctx: SysCtx) -> impl Future<Output = OrcRes<Option<GExpr>>> {
|
||||
async move { Err(err_not_command(&ctx.i).await.into()) }
|
||||
async move { Err(err_not_command(ctx.i()).await.into()) }
|
||||
}
|
||||
#[allow(unused_variables)]
|
||||
fn print(&self, ctx: SysCtx) -> impl Future<Output = FmtUnit> {
|
||||
|
||||
@@ -34,10 +34,10 @@ async fn err_type(pos: Pos, i: &Interner) -> OrcErr {
|
||||
impl<A: AtomicFeatures> TryFromExpr for TypAtom<'_, A> {
|
||||
async fn try_from_expr(expr: Expr) -> OrcRes<Self> {
|
||||
match expr.atom().await {
|
||||
Err(ex) => Err(err_not_atom(ex.data().await.pos.clone(), &ex.ctx().i).await.into()),
|
||||
Err(ex) => Err(err_not_atom(ex.data().await.pos.clone(), ex.ctx().i()).await.into()),
|
||||
Ok(f) => match downcast_atom::<A>(f).await {
|
||||
Ok(a) => Ok(a),
|
||||
Err(f) => Err(err_type(f.pos(), &f.ctx().i).await.into()),
|
||||
Err(f) => Err(err_type(f.pos(), f.ctx().i()).await.into()),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ use futures::future::{LocalBoxFuture, join_all};
|
||||
use futures::{FutureExt, StreamExt};
|
||||
use hashbrown::HashMap;
|
||||
use itertools::Itertools;
|
||||
use orchid_api::ApplyMacro;
|
||||
use orchid_api::{ApplyMacro, ExtMsgSet};
|
||||
use orchid_api_traits::{Decode, Encode, enc_vec};
|
||||
use orchid_base::builtin::{ExtPort, Spawner};
|
||||
use orchid_base::char_filter::{char_filter_match, char_filter_union, mk_char_filter};
|
||||
@@ -32,14 +32,14 @@ use trait_set::trait_set;
|
||||
|
||||
use crate::api;
|
||||
use crate::atom::{AtomCtx, AtomDynfo, AtomTypeId};
|
||||
use crate::atom_owned::{ObjStore, take_atom};
|
||||
use crate::atom_owned::take_atom;
|
||||
use crate::fs::VirtFS;
|
||||
use crate::lexer::{LexContext, err_cascade, err_not_applicable};
|
||||
use crate::macros::{Rule, RuleCtx};
|
||||
use crate::msg::{recv_parent_msg, send_parent_msg};
|
||||
use crate::system::{SysCtx, atom_by_idx};
|
||||
use crate::system_ctor::{CtedObj, DynSystemCtor};
|
||||
use crate::tree::{GenTok, GenTokTree, LazyMemberFactory, TIACtxImpl, do_extra};
|
||||
use crate::tree::{GenTok, GenTokTree, LazyMemberFactory, TreeIntoApiCtxImpl, do_extra};
|
||||
|
||||
pub type ExtReq<'a> = RequestHandle<'a, api::ExtMsgSet>;
|
||||
pub type ExtReqNot = ReqNot<api::ExtMsgSet>;
|
||||
@@ -61,11 +61,11 @@ pub enum MemberRecord {
|
||||
}
|
||||
|
||||
pub struct SystemRecord {
|
||||
cted: CtedObj,
|
||||
vfses: HashMap<api::VfsId, &'static dyn VirtFS>,
|
||||
declfs: api::EagerVfs,
|
||||
lazy_members: HashMap<api::TreeId, MemberRecord>,
|
||||
rules: HashMap<api::MacroId, Rc<Rule>>,
|
||||
ctx: SysCtx,
|
||||
}
|
||||
|
||||
trait_set! {
|
||||
@@ -78,14 +78,13 @@ trait_set! {
|
||||
}
|
||||
|
||||
pub async fn with_atom_record<'a, F: Future<Output = SysCtx>, T>(
|
||||
get_sys_ctx: &impl Fn(api::SysId, ReqNot<api::ExtMsgSet>) -> F,
|
||||
reqnot: ReqNot<api::ExtMsgSet>,
|
||||
get_sys_ctx: &impl Fn(api::SysId) -> F,
|
||||
atom: &'a api::Atom,
|
||||
cb: impl WARCallback<'a, T>,
|
||||
) -> T {
|
||||
let mut data = &atom.data[..];
|
||||
let ctx = get_sys_ctx(atom.owner, reqnot).await;
|
||||
let inst = ctx.cted.inst();
|
||||
let ctx = get_sys_ctx(atom.owner).await;
|
||||
let inst = ctx.get::<CtedObj>().inst();
|
||||
let id = AtomTypeId::decode(Pin::new(&mut data)).await;
|
||||
let atom_record = atom_by_idx(inst.card(), id.clone()).expect("Atom ID reserved");
|
||||
cb(atom_record, ctx, id, data).await
|
||||
@@ -108,6 +107,7 @@ pub struct ExtensionOwner {
|
||||
rn: ReqNot<api::ExtMsgSet>,
|
||||
out_recv: Receiver<Vec<u8>>,
|
||||
out_send: Sender<Vec<u8>>,
|
||||
ext_header: api::ExtensionHeader,
|
||||
}
|
||||
|
||||
impl ExtPort for ExtensionOwner {
|
||||
@@ -125,6 +125,12 @@ impl ExtPort for ExtensionOwner {
|
||||
.boxed_local()
|
||||
}
|
||||
}
|
||||
impl ExtensionOwner {
|
||||
pub fn ext_header(&self) -> &api::ExtensionHeader { &self.ext_header }
|
||||
// pub async fn new(data: ExtensionData, spawner: Spawner, header:
|
||||
// api::HostHeader) -> Self { let decls =
|
||||
// }
|
||||
}
|
||||
|
||||
pub async fn extension_main_logic(data: ExtensionData, spawner: Spawner) {
|
||||
let api::HostHeader { log_strategy, msg_logs } =
|
||||
@@ -134,7 +140,7 @@ pub async fn extension_main_logic(data: ExtensionData, spawner: Spawner) {
|
||||
.map(|(id, sys)| (u16::try_from(id).expect("more than u16max system ctors"), sys))
|
||||
.map(|(id, sys)| sys.decl(api::SysDeclId(NonZero::new(id + 1).unwrap())))
|
||||
.collect_vec();
|
||||
let systems = Rc::new(Mutex::new(HashMap::<api::SysId, SystemRecord>::new()));
|
||||
let systems_lock = Rc::new(Mutex::new(HashMap::<api::SysId, SystemRecord>::new()));
|
||||
api::ExtensionHeader { name: data.name.to_string(), systems: decls.clone() }
|
||||
.encode(Pin::new(&mut buf))
|
||||
.await;
|
||||
@@ -143,41 +149,48 @@ pub async fn extension_main_logic(data: ExtensionData, spawner: Spawner) {
|
||||
let exiting = Arc::new(AtomicBool::new(false));
|
||||
let logger = Logger::new(log_strategy);
|
||||
let msg_logger = Logger::new(msg_logs);
|
||||
let interner_cell = Rc::new(RefCell::new(None::<Rc<Interner>>));
|
||||
let interner_cell = Rc::new(RefCell::new(None::<Interner>));
|
||||
let interner_weak = Rc::downgrade(&interner_cell);
|
||||
let obj_store = ObjStore::default();
|
||||
let mk_ctx = clone!(
|
||||
logger, systems, spawner, obj_store, interner_weak;
|
||||
move |id: api::SysId, reqnot: ReqNot<api::ExtMsgSet>| {
|
||||
clone!(logger, systems, spawner, obj_store, interner_weak; async move {
|
||||
let cted = systems.lock().await[&id].cted.clone();
|
||||
let interner_cell = (interner_weak.upgrade())
|
||||
.expect("mk_ctx called after Interner rc dropped");
|
||||
let i = (interner_cell.borrow().clone())
|
||||
.expect("mk_ctx called before interner initialized");
|
||||
SysCtx { id, cted, logger, reqnot, spawner, obj_store, i: i.clone() }
|
||||
}.boxed_local())
|
||||
});
|
||||
let systems_weak = Rc::downgrade(&systems_lock);
|
||||
let get_ctx = clone!(systems_weak; move |id: api::SysId| clone!(systems_weak; async move {
|
||||
let systems =
|
||||
systems_weak.upgrade().expect("System table dropped before request processing done");
|
||||
let x = systems.lock().await.get(&id).expect("System not found").ctx.clone();
|
||||
x
|
||||
}));
|
||||
let init_ctx = {
|
||||
clone!(systems_weak, interner_weak, spawner, logger);
|
||||
move |id: api::SysId, cted: CtedObj, reqnot: ReqNot<ExtMsgSet>| {
|
||||
clone!(systems_weak, interner_weak, spawner, logger; async move {
|
||||
let interner_rc =
|
||||
interner_weak.upgrade().expect("System construction order while shutting down");
|
||||
let i = interner_rc.borrow().clone().expect("mk_ctx called very early, no interner!");
|
||||
SysCtx::new(id, i, reqnot, spawner, logger, cted)
|
||||
})
|
||||
}
|
||||
};
|
||||
let rn = ReqNot::<api::ExtMsgSet>::new(
|
||||
msg_logger.clone(),
|
||||
move |a, _| async move { send_parent_msg(a).await.unwrap() }.boxed_local(),
|
||||
clone!(systems, exiting, mk_ctx; move |n, reqnot| {
|
||||
clone!(systems, exiting, mk_ctx; async move {
|
||||
clone!(systems_weak, exiting, get_ctx; move |n, reqnot| {
|
||||
clone!(systems_weak, exiting, get_ctx; async move {
|
||||
match n {
|
||||
api::HostExtNotif::Exit => exiting.store(true, Ordering::Relaxed),
|
||||
api::HostExtNotif::SystemDrop(api::SystemDrop(sys_id)) =>
|
||||
mem::drop(systems.lock().await.remove(&sys_id)),
|
||||
if let Some(rc) = systems_weak.upgrade() {
|
||||
mem::drop(rc.lock().await.remove(&sys_id))
|
||||
},
|
||||
api::HostExtNotif::AtomDrop(api::AtomDrop(sys_id, atom)) => {
|
||||
let ctx = mk_ctx(sys_id, reqnot).await;
|
||||
let ctx = get_ctx(sys_id).await;
|
||||
take_atom(atom, &ctx).await.dyn_free(ctx.clone()).await
|
||||
}
|
||||
}
|
||||
}.boxed_local())
|
||||
}),
|
||||
{
|
||||
clone!(systems, logger, mk_ctx, interner_weak, obj_store, spawner, decls, msg_logger);
|
||||
clone!(logger, get_ctx, init_ctx, systems_weak, interner_weak, spawner, decls, msg_logger);
|
||||
move |hand, req| {
|
||||
clone!(systems, logger, mk_ctx, interner_weak, obj_store, spawner, decls, msg_logger);
|
||||
clone!(logger, get_ctx, init_ctx, systems_weak, interner_weak, spawner, decls, msg_logger);
|
||||
async move {
|
||||
let interner_cell = interner_weak.upgrade().expect("Interner dropped before request");
|
||||
let i = interner_cell.borrow().clone().expect("Request arrived before interner set");
|
||||
@@ -197,21 +210,13 @@ pub async fn extension_main_logic(data: ExtensionData, spawner: Spawner) {
|
||||
});
|
||||
let lazy_mems = Mutex::new(HashMap::new());
|
||||
let rules = Mutex::new(HashMap::new());
|
||||
let ctx = SysCtx {
|
||||
cted: cted.clone(),
|
||||
id: new_sys.id,
|
||||
logger: logger.clone(),
|
||||
reqnot: hand.reqnot(),
|
||||
i: i.clone(),
|
||||
obj_store: obj_store.clone(),
|
||||
spawner: spawner.clone(),
|
||||
};
|
||||
let ctx = init_ctx(new_sys.id, cted.clone(), hand.reqnot()).await;
|
||||
let const_root = stream::from_iter(cted.inst().dyn_env())
|
||||
.then(|(k, v)| {
|
||||
let (req, lazy_mems, rules) = (&hand, &lazy_mems, &rules);
|
||||
clone!(i, ctx; async move {
|
||||
let name = i.i(&k).await.to_api();
|
||||
let value = v.into_api(&mut TIACtxImpl {
|
||||
let value = v.into_api(&mut TreeIntoApiCtxImpl {
|
||||
lazy_members: &mut *lazy_mems.lock().await,
|
||||
rules: &mut *rules.lock().await,
|
||||
sys: ctx,
|
||||
@@ -229,17 +234,19 @@ pub async fn extension_main_logic(data: ExtensionData, spawner: Spawner) {
|
||||
let record = SystemRecord {
|
||||
declfs,
|
||||
vfses,
|
||||
cted,
|
||||
ctx,
|
||||
lazy_members: lazy_mems.into_inner(),
|
||||
rules: rules.into_inner(),
|
||||
};
|
||||
let systems = systems_weak.upgrade().expect("System constructed during shutdown");
|
||||
systems.lock().await.insert(new_sys.id, record);
|
||||
hand
|
||||
.handle(&new_sys, &api::SystemInst { lex_filter, const_root, line_types: vec![] })
|
||||
.await
|
||||
},
|
||||
api::HostExtReq::GetMember(get_tree @ api::GetMember(sys_id, tree_id)) => {
|
||||
let sys_ctx = mk_ctx(sys_id, hand.reqnot()).await;
|
||||
let sys_ctx = get_ctx(sys_id).await;
|
||||
let systems = systems_weak.upgrade().expect("Member queried during shutdown");
|
||||
let mut systems_g = systems.lock().await;
|
||||
let SystemRecord { lazy_members, rules, .. } =
|
||||
systems_g.get_mut(&sys_id).expect("System not found");
|
||||
@@ -248,8 +255,8 @@ pub async fn extension_main_logic(data: ExtensionData, spawner: Spawner) {
|
||||
Some(MemberRecord::Res) => panic!("This tree has already been transmitted"),
|
||||
Some(MemberRecord::Gen(path, cb)) => (path, cb),
|
||||
};
|
||||
let tree = cb.build(Sym::new(path.clone(), &i).await.unwrap()).await;
|
||||
let mut tia_ctx = TIACtxImpl {
|
||||
let tree = cb.build(Sym::new(path.clone(), &i).await.unwrap(), sys_ctx.clone()).await;
|
||||
let mut tia_ctx = TreeIntoApiCtxImpl {
|
||||
sys: sys_ctx,
|
||||
path: Substack::Bottom,
|
||||
basepath: &path,
|
||||
@@ -260,32 +267,33 @@ pub async fn extension_main_logic(data: ExtensionData, spawner: Spawner) {
|
||||
hand.handle(&get_tree, &tree.into_api(&mut tia_ctx).await).await
|
||||
},
|
||||
api::HostExtReq::VfsReq(api::VfsReq::GetVfs(get_vfs @ api::GetVfs(sys_id))) => {
|
||||
let systems = systems_weak.upgrade().expect("VFS root requested during shutdown");
|
||||
let systems_g = systems.lock().await;
|
||||
hand.handle(&get_vfs, &systems_g[&sys_id].declfs).await
|
||||
},
|
||||
api::HostExtReq::SysReq(api::SysReq::SysFwded(fwd)) => {
|
||||
let api::SysFwded(sys_id, payload) = fwd;
|
||||
let ctx = mk_ctx(sys_id, hand.reqnot()).await;
|
||||
let sys = ctx.cted.inst();
|
||||
let ctx = get_ctx(sys_id).await;
|
||||
let sys = ctx.cted().inst();
|
||||
sys.dyn_request(hand, payload).await
|
||||
},
|
||||
api::HostExtReq::VfsReq(api::VfsReq::VfsRead(vfs_read)) => {
|
||||
let api::VfsRead(sys_id, vfs_id, path) = &vfs_read;
|
||||
let ctx = mk_ctx(*sys_id, hand.reqnot()).await;
|
||||
let ctx = get_ctx(*sys_id).await;
|
||||
let systems = systems_weak.upgrade().expect("VFS requested during shutdoown");
|
||||
let systems_g = systems.lock().await;
|
||||
let path = join_all(path.iter().map(|t| Tok::from_api(*t, &i))).await;
|
||||
let vfs = systems_g[sys_id].vfses[vfs_id].load(&path, ctx).await;
|
||||
hand.handle(&vfs_read, &vfs).await
|
||||
},
|
||||
api::HostExtReq::LexExpr(lex @ api::LexExpr { sys, text, pos, id }) => {
|
||||
let systems_g = systems.lock().await;
|
||||
let lexers = systems_g[&sys].cted.inst().dyn_lexers();
|
||||
mem::drop(systems_g);
|
||||
let sys_ctx = get_ctx(sys).await;
|
||||
let text = Tok::from_api(text, &i).await;
|
||||
let ctx = LexContext { sys, id, pos, reqnot: hand.reqnot(), text: &text, i: &i };
|
||||
let trigger_char = text.chars().nth(pos as usize).unwrap();
|
||||
let err_na = err_not_applicable(&i).await;
|
||||
let err_cascade = err_cascade(&i).await;
|
||||
let lexers = sys_ctx.cted().inst().dyn_lexers();
|
||||
for lx in lexers.iter().filter(|l| char_filter_match(l.char_filter(), trigger_char)) {
|
||||
match lx.lex(&text[pos as usize..], &ctx).await {
|
||||
Err(e) if e.any(|e| *e == err_na) => continue,
|
||||
@@ -294,10 +302,9 @@ pub async fn extension_main_logic(data: ExtensionData, spawner: Spawner) {
|
||||
return hand.handle(&lex, &eopt).await;
|
||||
},
|
||||
Ok((s, expr)) => {
|
||||
let ctx = mk_ctx(sys, hand.reqnot()).await;
|
||||
let expr = expr
|
||||
.to_api(&mut |f, r| {
|
||||
clone!(ctx; async move { do_extra(f, r, ctx).await }).boxed_local()
|
||||
clone!(sys_ctx; async move { do_extra(f, r, sys_ctx).await }).boxed_local()
|
||||
})
|
||||
.await;
|
||||
let pos = (text.len() - s.len()) as u32;
|
||||
@@ -310,8 +317,8 @@ pub async fn extension_main_logic(data: ExtensionData, spawner: Spawner) {
|
||||
},
|
||||
api::HostExtReq::ParseLine(pline) => {
|
||||
let api::ParseLine { exported, comments, sys, line } = &pline;
|
||||
let mut ctx = mk_ctx(*sys, hand.reqnot()).await;
|
||||
let parsers = ctx.cted.inst().dyn_parsers();
|
||||
let mut ctx = get_ctx(*sys).await;
|
||||
let parsers = ctx.cted().inst().dyn_parsers();
|
||||
let comments = join_all(comments.iter().map(|c| Comment::from_api(c, &i))).await;
|
||||
let line: Vec<GenTokTree> = ttv_from_api(line, &mut ctx, &i).await;
|
||||
let snip = Snippet::new(line.first().expect("Empty line"), &line, &i);
|
||||
@@ -337,7 +344,7 @@ pub async fn extension_main_logic(data: ExtensionData, spawner: Spawner) {
|
||||
api::HostExtReq::AtomReq(atom_req) => {
|
||||
let atom = atom_req.get_atom();
|
||||
let atom_req = atom_req.clone();
|
||||
with_atom_record(&mk_ctx, hand.reqnot(), atom, move |nfo, ctx, id, buf| {
|
||||
with_atom_record(&get_ctx, atom, move |nfo, ctx, id, buf| {
|
||||
async move {
|
||||
let actx = AtomCtx(buf, atom.drop, ctx.clone());
|
||||
match &atom_req {
|
||||
@@ -389,16 +396,16 @@ pub async fn extension_main_logic(data: ExtensionData, spawner: Spawner) {
|
||||
api::HostExtReq::DeserAtom(deser) => {
|
||||
let api::DeserAtom(sys, buf, refs) = &deser;
|
||||
let mut read = &mut &buf[..];
|
||||
let ctx = mk_ctx(*sys, hand.reqnot()).await;
|
||||
let ctx = get_ctx(*sys).await;
|
||||
let id = AtomTypeId::decode(Pin::new(&mut read)).await;
|
||||
let inst = ctx.cted.inst();
|
||||
let inst = ctx.cted().inst();
|
||||
let nfo = atom_by_idx(inst.card(), id).expect("Deserializing atom with invalid ID");
|
||||
hand.handle(&deser, &nfo.deserialize(ctx.clone(), read, refs).await).await
|
||||
},
|
||||
orchid_api::HostExtReq::ApplyMacro(am) => {
|
||||
let tok = hand.will_handle_as(&am);
|
||||
let ApplyMacro { id, params, run_id, sys } = am;
|
||||
let sys_ctx = mk_ctx(sys, hand.reqnot()).await;
|
||||
let sys_ctx = get_ctx(sys).await;
|
||||
let mut ctx =
|
||||
RuleCtx { args: ahash::HashMap::default(), run_id, sys: sys_ctx.clone() };
|
||||
for (k, v) in params {
|
||||
@@ -408,6 +415,7 @@ pub async fn extension_main_logic(data: ExtensionData, spawner: Spawner) {
|
||||
);
|
||||
}
|
||||
let err_cascade = err_cascade(&i).await;
|
||||
let systems = systems_weak.upgrade().expect("macro call during shutdown");
|
||||
let systems_g = systems.lock().await;
|
||||
let rule = &systems_g[&sys].rules[&id];
|
||||
match (rule.apply)(ctx).await {
|
||||
@@ -432,7 +440,7 @@ pub async fn extension_main_logic(data: ExtensionData, spawner: Spawner) {
|
||||
}
|
||||
},
|
||||
);
|
||||
*interner_cell.borrow_mut() = Some(Rc::new(Interner::new_replica(rn.clone().map())));
|
||||
*interner_cell.borrow_mut() = Some(Interner::new_replica(rn.clone().map()));
|
||||
while !exiting.load(Ordering::Relaxed) {
|
||||
let rcvd = recv_parent_msg().await.unwrap();
|
||||
spawner(Box::pin(clone!(rn; async move { rn.receive(&rcvd).await })))
|
||||
|
||||
@@ -23,7 +23,7 @@ impl ExprHandle {
|
||||
pub(crate) fn from_args(ctx: SysCtx, tk: api::ExprTicket) -> Self { Self { ctx, tk } }
|
||||
pub fn get_ctx(&self) -> SysCtx { self.ctx.clone() }
|
||||
pub async fn clone(&self) -> Self {
|
||||
self.ctx.reqnot.notify(api::Acquire(self.ctx.id, self.tk)).await;
|
||||
self.ctx.reqnot().notify(api::Acquire(self.ctx.sys_id(), self.tk)).await;
|
||||
Self { ctx: self.ctx.clone(), tk: self.tk }
|
||||
}
|
||||
}
|
||||
@@ -34,9 +34,9 @@ impl fmt::Debug for ExprHandle {
|
||||
}
|
||||
impl Drop for ExprHandle {
|
||||
fn drop(&mut self) {
|
||||
let notif = api::Release(self.ctx.id, self.tk);
|
||||
let SysCtx { reqnot, spawner, .. } = self.ctx.clone();
|
||||
spawner(Box::pin(async move { reqnot.notify(notif).await }))
|
||||
let notif = api::Release(self.ctx.sys_id(), self.tk);
|
||||
let reqnot = self.ctx.reqnot().clone();
|
||||
self.ctx.spawner()(Box::pin(async move { reqnot.notify(notif).await }))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,13 +53,13 @@ impl Expr {
|
||||
|
||||
pub async fn data(&self) -> &ExprData {
|
||||
(self.data.get_or_init(async {
|
||||
let details = self.handle.ctx.reqnot.request(api::Inspect { target: self.handle.tk }).await;
|
||||
let pos = Pos::from_api(&details.location, &self.handle.ctx.i).await;
|
||||
let details = self.handle.ctx.reqnot().request(api::Inspect { target: self.handle.tk }).await;
|
||||
let pos = Pos::from_api(&details.location, self.handle.ctx.i()).await;
|
||||
let kind = match details.kind {
|
||||
api::InspectedKind::Atom(a) =>
|
||||
ExprKind::Atom(ForeignAtom::new(self.handle.clone(), a, pos.clone())),
|
||||
api::InspectedKind::Bottom(b) =>
|
||||
ExprKind::Bottom(OrcErrv::from_api(&b, &self.handle.ctx.i).await),
|
||||
ExprKind::Bottom(OrcErrv::from_api(&b, self.handle.ctx.i()).await),
|
||||
api::InspectedKind::Opaque => ExprKind::Opaque,
|
||||
};
|
||||
ExprData { pos, kind }
|
||||
@@ -83,7 +83,7 @@ impl Format for Expr {
|
||||
ExprKind::Opaque => "OPAQUE".to_string().into(),
|
||||
ExprKind::Bottom(b) => format!("Bottom({b})").into(),
|
||||
ExprKind::Atom(a) =>
|
||||
FmtUnit::from_api(&self.handle.ctx.reqnot.request(ExtAtomPrint(a.atom.clone())).await),
|
||||
FmtUnit::from_api(&self.handle.ctx.reqnot().request(ExtAtomPrint(a.atom.clone())).await),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ use never::Never;
|
||||
use orchid_api_traits::Encode;
|
||||
use orchid_base::clone;
|
||||
use orchid_base::error::OrcRes;
|
||||
use orchid_base::format::{FmtCtxImpl, Format, take_first};
|
||||
use orchid_base::name::Sym;
|
||||
use trait_set::trait_set;
|
||||
|
||||
@@ -22,7 +21,7 @@ use crate::atom_owned::{DeserializeCtx, OwnedAtom, OwnedVariant};
|
||||
use crate::conv::ToExpr;
|
||||
use crate::expr::{Expr, ExprHandle};
|
||||
use crate::gen_expr::GExpr;
|
||||
use crate::system::SysCtx;
|
||||
use crate::system::{SysCtx, SysCtxEntry};
|
||||
|
||||
trait_set! {
|
||||
trait FunCB = Fn(Vec<Expr>) -> LocalBoxFuture<'static, OrcRes<GExpr>> + 'static;
|
||||
@@ -33,9 +32,9 @@ pub trait ExprFunc<I, O>: Clone + 'static {
|
||||
fn apply(&self, v: Vec<Expr>) -> impl Future<Output = OrcRes<GExpr>>;
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
static FUNS: Rc<Mutex<HashMap<Sym, (u8, Rc<dyn FunCB>)>>> = Rc::default();
|
||||
}
|
||||
#[derive(Default)]
|
||||
struct FunsCtx(Mutex<HashMap<Sym, (u8, Rc<dyn FunCB>)>>);
|
||||
impl SysCtxEntry for FunsCtx {}
|
||||
|
||||
/// An Atom representing a partially applied named native function. These
|
||||
/// partial calls are serialized into the name of the native function and the
|
||||
@@ -50,9 +49,9 @@ pub(crate) struct Fun {
|
||||
fun: Rc<dyn FunCB>,
|
||||
}
|
||||
impl Fun {
|
||||
pub async fn new<I, O, F: ExprFunc<I, O>>(path: Sym, f: F) -> Self {
|
||||
let funs = FUNS.with(|funs| funs.clone());
|
||||
let mut fung = funs.lock().await;
|
||||
pub async fn new<I, O, F: ExprFunc<I, O>>(path: Sym, ctx: SysCtx, f: F) -> Self {
|
||||
let funs: &FunsCtx = ctx.get_or_default();
|
||||
let mut fung = funs.0.lock().await;
|
||||
let fun = if let Some(x) = fung.get(&path) {
|
||||
x.1.clone()
|
||||
} else {
|
||||
@@ -89,8 +88,8 @@ impl OwnedAtom for Fun {
|
||||
}
|
||||
async fn deserialize(mut ctx: impl DeserializeCtx, args: Self::Refs) -> Self {
|
||||
let sys = ctx.sys();
|
||||
let path = Sym::from_api(ctx.decode().await, &sys.i).await;
|
||||
let (arity, fun) = FUNS.with(|f| f.clone()).lock().await.get(&path).unwrap().clone();
|
||||
let path = Sym::from_api(ctx.decode().await, sys.i()).await;
|
||||
let (arity, fun) = sys.get_or_default::<FunsCtx>().0.lock().await.get(&path).unwrap().clone();
|
||||
Self { args, arity, path, fun }
|
||||
}
|
||||
async fn print(&self, _: SysCtx) -> orchid_base::format::FmtUnit {
|
||||
|
||||
@@ -4,10 +4,11 @@ use ahash::HashMap;
|
||||
use futures::future::{LocalBoxFuture, join_all};
|
||||
use itertools::Itertools;
|
||||
use never::Never;
|
||||
use orchid_api::ExtMsgSet;
|
||||
use orchid_base::error::OrcRes;
|
||||
use orchid_base::interner::Tok;
|
||||
use orchid_base::macros::{MTree, mtreev_from_api, mtreev_to_api};
|
||||
use orchid_base::reqnot::Requester;
|
||||
use orchid_base::reqnot::{ReqNot, Requester};
|
||||
use trait_set::trait_set;
|
||||
|
||||
use crate::api;
|
||||
@@ -44,11 +45,11 @@ impl<'a> RuleCtx<'a> {
|
||||
run_id: self.run_id,
|
||||
query: mtreev_to_api(tree, &mut |b| match *b {}).await,
|
||||
};
|
||||
let Some(treev) = self.sys.reqnot.request(req).await else {
|
||||
return Err(err_cascade(&self.sys.i).await.into());
|
||||
let Some(treev) = self.sys.get::<ReqNot<ExtMsgSet>>().request(req).await else {
|
||||
return Err(err_cascade(self.sys.i()).await.into());
|
||||
};
|
||||
static ATOM_MSG: &str = "Returned atom from Rule recursion";
|
||||
Ok(mtreev_from_api(&treev, &self.sys.i, &mut |_| panic!("{ATOM_MSG}")).await)
|
||||
Ok(mtreev_from_api(&treev, self.sys.i(), &mut |_| panic!("{ATOM_MSG}")).await)
|
||||
}
|
||||
pub fn getv(&mut self, key: &Tok<String>) -> Vec<MTree<'a, Never>> {
|
||||
self.args.remove(key).expect("Key not found")
|
||||
@@ -78,7 +79,7 @@ impl Rule {
|
||||
pub(crate) async fn into_api(self, ctx: &mut impl TreeIntoApiCtx) -> api::MacroRule {
|
||||
api::MacroRule {
|
||||
comments: join_all(self.comments.iter().map(|c| async {
|
||||
api::Comment { text: ctx.sys().i.i(c).await.to_api(), location: api::Location::Inherit }
|
||||
api::Comment { text: ctx.sys().i().i(c).await.to_api(), location: api::Location::Inherit }
|
||||
}))
|
||||
.await,
|
||||
location: api::Location::Inherit,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use core::fmt;
|
||||
use std::any::{TypeId, type_name};
|
||||
use std::any::{Any, TypeId, type_name};
|
||||
use std::fmt;
|
||||
use std::future::Future;
|
||||
use std::num::NonZero;
|
||||
use std::pin::Pin;
|
||||
@@ -7,6 +7,8 @@ use std::rc::Rc;
|
||||
|
||||
use futures::future::LocalBoxFuture;
|
||||
use hashbrown::HashMap;
|
||||
use memo_map::MemoMap;
|
||||
use orchid_api::ExtMsgSet;
|
||||
use orchid_api_traits::{Coding, Decode};
|
||||
use orchid_base::boxed_iter::BoxedIter;
|
||||
use orchid_base::builtin::Spawner;
|
||||
@@ -16,7 +18,6 @@ use orchid_base::reqnot::{Receipt, ReqNot};
|
||||
|
||||
use crate::api;
|
||||
use crate::atom::{AtomCtx, AtomDynfo, AtomTypeId, AtomicFeatures, ForeignAtom, TypAtom, get_info};
|
||||
use crate::atom_owned::ObjStore;
|
||||
use crate::entrypoint::ExtReq;
|
||||
use crate::fs::DeclFs;
|
||||
use crate::func_atom::Fun;
|
||||
@@ -116,11 +117,11 @@ where A: AtomicFeatures {
|
||||
let mut data = &foreign.atom.data[..];
|
||||
let ctx = foreign.ctx.clone();
|
||||
let value = AtomTypeId::decode(Pin::new(&mut data)).await;
|
||||
let own_inst = ctx.cted.inst();
|
||||
let owner = if ctx.id == foreign.atom.owner {
|
||||
let own_inst = ctx.get::<CtedObj>().inst();
|
||||
let owner = if *ctx.get::<api::SysId>() == foreign.atom.owner {
|
||||
own_inst.card()
|
||||
} else {
|
||||
(ctx.cted.deps().find(|s| s.id() == foreign.atom.owner))
|
||||
(ctx.get::<CtedObj>().deps().find(|s| s.id() == foreign.atom.owner))
|
||||
.ok_or_else(|| foreign.clone())?
|
||||
.get_card()
|
||||
};
|
||||
@@ -133,18 +134,80 @@ where A: AtomicFeatures {
|
||||
Ok(TypAtom { value, data: foreign })
|
||||
}
|
||||
|
||||
// #[derive(Clone)]
|
||||
// pub struct SysCtx {
|
||||
// pub reqnot: ReqNot<api::ExtMsgSet>,
|
||||
// pub spawner: Spawner,
|
||||
// pub id: api::SysId,
|
||||
// pub cted: CtedObj,
|
||||
// pub logger: Logger,
|
||||
// pub obj_store: ObjStore,
|
||||
// pub i: Rc<Interner>,
|
||||
// }
|
||||
// impl fmt::Debug for SysCtx {
|
||||
// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
// write!(f, "SysCtx({:?})", self.id)
|
||||
// }
|
||||
// }
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SysCtx {
|
||||
pub reqnot: ReqNot<api::ExtMsgSet>,
|
||||
pub spawner: Spawner,
|
||||
pub id: api::SysId,
|
||||
pub cted: CtedObj,
|
||||
pub logger: Logger,
|
||||
pub obj_store: ObjStore,
|
||||
pub i: Rc<Interner>,
|
||||
pub struct SysCtx(Rc<MemoMap<TypeId, Box<dyn Any>>>);
|
||||
impl SysCtx {
|
||||
pub fn new(
|
||||
id: api::SysId,
|
||||
i: Interner,
|
||||
reqnot: ReqNot<ExtMsgSet>,
|
||||
spawner: Spawner,
|
||||
logger: Logger,
|
||||
cted: CtedObj,
|
||||
) -> Self {
|
||||
let this = Self(Rc::new(MemoMap::new()));
|
||||
this.add(id).add(i).add(reqnot).add(spawner).add(logger).add(cted);
|
||||
this
|
||||
}
|
||||
pub fn add<T: SysCtxEntry>(&self, t: T) -> &Self {
|
||||
assert!(self.0.insert(TypeId::of::<T>(), Box::new(t)), "Key already exists");
|
||||
self
|
||||
}
|
||||
pub fn get_or_insert<T: SysCtxEntry>(&self, f: impl FnOnce() -> T) -> &T {
|
||||
(self.0.get_or_insert_owned(TypeId::of::<T>(), || Box::new(f())).downcast_ref())
|
||||
.expect("Keyed by TypeId")
|
||||
}
|
||||
pub fn get_or_default<T: SysCtxEntry + Default>(&self) -> &T {
|
||||
self.get_or_insert(|| {
|
||||
let rc_id = self.0.as_ref() as *const _ as *const () as usize;
|
||||
eprintln!("Default-initializing {} in {}", type_name::<T>(), rc_id);
|
||||
T::default()
|
||||
})
|
||||
}
|
||||
pub fn try_get<T: SysCtxEntry>(&self) -> Option<&T> {
|
||||
Some(self.0.get(&TypeId::of::<T>())?.downcast_ref().expect("Keyed by TypeId"))
|
||||
}
|
||||
pub fn get<T: SysCtxEntry>(&self) -> &T {
|
||||
self.try_get().unwrap_or_else(|| panic!("Context {} missing", type_name::<T>()))
|
||||
}
|
||||
/// Shorthand to get the [Interner] instance
|
||||
pub fn i(&self) -> &Interner { self.get::<Interner>() }
|
||||
/// Shorthand to get the messaging link
|
||||
pub fn reqnot(&self) -> &ReqNot<ExtMsgSet> { self.get::<ReqNot<ExtMsgSet>>() }
|
||||
/// Shorthand to get the system ID
|
||||
pub fn sys_id(&self) -> api::SysId { *self.get::<api::SysId>() }
|
||||
/// Shorthand to get the task spawner callback
|
||||
pub fn spawner(&self) -> &Spawner { self.get::<Spawner>() }
|
||||
/// Shorthand to get the logger
|
||||
pub fn logger(&self) -> &Logger { self.get::<Logger>() }
|
||||
/// Shorthand to get the constructed system object
|
||||
pub fn cted(&self) -> &CtedObj { self.get::<CtedObj>() }
|
||||
}
|
||||
impl fmt::Debug for SysCtx {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "SysCtx({:?})", self.id)
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "SysCtx({:?})", self.sys_id())
|
||||
}
|
||||
}
|
||||
pub trait SysCtxEntry: 'static + Sized {}
|
||||
impl SysCtxEntry for api::SysId {}
|
||||
impl SysCtxEntry for ReqNot<api::ExtMsgSet> {}
|
||||
impl SysCtxEntry for Spawner {}
|
||||
impl SysCtxEntry for CtedObj {}
|
||||
impl SysCtxEntry for Logger {}
|
||||
impl SysCtxEntry for Interner {}
|
||||
|
||||
@@ -46,7 +46,7 @@ pub struct GenItem {
|
||||
impl GenItem {
|
||||
pub async fn into_api(self, ctx: &mut impl TreeIntoApiCtx) -> api::Item {
|
||||
let kind = match self.kind {
|
||||
GenItemKind::Export(n) => api::ItemKind::Export(ctx.sys().i.i::<String>(&n).await.to_api()),
|
||||
GenItemKind::Export(n) => api::ItemKind::Export(ctx.sys().i().i::<String>(&n).await.to_api()),
|
||||
GenItemKind::Member(mem) => api::ItemKind::Member(mem.into_api(ctx).await),
|
||||
GenItemKind::Import(cn) => api::ItemKind::Import(cn.tok().to_api()),
|
||||
GenItemKind::Macro(priority, gen_rules) => {
|
||||
@@ -60,7 +60,7 @@ impl GenItem {
|
||||
let comments = join_all(self.comments.iter().map(|c| async {
|
||||
api::Comment {
|
||||
location: api::Location::Inherit,
|
||||
text: ctx.sys().i.i::<String>(c).await.to_api(),
|
||||
text: ctx.sys().i().i::<String>(c).await.to_api(),
|
||||
}
|
||||
}))
|
||||
.await;
|
||||
@@ -92,8 +92,8 @@ pub fn root_mod(
|
||||
(name.to_string(), kind)
|
||||
}
|
||||
pub fn fun<I, O>(exported: bool, name: &str, xf: impl ExprFunc<I, O>) -> Vec<GenItem> {
|
||||
let fac = LazyMemberFactory::new(move |sym| async {
|
||||
return MemKind::Const(build_lambdas(Fun::new(sym, xf).await, 0));
|
||||
let fac = LazyMemberFactory::new(move |sym, ctx| async {
|
||||
return MemKind::Const(build_lambdas(Fun::new(sym, ctx, xf).await, 0));
|
||||
fn build_lambdas(fun: Fun, i: u64) -> GExpr {
|
||||
if i < fun.arity().into() {
|
||||
return lambda(i, [build_lambdas(fun, i + 1)]);
|
||||
@@ -129,16 +129,16 @@ pub fn comments<'a>(
|
||||
|
||||
trait_set! {
|
||||
trait LazyMemberCallback =
|
||||
FnOnce(Sym) -> LocalBoxFuture<'static, MemKind> + DynClone
|
||||
FnOnce(Sym, SysCtx) -> LocalBoxFuture<'static, MemKind> + DynClone
|
||||
}
|
||||
pub struct LazyMemberFactory(Box<dyn LazyMemberCallback>);
|
||||
impl LazyMemberFactory {
|
||||
pub fn new<F: Future<Output = MemKind> + 'static>(
|
||||
cb: impl FnOnce(Sym) -> F + Clone + 'static,
|
||||
cb: impl FnOnce(Sym, SysCtx) -> F + Clone + 'static,
|
||||
) -> Self {
|
||||
Self(Box::new(|s| cb(s).boxed_local()))
|
||||
Self(Box::new(|s, ctx| cb(s, ctx).boxed_local()))
|
||||
}
|
||||
pub async fn build(self, path: Sym) -> MemKind { (self.0)(path).await }
|
||||
pub async fn build(self, path: Sym, ctx: SysCtx) -> MemKind { (self.0)(path, ctx).await }
|
||||
}
|
||||
impl Clone for LazyMemberFactory {
|
||||
fn clone(&self) -> Self { Self(clone_box(&*self.0)) }
|
||||
@@ -157,7 +157,7 @@ pub struct GenMember {
|
||||
}
|
||||
impl GenMember {
|
||||
pub async fn into_api(self, ctx: &mut impl TreeIntoApiCtx) -> api::Member {
|
||||
let name = ctx.sys().i.i::<String>(&self.name).await;
|
||||
let name = ctx.sys().i().i::<String>(&self.name).await;
|
||||
api::Member {
|
||||
kind: self.kind.into_api(&mut ctx.push_path(name.clone())).await,
|
||||
name: name.to_api(),
|
||||
@@ -197,7 +197,7 @@ pub trait TreeIntoApiCtx {
|
||||
fn req(&self) -> &impl ReqHandlish;
|
||||
}
|
||||
|
||||
pub struct TIACtxImpl<'a, 'b, RH: ReqHandlish> {
|
||||
pub struct TreeIntoApiCtxImpl<'a, 'b, RH: ReqHandlish> {
|
||||
pub sys: SysCtx,
|
||||
pub basepath: &'a [Tok<String>],
|
||||
pub path: Substack<'a, Tok<String>>,
|
||||
@@ -206,10 +206,10 @@ pub struct TIACtxImpl<'a, 'b, RH: ReqHandlish> {
|
||||
pub req: &'a RH,
|
||||
}
|
||||
|
||||
impl<RH: ReqHandlish> TreeIntoApiCtx for TIACtxImpl<'_, '_, RH> {
|
||||
impl<RH: ReqHandlish> TreeIntoApiCtx for TreeIntoApiCtxImpl<'_, '_, RH> {
|
||||
fn sys(&self) -> SysCtx { self.sys.clone() }
|
||||
fn push_path(&mut self, seg: Tok<String>) -> impl TreeIntoApiCtx {
|
||||
TIACtxImpl {
|
||||
TreeIntoApiCtxImpl {
|
||||
req: self.req,
|
||||
lazy_members: self.lazy_members,
|
||||
rules: self.rules,
|
||||
|
||||
Reference in New Issue
Block a user