temp commit

This commit is contained in:
2025-07-12 00:46:10 +02:00
parent 1868f1a506
commit fe89188c4b
60 changed files with 1536 additions and 709 deletions

View File

@@ -3,19 +3,18 @@ use std::fmt;
use std::future::Future;
use std::rc::{Rc, Weak};
use async_stream::stream;
use derive_destructure::destructure;
use futures::StreamExt;
use futures::FutureExt;
use futures::future::join_all;
use hashbrown::HashMap;
use itertools::Itertools;
use memo_map::MemoMap;
use orchid_base::char_filter::char_filter_match;
use orchid_base::clone;
use orchid_base::error::{OrcErrv, OrcRes};
use orchid_base::format::{FmtCtx, FmtUnit, Format};
use orchid_base::interner::{Interner, Tok};
use orchid_base::location::Pos;
use orchid_base::name::Sym;
use orchid_base::location::SrcRange;
use orchid_base::name::{NameLike, Sym, VName};
use orchid_base::parse::Comment;
use orchid_base::reqnot::{ReqNot, Requester};
use orchid_base::tree::ttv_from_api;
@@ -24,19 +23,25 @@ use substack::{Stackframe, Substack};
use crate::api;
use crate::ctx::Ctx;
use crate::expr::{Expr, ExprParseCtx};
use crate::dealias::{absolute_path, walk};
use crate::expr::{ExprParseCtx, ExprWillPanic};
use crate::expr_store::ExprStore;
use crate::extension::{Extension, WeakExtension};
use crate::parsed::{ItemKind, ParsTokTree, ParsedModule, Root};
use crate::tree::Module;
use crate::fs::{DeclFS, DeclMod};
use crate::parsed::{Item, ItemKind, ParsTokTree, ParsedMember, ParsedMemberKind, ParsedModule};
use crate::tree::Root;
#[derive(destructure)]
struct SystemInstData {
deps: Vec<System>,
ctx: Ctx,
ext: Extension,
decl_id: api::SysDeclId,
lex_filter: api::CharFilter,
id: api::SysId,
line_types: Vec<Tok<String>>,
vfs: std::collections::HashMap<api::TStr, api::EagerVfs>,
pub(crate) const_paths: MemoMap<api::ParsedConstId, Sym>,
}
impl Drop for SystemInstData {
fn drop(&mut self) { self.ext.system_drop(self.id); }
@@ -55,15 +60,29 @@ impl fmt::Debug for SystemInstData {
#[derive(Clone, Debug)]
pub struct System(Rc<SystemInstData>);
impl System {
#[must_use]
pub fn id(&self) -> api::SysId { self.0.id }
#[must_use]
pub fn ext(&self) -> &Extension { &self.0.ext }
#[must_use]
pub fn ctx(&self) -> &Ctx { &self.0.ctx }
#[must_use]
pub fn i(&self) -> &Interner { &self.0.ctx.i }
#[must_use]
pub fn deps(&self) -> &[System] { &self.0.deps }
#[must_use]
pub(crate) fn reqnot(&self) -> &ReqNot<api::HostMsgSet> { self.0.ext.reqnot() }
#[must_use]
pub async fn get_tree(&self, id: api::TreeId) -> api::MemberKind {
self.reqnot().request(api::GetMember(self.0.id, id)).await
}
#[must_use]
pub fn has_lexer(&self) -> bool { !self.0.lex_filter.0.is_empty() }
#[must_use]
pub async fn vfs(&self) -> DeclFS {
DeclFS::Eager(DeclMod::from_api(&self.0.vfs, self.clone()).await)
}
#[must_use]
pub fn can_lex(&self, c: char) -> bool { char_filter_match(&self.0.lex_filter, c) }
/// Have this system lex a part of the source. It is assumed that
/// [Self::can_lex] was called and returned true.
@@ -76,24 +95,26 @@ impl System {
) -> api::OrcResult<Option<api::LexedExpr>> {
self.0.ext.lex_req(source, src, pos, self.id(), r).await
}
#[must_use]
pub fn can_parse(&self, ltyp: Tok<String>) -> bool { self.0.line_types.contains(&ltyp) }
pub fn line_types(&self) -> impl Iterator<Item = &Tok<String>> + '_ { self.0.line_types.iter() }
pub async fn parse(
&self,
module: Sym,
path: Substack<'_, Tok<String>>,
line: Vec<ParsTokTree>,
exported: bool,
comments: Vec<Comment>,
) -> OrcRes<Vec<ParsTokTree>> {
callback: &mut impl AsyncFnMut(Substack<'_, Tok<String>>, Vec<ParsTokTree>) -> OrcRes<Vec<Item>>,
) -> OrcRes<Vec<Item>> {
let src_path = line.first().expect("cannot be empty").sr.path();
let line = join_all(line.into_iter().map(|t| async {
let mut expr_store = self.0.ext.exprs().clone();
t.into_api(&mut expr_store, &mut ()).await
t.into_api(&mut expr_store, &mut ExprWillPanic).await
}))
.await;
let comments = comments.iter().map(Comment::to_api).collect_vec();
let req = api::ParseLine {
module: module.to_api(),
module: self.i().i(&path.unreverse()).await.to_api(),
src: src_path.to_api(),
exported,
sys: self.id(),
@@ -101,14 +122,69 @@ impl System {
line,
};
match self.reqnot().request(req).await {
Ok(parsed) => {
let mut pctx = ExprParseCtx { ctx: self.ctx().clone(), exprs: self.ext().exprs().clone() };
Ok(parsed_v) => {
let mut ext_exprs = self.ext().exprs().clone();
Ok(ttv_from_api(parsed, &mut ext_exprs, &mut pctx, &src_path, self.i()).await)
struct ConvCtx<'a> {
sys: &'a System,
src_path: &'a Sym,
i: &'a Interner,
ext_exprs: &'a mut ExprStore,
pctx: &'a mut ExprParseCtx<'a>,
}
async fn conv(
parsed_v: Vec<api::ParsedLine>,
module: Substack<'_, Tok<String>>,
callback: &'_ mut impl AsyncFnMut(
Substack<'_, Tok<String>>,
Vec<ParsTokTree>,
) -> OrcRes<Vec<Item>>,
ctx: &mut ConvCtx<'_>,
) -> OrcRes<Vec<Item>> {
let mut items = Vec::new();
for parsed in parsed_v {
let (name, exported, kind) = match parsed.kind {
api::ParsedLineKind::Member(api::ParsedMember { name, exported, kind }) =>
(name, exported, kind),
api::ParsedLineKind::Recursive(rec) => {
let tokens = ttv_from_api(rec, ctx.ext_exprs, ctx.pctx, ctx.src_path, ctx.i).await;
items.extend(callback(module.clone(), tokens).await?);
continue;
},
};
let name = ctx.i.ex(name).await;
let mkind = match kind {
api::ParsedMemberKind::Module(items) => {
let items =
conv(items, module.push(name.clone()), callback, ctx).boxed_local().await?;
ParsedMemberKind::Mod(ParsedModule::new(items))
},
api::ParsedMemberKind::Constant(cid) =>
ParsedMemberKind::DeferredConst(cid, ctx.sys.clone()),
};
items.push(Item {
comments: join_all(
parsed.comments.iter().map(|c| Comment::from_api(c, ctx.src_path.clone(), ctx.i)),
)
.await,
sr: SrcRange::from_api(&parsed.source_range, ctx.i).await,
kind: ItemKind::Member(ParsedMember { name, exported, kind: mkind }),
})
}
Ok(items)
}
conv(parsed_v, path, callback, &mut ConvCtx {
i: self.i(),
ext_exprs: &mut ext_exprs,
pctx: &mut ExprParseCtx { ctx: self.ctx(), exprs: self.ext().exprs() },
src_path: &src_path,
sys: self,
})
.await
},
Err(e) => Err(OrcErrv::from_api(&e, &self.ctx().i).await),
}
}
#[must_use]
pub async fn request(&self, req: Vec<u8>) -> Vec<u8> {
self.reqnot().request(api::SysFwded(self.id(), req)).await
}
@@ -118,7 +194,24 @@ impl System {
this.ctx.owned_atoms.write().await.remove(&drop);
}))
}
#[must_use]
pub fn downgrade(&self) -> WeakSystem { WeakSystem(Rc::downgrade(&self.0)) }
/// Implementation of [api::ResolveNames]
pub(crate) async fn name_resolver(
&self,
orig: api::ParsedConstId,
) -> impl AsyncFnMut(&[Tok<String>]) -> Option<VName> + use<> {
let root = self.0.ctx.root.read().await.upgrade().expect("find_names when root not in context");
let orig = self.0.const_paths.get(&orig).expect("origin for find_names invalid").clone();
let ctx = self.0.ctx.clone();
async move |rel| {
let cwd = orig.split_last().1;
let abs = absolute_path(cwd, rel, &ctx.i).await.ok()?;
let root_data = &mut *root.0.write().await;
let walk_ctx = &mut (ctx.clone(), &mut root_data.consts);
walk(&root_data.root, false, abs.iter(), walk_ctx).await.is_ok().then_some(abs)
}
}
}
impl Format for System {
async fn print<'a>(&'a self, _c: &'a (impl FmtCtx + ?Sized + 'a)) -> FmtUnit {
@@ -130,6 +223,7 @@ impl Format for System {
pub struct WeakSystem(Weak<SystemInstData>);
impl WeakSystem {
#[must_use]
pub fn upgrade(&self) -> Option<System> { self.0.upgrade().map(System) }
}
@@ -138,56 +232,42 @@ pub struct SystemCtor {
pub(crate) ext: WeakExtension,
}
impl SystemCtor {
#[must_use]
pub fn name(&self) -> &str { &self.decl.name }
#[must_use]
pub fn priority(&self) -> NotNan<f64> { self.decl.priority }
#[must_use]
pub fn depends(&self) -> impl ExactSizeIterator<Item = &str> {
self.decl.depends.iter().map(|s| &**s)
}
#[must_use]
pub fn id(&self) -> api::SysDeclId { self.decl.id }
pub async fn run<'a>(
&self,
depends: impl IntoIterator<Item = &'a System>,
consts: &mut HashMap<Sym, Expr>,
) -> (Module, System) {
let depends = depends.into_iter().map(|si| si.id()).collect_vec();
#[must_use]
pub async fn run(&self, deps: Vec<System>) -> (Root, System) {
let depends = deps.iter().map(|si| si.id()).collect_vec();
debug_assert_eq!(depends.len(), self.decl.depends.len(), "Wrong number of deps provided");
let ext = self.ext.upgrade().expect("SystemCtor should be freed before Extension");
let id = ext.ctx().next_sys_id();
let sys_inst = ext.reqnot().request(api::NewSystem { depends, id, system: self.decl.id }).await;
let data = System(Rc::new(SystemInstData {
deps,
decl_id: self.decl.id,
ext: ext.clone(),
ctx: ext.ctx().clone(),
lex_filter: sys_inst.lex_filter,
vfs: sys_inst.vfs,
line_types: join_all(sys_inst.line_types.iter().map(|m| Tok::from_api(*m, &ext.ctx().i)))
.await,
id,
const_paths: MemoMap::new(),
}));
let const_root =
Module::from_api((sys_inst.const_root.into_iter()).map(|(k, v)| api::Member {
name: k,
kind: v,
comments: vec![],
exported: true,
}))
.await;
let const_root = clone!(data, ext; stream! {
for (k, v) in sys_inst.const_root {
yield Member::from_api(
,
&mut ParsedFromApiCx {
consts,
path: ext.ctx().i.i(&[]).await,
sys: &data,
}
).await;
}
})
.map(|mem| ItemKind::Member(mem).at(Pos::None))
.collect::<Vec<_>>()
.await;
let api_module_root = api::Module {
members: (sys_inst.const_root.into_iter())
.map(|(k, v)| api::Member { name: k, kind: v, comments: vec![], exported: true })
.collect_vec(),
};
let root = Root::from_api(api_module_root, &data).await;
ext.ctx().systems.write().await.insert(id, data.downgrade());
let root = ParsedModule::new(const_root);
(root, data)
}
}
@@ -219,7 +299,6 @@ pub async fn init_systems(
fn walk_deps<'a>(
graph: &mut HashMap<&str, &'a SystemCtor>,
list: &mut Vec<&'a SystemCtor>,
consts: &mut HashMap<Sym, Expr>,
chain: Stackframe<&str>,
) -> Result<(), SysResolvErr> {
if let Some(ctor) = graph.remove(chain.item) {
@@ -231,22 +310,21 @@ pub async fn init_systems(
circle.extend(Substack::Frame(chain).iter().map(|s| s.to_string()));
return Err(SysResolvErr::Loop(circle));
}
walk_deps(graph, list, consts, Substack::Frame(chain).new_frame(dep))?
walk_deps(graph, list, Substack::Frame(chain).new_frame(dep))?
}
list.push(ctor);
}
Ok(())
}
let mut consts = HashMap::new();
for tgt in tgts {
walk_deps(&mut to_load, &mut to_load_ordered, &mut consts, Substack::Bottom.new_frame(tgt))?;
walk_deps(&mut to_load, &mut to_load_ordered, Substack::Bottom.new_frame(tgt))?;
}
let mut systems = HashMap::<&str, System>::new();
let mut root_mod = ParsedModule::default();
let mut root = Root::new(exts.first().unwrap().ctx().clone());
for ctor in to_load_ordered.iter() {
let (sys_root, sys) = ctor.run(ctor.depends().map(|n| &systems[n]), &mut consts).await;
let (sys_root, sys) = ctor.run(ctor.depends().map(|n| systems[n].clone()).collect()).await;
systems.insert(ctor.name(), sys);
root_mod.merge(sys_root);
root = root.merge(&sys_root).await.expect("Conflicting roots");
}
Ok((Root::new(root_mod, consts), systems.into_values().collect_vec()))
Ok((root, systems.into_values().collect_vec()))
}