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:
@@ -13,11 +13,11 @@ use hashbrown::hash_map::Entry;
|
||||
use itertools::Itertools;
|
||||
use memo_map::MemoMap;
|
||||
use orchid_base::clone;
|
||||
use orchid_base::error::{OrcRes, Reporter, mk_errv};
|
||||
use orchid_base::interner::Tok;
|
||||
use orchid_base::error::{OrcRes, mk_errv, report};
|
||||
use orchid_base::interner::{IStr, IStrv, es, is, iv};
|
||||
use orchid_base::location::{CodeGenInfo, Pos};
|
||||
use orchid_base::name::{NameLike, Sym, VPath};
|
||||
use orchid_base::reqnot::Requester;
|
||||
use orchid_base::reqnot::ClientExt;
|
||||
|
||||
use crate::api;
|
||||
use crate::ctx::Ctx;
|
||||
@@ -45,7 +45,7 @@ impl Root {
|
||||
#[must_use]
|
||||
pub async fn from_api(api: api::Module, sys: &System) -> Self {
|
||||
let consts = MemoMap::new();
|
||||
let mut tfac = TreeFromApiCtx { consts: &consts, path: sys.i().i(&[][..]).await, sys };
|
||||
let mut tfac = TreeFromApiCtx { consts: &consts, path: iv(&[][..]).await, sys };
|
||||
let root = Module::from_api(api, &mut tfac).await;
|
||||
Root(Rc::new(RwLock::new(RootData { root, consts, ctx: sys.ctx().clone() })))
|
||||
}
|
||||
@@ -60,7 +60,7 @@ impl Root {
|
||||
Ok(Self(Rc::new(RwLock::new(RootData { root, consts, ctx: this.ctx.clone() }))))
|
||||
}
|
||||
#[must_use]
|
||||
pub async fn add_parsed(&self, parsed: &ParsedModule, pars_prefix: Sym, rep: &Reporter) -> Self {
|
||||
pub async fn add_parsed(&self, parsed: &ParsedModule, pars_prefix: Sym) -> Self {
|
||||
let mut ref_this = self.0.write().await;
|
||||
let this = &mut *ref_this;
|
||||
let mut deferred_consts = HashMap::new();
|
||||
@@ -72,7 +72,6 @@ impl Root {
|
||||
pars_prefix: pars_prefix.clone(),
|
||||
root: &this.root,
|
||||
ctx: &this.ctx,
|
||||
rep,
|
||||
};
|
||||
let mut module = Module::from_parsed(parsed, pars_prefix.clone(), &mut tfpctx).await;
|
||||
for step in pars_prefix.iter().rev() {
|
||||
@@ -89,7 +88,7 @@ impl Root {
|
||||
*this.ctx.root.write().await = new.downgrade();
|
||||
for (path, (sys_id, pc_id)) in deferred_consts {
|
||||
let sys = this.ctx.system_inst(sys_id).await.expect("System dropped since parsing");
|
||||
let api_expr = sys.reqnot().request(api::FetchParsedConst(sys.id(), pc_id)).await;
|
||||
let api_expr = sys.client().request(api::FetchParsedConst(sys.id(), pc_id)).await.unwrap();
|
||||
let expr = Expr::from_api(&api_expr, PathSetBuilder::new(), this.ctx.clone()).await;
|
||||
new.0.write().await.consts.insert(path, expr);
|
||||
}
|
||||
@@ -110,7 +109,7 @@ impl Root {
|
||||
}
|
||||
match module {
|
||||
Ok(_) => Err(mk_errv(
|
||||
ctx.i.i("module used as constant").await,
|
||||
is("module used as constant").await,
|
||||
format!("{name} is a module, not a constant"),
|
||||
[pos],
|
||||
)),
|
||||
@@ -118,7 +117,7 @@ impl Root {
|
||||
ChildErrorKind::Private => panic!("public_only is false"),
|
||||
ChildErrorKind::Constant => panic!("Tree refers to constant not in table"),
|
||||
ChildErrorKind::Missing => Err(mk_errv(
|
||||
ctx.i.i("Constant does not exist").await,
|
||||
is("Constant does not exist").await,
|
||||
format!("{name} does not refer to a constant"),
|
||||
[pos],
|
||||
)),
|
||||
@@ -144,12 +143,12 @@ impl Default for WeakRoot {
|
||||
pub struct TreeFromApiCtx<'a> {
|
||||
pub sys: &'a System,
|
||||
pub consts: &'a MemoMap<Sym, Expr>,
|
||||
pub path: Tok<Vec<Tok<String>>>,
|
||||
pub path: IStrv,
|
||||
}
|
||||
impl<'a> TreeFromApiCtx<'a> {
|
||||
#[must_use]
|
||||
pub async fn push<'c>(&'c self, name: Tok<String>) -> TreeFromApiCtx<'c> {
|
||||
let path = self.sys.ctx().i.i(&self.path.iter().cloned().chain([name]).collect_vec()).await;
|
||||
pub async fn push<'c>(&'c self, name: IStr) -> TreeFromApiCtx<'c> {
|
||||
let path = iv(&self.path.iter().cloned().chain([name]).collect_vec()).await;
|
||||
TreeFromApiCtx { path, consts: self.consts, sys: self.sys }
|
||||
}
|
||||
}
|
||||
@@ -162,17 +161,17 @@ pub struct ResolvedImport {
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct Module {
|
||||
pub imports: HashMap<Tok<String>, Result<ResolvedImport, Vec<ResolvedImport>>>,
|
||||
pub members: HashMap<Tok<String>, Rc<Member>>,
|
||||
pub imports: HashMap<IStr, Result<ResolvedImport, Vec<ResolvedImport>>>,
|
||||
pub members: HashMap<IStr, Rc<Member>>,
|
||||
}
|
||||
impl Module {
|
||||
#[must_use]
|
||||
pub async fn from_api(api: api::Module, ctx: &mut TreeFromApiCtx<'_>) -> Self {
|
||||
let mut members = HashMap::new();
|
||||
for mem in api.members {
|
||||
let mem_name = ctx.sys.i().ex(mem.name).await;
|
||||
let mem_name = es(mem.name).await;
|
||||
let vname = VPath::new(ctx.path.iter().cloned()).name_with_suffix(mem_name.clone());
|
||||
let name = vname.to_sym(ctx.sys.i()).await;
|
||||
let name = vname.to_sym().await;
|
||||
let (lazy, kind) = match mem.kind {
|
||||
api::MemberKind::Lazy(id) =>
|
||||
(Some(LazyMemberHandle { id, sys: ctx.sys.id(), path: name.clone() }), None),
|
||||
@@ -205,23 +204,23 @@ impl Module {
|
||||
let mut glob_imports_by_name = HashMap::<_, Vec<_>>::new();
|
||||
for import in parsed.get_imports().into_iter().filter(|i| i.name.is_none()) {
|
||||
let pos = import.sr.pos();
|
||||
match absolute_path(&path, &import.path, &ctx.ctx.i).await {
|
||||
Err(e) => ctx.rep.report(e.err_obj(&ctx.ctx.i, pos, &import.path.to_string()).await),
|
||||
match absolute_path(&path, &import.path).await {
|
||||
Err(e) => report(e.err_obj(pos, &import.path.to_string()).await),
|
||||
Ok(abs_path) => {
|
||||
let names_res = match abs_path.strip_prefix(&ctx.pars_prefix[..]) {
|
||||
None => {
|
||||
let mut tree_ctx = (ctx.ctx.clone(), ctx.consts);
|
||||
resolv_glob(&path, ctx.root, &abs_path, pos, &ctx.ctx.i, &mut tree_ctx).await
|
||||
resolv_glob(&path, ctx.root, &abs_path, pos, &mut tree_ctx).await
|
||||
},
|
||||
Some(sub_tgt) => {
|
||||
let sub_path = (path.strip_prefix(&ctx.pars_prefix[..]))
|
||||
.expect("from_parsed called with path outside pars_prefix");
|
||||
resolv_glob(sub_path, ctx.pars_root, sub_tgt, pos, &ctx.ctx.i, &mut ()).await
|
||||
resolv_glob(sub_path, ctx.pars_root, sub_tgt, pos, &mut ()).await
|
||||
},
|
||||
};
|
||||
let abs_path = abs_path.to_sym(&ctx.ctx.i).await;
|
||||
let abs_path = abs_path.to_sym().await;
|
||||
match names_res {
|
||||
Err(e) => ctx.rep.report(e),
|
||||
Err(e) => report(e),
|
||||
Ok(names) =>
|
||||
for name in names {
|
||||
match glob_imports_by_name.entry(name) {
|
||||
@@ -244,30 +243,28 @@ impl Module {
|
||||
prelude_item.last_seg(),
|
||||
Ok(ResolvedImport {
|
||||
target: prelude_item,
|
||||
pos: CodeGenInfo::new_details(sys.ctor().name_tok().await, "In prelude", &ctx.ctx.i)
|
||||
.await
|
||||
.pos(),
|
||||
pos: CodeGenInfo::new_details(sys.ctor().name_tok().await, "In prelude").await.pos(),
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
let conflicting_imports_msg = ctx.ctx.i.i("Conflicting imports").await;
|
||||
let conflicting_imports_msg = is("Conflicting imports").await;
|
||||
for (key, values) in imports_by_name {
|
||||
if values.len() == 1 {
|
||||
let import = values.into_iter().next().unwrap();
|
||||
let sr = import.sr.clone();
|
||||
let abs_path_res = absolute_path(&path, &import.clone().mspath(), &ctx.ctx.i).await;
|
||||
let abs_path_res = absolute_path(&path, &import.clone().mspath()).await;
|
||||
match abs_path_res {
|
||||
Err(e) => ctx.rep.report(e.err_obj(&ctx.ctx.i, sr.pos(), &import.to_string()).await),
|
||||
Err(e) => report(e.err_obj(sr.pos(), &import.to_string()).await),
|
||||
Ok(abs_path) => {
|
||||
let target = abs_path.to_sym(&ctx.ctx.i).await;
|
||||
let target = abs_path.to_sym().await;
|
||||
imports.insert(key, Ok(ResolvedImport { target, pos: sr.pos() }));
|
||||
},
|
||||
}
|
||||
} else {
|
||||
for item in values {
|
||||
ctx.rep.report(mk_errv(
|
||||
report(mk_errv(
|
||||
conflicting_imports_msg.clone(),
|
||||
format!("{key} is imported multiple times from different modules"),
|
||||
[item.sr.pos()],
|
||||
@@ -277,12 +274,11 @@ impl Module {
|
||||
}
|
||||
for (key, values) in glob_imports_by_name {
|
||||
if !imports.contains_key(&key) {
|
||||
let i = &ctx.ctx.i;
|
||||
let values = stream::iter(values)
|
||||
.then(|(n, sr)| {
|
||||
clone!(key; async move {
|
||||
ResolvedImport {
|
||||
target: n.to_vname().suffix([key.clone()]).to_sym(i).await,
|
||||
target: n.to_vname().suffix([key.clone()]).to_sym().await,
|
||||
pos: sr.pos(),
|
||||
}
|
||||
})
|
||||
@@ -292,12 +288,12 @@ impl Module {
|
||||
imports.insert(key, if values.len() == 1 { Ok(values[0].clone()) } else { Err(values) });
|
||||
}
|
||||
}
|
||||
let self_referential_msg = ctx.ctx.i.i("Self-referential import").await;
|
||||
let self_referential_msg = is("Self-referential import").await;
|
||||
for (key, value) in imports.iter() {
|
||||
let Ok(import) = value else { continue };
|
||||
if import.target.strip_prefix(&path[..]).is_some_and(|t| t.starts_with(slice::from_ref(key)))
|
||||
{
|
||||
ctx.rep.report(mk_errv(
|
||||
report(mk_errv(
|
||||
self_referential_msg.clone(),
|
||||
format!("import {} points to itself or a path within itself", &import.target),
|
||||
[import.pos.clone()],
|
||||
@@ -308,7 +304,7 @@ impl Module {
|
||||
for item in &parsed.items {
|
||||
match &item.kind {
|
||||
ItemKind::Member(mem) => {
|
||||
let path = path.to_vname().suffix([mem.name.clone()]).to_sym(&ctx.ctx.i).await;
|
||||
let path = path.to_vname().suffix([mem.name.clone()]).to_sym().await;
|
||||
let kind = OnceCell::from(MemberKind::from_parsed(&mem.kind, path.clone(), ctx).await);
|
||||
members.insert(
|
||||
mem.name.clone(),
|
||||
@@ -385,7 +381,6 @@ pub struct FromParsedCtx<'a> {
|
||||
pars_prefix: Sym,
|
||||
pars_root: &'a ParsedModule,
|
||||
root: &'a Module,
|
||||
rep: &'a Reporter,
|
||||
ctx: &'a Ctx,
|
||||
consts: &'a MemoMap<Sym, Expr>,
|
||||
deferred_consts: &'a mut HashMap<Sym, (api::SysId, api::ParsedConstId)>,
|
||||
@@ -395,7 +390,7 @@ impl Tree for Module {
|
||||
type Ctx<'a> = (Ctx, &'a MemoMap<Sym, Expr>);
|
||||
async fn child(
|
||||
&self,
|
||||
key: Tok<String>,
|
||||
key: IStr,
|
||||
public_only: bool,
|
||||
(ctx, consts): &mut Self::Ctx<'_>,
|
||||
) -> crate::dealias::ChildResult<'_, Self> {
|
||||
@@ -410,7 +405,7 @@ impl Tree for Module {
|
||||
MemberKind::Const => Err(ChildErrorKind::Constant),
|
||||
}
|
||||
}
|
||||
fn children(&self, public_only: bool) -> hashbrown::HashSet<Tok<String>> {
|
||||
fn children(&self, public_only: bool) -> hashbrown::HashSet<IStr> {
|
||||
self.members.iter().filter(|(_, v)| !public_only || v.public).map(|(k, _)| k.clone()).collect()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user