task_local context over context objects
- interner impls logically separate from API in orchid-base (default host interner still in base for testing) - error reporting, logging, and a variety of other features passed down via context in extension, not yet in host to maintain library-ish profile, should consider options - no global spawn mechanic, the host has a spawn function but extensions only get a stash for enqueuing async work in sync callbacks which is then explicitly, manually, and with strict order popped and awaited - still deadlocks nondeterministically for some ungodly reason
This commit is contained in:
@@ -1,15 +1,18 @@
|
||||
use std::cell::OnceCell;
|
||||
use std::cell::{OnceCell, RefCell};
|
||||
use std::rc::Rc;
|
||||
|
||||
use futures::FutureExt;
|
||||
use futures::future::LocalBoxFuture;
|
||||
use futures::lock::Mutex;
|
||||
use hashbrown::HashMap;
|
||||
use memo_map::MemoMap;
|
||||
use orchid_base::interner::Tok;
|
||||
use orchid_base::interner::{IStr, es, iv};
|
||||
use orchid_base::name::{NameLike, VPath};
|
||||
use orchid_base::reqnot::Requester;
|
||||
use task_local::task_local;
|
||||
|
||||
use crate::api;
|
||||
use crate::context::{SysCtxEntry, ctx, i};
|
||||
use crate::entrypoint::request;
|
||||
use crate::system::sys_id;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ReflMemData {
|
||||
@@ -33,29 +36,28 @@ pub enum ReflMemKind {
|
||||
pub struct ReflModData {
|
||||
inferred: Mutex<bool>,
|
||||
path: VPath,
|
||||
members: MemoMap<Tok<String>, ReflMem>,
|
||||
members: MemoMap<IStr, ReflMem>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ReflMod(Rc<ReflModData>);
|
||||
impl ReflMod {
|
||||
pub fn path(&self) -> &[Tok<String>] { &self.0.path[..] }
|
||||
pub fn path(&self) -> &[IStr] { &self.0.path[..] }
|
||||
pub fn is_root(&self) -> bool { self.0.path.is_empty() }
|
||||
async fn try_populate(&self) -> Result<(), api::LsModuleError> {
|
||||
let path_tok = i().i(&self.0.path[..]).await;
|
||||
let reply = match ctx().reqnot().request(api::LsModule(ctx().sys_id(), path_tok.to_api())).await
|
||||
{
|
||||
let path_tok = iv(&self.0.path[..]).await;
|
||||
let reply = match request(api::LsModule(sys_id(), path_tok.to_api())).await {
|
||||
Err(api::LsModuleError::TreeUnavailable) =>
|
||||
panic!("Reflected tree accessed outside an interpreter call. This extension is faulty."),
|
||||
Err(err) => return Err(err),
|
||||
Ok(details) => details,
|
||||
};
|
||||
for (k, v) in reply.members {
|
||||
let k = i().ex(k).await;
|
||||
let k = es(k).await;
|
||||
let mem = match self.0.members.get(&k) {
|
||||
Some(mem) => mem,
|
||||
None => {
|
||||
let path = self.0.path.clone().name_with_suffix(k.clone()).to_sym(&i()).await;
|
||||
let path = self.0.path.clone().name_with_suffix(k.clone()).to_sym().await;
|
||||
let kind = match v.kind {
|
||||
api::MemberInfoKind::Constant => ReflMemKind::Const,
|
||||
api::MemberInfoKind::Module =>
|
||||
@@ -68,7 +70,7 @@ impl ReflMod {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
pub async fn get_child(&self, key: &Tok<String>) -> Option<ReflMem> {
|
||||
pub async fn get_child(&self, key: &IStr) -> Option<ReflMem> {
|
||||
let inferred_g = self.0.inferred.lock().await;
|
||||
if let Some(mem) = self.0.members.get(key) {
|
||||
return Some(mem.clone());
|
||||
@@ -86,7 +88,7 @@ impl ReflMod {
|
||||
}
|
||||
self.0.members.get(key).cloned()
|
||||
}
|
||||
pub async fn get_by_path(&self, path: &[Tok<String>]) -> Result<ReflMem, InvalidPathError> {
|
||||
pub async fn get_by_path(&self, path: &[IStr]) -> Result<ReflMem, InvalidPathError> {
|
||||
let (next, tail) = path.split_first().expect("Attempted to walk by empty path");
|
||||
let inferred_g = self.0.inferred.lock().await;
|
||||
if let Some(next) = self.0.members.get(next) {
|
||||
@@ -130,9 +132,9 @@ impl ReflMod {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct ReflRoot(ReflMod);
|
||||
impl SysCtxEntry for ReflRoot {}
|
||||
task_local! {
|
||||
static REFL_ROOTS: RefCell<HashMap<api::SysId, ReflMod>>
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct InvalidPathError {
|
||||
@@ -150,8 +152,12 @@ fn default_member(is_root: bool, kind: ReflMemKind) -> ReflMem {
|
||||
}))
|
||||
}
|
||||
|
||||
fn get_root() -> ReflRoot {
|
||||
ctx().get_or_insert(|| ReflRoot(default_module(VPath::new([])))).clone()
|
||||
pub fn refl() -> ReflMod {
|
||||
REFL_ROOTS.with(|tbl| {
|
||||
tbl.borrow_mut().entry(sys_id()).or_insert_with(|| default_module(VPath::new([]))).clone()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn refl() -> ReflMod { get_root().0.clone() }
|
||||
pub fn with_refl_roots<'a>(fut: LocalBoxFuture<'a, ()>) -> LocalBoxFuture<'a, ()> {
|
||||
Box::pin(REFL_ROOTS.scope(RefCell::default(), fut))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user