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:
@@ -5,21 +5,22 @@ use futures::future::{LocalBoxFuture, join_all};
|
||||
use futures::{FutureExt, Stream, StreamExt};
|
||||
use itertools::Itertools;
|
||||
use never::Never;
|
||||
use orchid_base::error::{OrcErrv, OrcRes, Reporter};
|
||||
use orchid_base::error::{OrcErrv, OrcRes};
|
||||
use orchid_base::id_store::IdStore;
|
||||
use orchid_base::interner::{Interner, Tok};
|
||||
use orchid_base::interner::IStr;
|
||||
use orchid_base::location::SrcRange;
|
||||
use orchid_base::match_mapping;
|
||||
use orchid_base::name::Sym;
|
||||
use orchid_base::parse::{Comment, ParseCtx, Snippet};
|
||||
use orchid_base::reqnot::Requester;
|
||||
use orchid_base::parse::{Comment, Snippet};
|
||||
use orchid_base::tree::{TokTree, Token, ttv_into_api};
|
||||
use task_local::task_local;
|
||||
|
||||
use crate::api;
|
||||
use crate::context::{SysCtxEntry, ctx, i};
|
||||
use crate::conv::ToExpr;
|
||||
use crate::entrypoint::request;
|
||||
use crate::expr::Expr;
|
||||
use crate::gen_expr::GExpr;
|
||||
use crate::system::sys_id;
|
||||
use crate::tree::{GenTok, GenTokTree};
|
||||
|
||||
pub type PTok = Token<Expr, Never>;
|
||||
@@ -82,27 +83,21 @@ pub type ParserObj = &'static dyn DynParser;
|
||||
pub struct ParsCtx<'a> {
|
||||
_parse: PhantomData<&'a mut ()>,
|
||||
module: Sym,
|
||||
reporter: &'a Reporter,
|
||||
i: Interner,
|
||||
}
|
||||
impl<'a> ParsCtx<'a> {
|
||||
pub(crate) fn new(module: Sym, reporter: &'a Reporter) -> Self {
|
||||
Self { _parse: PhantomData, module, reporter, i: i() }
|
||||
}
|
||||
pub(crate) fn new(module: Sym) -> Self { Self { _parse: PhantomData, module } }
|
||||
pub fn module(&self) -> Sym { self.module.clone() }
|
||||
}
|
||||
impl ParseCtx for ParsCtx<'_> {
|
||||
fn i(&self) -> &Interner { &self.i }
|
||||
fn rep(&self) -> &Reporter { self.reporter }
|
||||
}
|
||||
|
||||
type BoxConstCallback = Box<dyn FnOnce(ConstCtx) -> LocalBoxFuture<'static, GExpr>>;
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct ParsedConstCtxEntry {
|
||||
pub(crate) consts: IdStore<BoxConstCallback>,
|
||||
task_local! {
|
||||
static PARSED_CONST_CTX: IdStore<BoxConstCallback>
|
||||
}
|
||||
|
||||
pub(crate) fn with_parsed_const_ctx<'a>(fut: LocalBoxFuture<'a, ()>) -> LocalBoxFuture<'a, ()> {
|
||||
Box::pin(PARSED_CONST_CTX.scope(IdStore::default(), fut))
|
||||
}
|
||||
impl SysCtxEntry for ParsedConstCtxEntry {}
|
||||
|
||||
pub struct ParsedLine {
|
||||
pub sr: SrcRange,
|
||||
@@ -114,7 +109,7 @@ impl ParsedLine {
|
||||
sr: &SrcRange,
|
||||
comments: impl IntoIterator<Item = &'a Comment>,
|
||||
exported: bool,
|
||||
name: Tok<String>,
|
||||
name: IStr,
|
||||
f: F,
|
||||
) -> Self {
|
||||
let cb = Box::new(|ctx| async move { f(ctx).await.to_gen().await }.boxed_local());
|
||||
@@ -126,7 +121,7 @@ impl ParsedLine {
|
||||
sr: &SrcRange,
|
||||
comments: impl IntoIterator<Item = &'a Comment>,
|
||||
exported: bool,
|
||||
name: &Tok<String>,
|
||||
name: &IStr,
|
||||
use_prelude: bool,
|
||||
lines: impl IntoIterator<Item = ParsedLine>,
|
||||
) -> Self {
|
||||
@@ -145,7 +140,7 @@ impl ParsedLine {
|
||||
exported: mem.exported,
|
||||
kind: match mem.kind {
|
||||
ParsedMemKind::Const(cb) => api::ParsedMemberKind::Constant(api::ParsedConstId(
|
||||
ctx().get_or_default::<ParsedConstCtxEntry>().consts.add(cb).id(),
|
||||
PARSED_CONST_CTX.with(|consts| consts.add(cb).id()),
|
||||
)),
|
||||
ParsedMemKind::Mod { lines, use_prelude } => api::ParsedMemberKind::Module {
|
||||
lines: linev_into_api(lines).boxed_local().await,
|
||||
@@ -170,7 +165,7 @@ pub enum ParsedLineKind {
|
||||
}
|
||||
|
||||
pub struct ParsedMem {
|
||||
pub name: Tok<String>,
|
||||
pub name: IStr,
|
||||
pub exported: bool,
|
||||
pub kind: ParsedMemKind,
|
||||
}
|
||||
@@ -191,14 +186,14 @@ impl ConstCtx {
|
||||
) -> impl Stream<Item = OrcRes<Sym>> + 'b {
|
||||
let resolve_names = api::ResolveNames {
|
||||
constid: self.constid,
|
||||
sys: ctx().sys_id(),
|
||||
sys: sys_id(),
|
||||
names: names.into_iter().map(|n| n.to_api()).collect_vec(),
|
||||
};
|
||||
stream(async |mut cx| {
|
||||
for name_opt in ctx().reqnot().request(resolve_names).await {
|
||||
for name_opt in request(resolve_names).await {
|
||||
cx.emit(match name_opt {
|
||||
Err(e) => Err(OrcErrv::from_api(&e, &i()).await),
|
||||
Ok(name) => Ok(Sym::from_api(name, &i()).await),
|
||||
Err(e) => Err(OrcErrv::from_api(&e).await),
|
||||
Ok(name) => Ok(Sym::from_api(name).await),
|
||||
})
|
||||
.await
|
||||
}
|
||||
@@ -210,8 +205,7 @@ impl ConstCtx {
|
||||
}
|
||||
|
||||
pub(crate) async fn get_const(id: api::ParsedConstId) -> GExpr {
|
||||
let cb = (ctx().get_or_default::<ParsedConstCtxEntry>().consts.get(id.0))
|
||||
.expect("Bad ID or double read of parsed const")
|
||||
.remove();
|
||||
let cb = PARSED_CONST_CTX
|
||||
.with(|ent| ent.get(id.0).expect("Bad ID or double read of parsed const").remove());
|
||||
cb(ConstCtx { constid: id }).await
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user