forked from Orchid/orchid
116 lines
3.4 KiB
Rust
116 lines
3.4 KiB
Rust
use futures::FutureExt;
|
|
use futures::future::join_all;
|
|
use itertools::Itertools;
|
|
use orchid_base::error::{OrcErrv, OrcRes};
|
|
use orchid_base::interner::{Interner, Tok};
|
|
use orchid_base::location::SrcRange;
|
|
use orchid_base::name::Sym;
|
|
use orchid_base::parse::Comment;
|
|
use orchid_base::reqnot::Requester;
|
|
use orchid_base::tree::ttv_from_api;
|
|
use substack::Substack;
|
|
|
|
use crate::api;
|
|
use crate::expr_store::ExprStore;
|
|
use crate::parse::HostParseCtx;
|
|
use crate::parsed::{
|
|
Item, ItemKind, ParsTokTree, ParsedMember, ParsedMemberKind, ParsedModule, tt_to_api,
|
|
};
|
|
use crate::system::System;
|
|
|
|
pub struct Parser {
|
|
pub(crate) system: System,
|
|
pub(crate) idx: u16,
|
|
}
|
|
type ModPath<'a> = Substack<'a, Tok<String>>;
|
|
|
|
impl Parser {
|
|
pub async fn parse(
|
|
&self,
|
|
ctx: &impl HostParseCtx,
|
|
path: ModPath<'_>,
|
|
line: Vec<ParsTokTree>,
|
|
exported: bool,
|
|
comments: Vec<Comment>,
|
|
callback: &mut impl AsyncFnMut(ModPath<'_>, Vec<ParsTokTree>) -> OrcRes<Vec<Item>>,
|
|
) -> OrcRes<Vec<Item>> {
|
|
let mut temp_store = self.system.ctx().exprs.derive();
|
|
let src_path = line.first().expect("cannot be empty").sr.path();
|
|
let line =
|
|
join_all((line.into_iter()).map(|t| async { tt_to_api(&mut temp_store.clone(), t).await }))
|
|
.await;
|
|
let mod_path = ctx.src_path().suffix(path.unreverse(), self.system.i()).await;
|
|
let comments = comments.iter().map(Comment::to_api).collect_vec();
|
|
let req = api::ParseLine {
|
|
idx: self.idx,
|
|
module: mod_path.to_api(),
|
|
src: src_path.to_api(),
|
|
exported,
|
|
sys: self.system.id(),
|
|
comments,
|
|
line,
|
|
};
|
|
match self.system.reqnot().request(req).await {
|
|
Ok(parsed_v) =>
|
|
conv(parsed_v, path, callback, &mut ConvCtx {
|
|
i: self.system.i(),
|
|
mod_path: &mod_path,
|
|
ext_exprs: &mut temp_store,
|
|
src_path: &src_path,
|
|
sys: &self.system,
|
|
})
|
|
.await,
|
|
Err(e) => Err(OrcErrv::from_api(&e, &self.system.ctx().i).await),
|
|
}
|
|
}
|
|
}
|
|
|
|
struct ConvCtx<'a> {
|
|
sys: &'a System,
|
|
mod_path: &'a Sym,
|
|
src_path: &'a Sym,
|
|
i: &'a Interner,
|
|
ext_exprs: &'a mut ExprStore,
|
|
}
|
|
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, &mut ctx.sys.ctx().clone(), ctx.src_path, ctx.i).await;
|
|
items.extend(callback(module.clone(), tokens).await?);
|
|
continue;
|
|
},
|
|
};
|
|
let name = ctx.i.ex(name).await;
|
|
let mem_path = module.push(name.clone());
|
|
let mkind = match kind {
|
|
api::ParsedMemberKind::Module { lines, use_prelude } => {
|
|
let items = conv(lines, mem_path, callback, ctx).boxed_local().await?;
|
|
ParsedMemberKind::Mod(ParsedModule::new(use_prelude, items))
|
|
},
|
|
api::ParsedMemberKind::Constant(cid) => {
|
|
ctx.sys.0.const_paths.insert(cid, ctx.mod_path.suffix(mem_path.unreverse(), ctx.i).await);
|
|
ParsedMemberKind::Const(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)
|
|
}
|