Initial extension asynchronization efforts.
This commit is contained in:
@@ -1,16 +1,16 @@
|
||||
use std::future::Future;
|
||||
use std::num::NonZero;
|
||||
use std::ops::Range;
|
||||
use std::rc::Rc;
|
||||
|
||||
use dyn_clone::{DynClone, clone_box};
|
||||
use futures::FutureExt;
|
||||
use futures::future::{LocalBoxFuture, join_all};
|
||||
use hashbrown::HashMap;
|
||||
use itertools::Itertools;
|
||||
use orchid_base::interner::{Tok, intern};
|
||||
use orchid_base::location::Pos;
|
||||
use orchid_base::interner::Tok;
|
||||
use orchid_base::name::Sym;
|
||||
use orchid_base::parse::Comment;
|
||||
use orchid_base::reqnot::ReqHandlish;
|
||||
use orchid_base::tree::{TokTree, Token};
|
||||
use ordered_float::NotNan;
|
||||
use substack::Substack;
|
||||
@@ -20,47 +20,56 @@ use crate::api;
|
||||
use crate::atom::{AtomFactory, ForeignAtom};
|
||||
use crate::conv::ToExpr;
|
||||
use crate::entrypoint::MemberRecord;
|
||||
use crate::expr::Expr;
|
||||
use crate::func_atom::{ExprFunc, Fun};
|
||||
use crate::gen_expr::GExpr;
|
||||
use crate::macros::Rule;
|
||||
use crate::system::SysCtx;
|
||||
|
||||
pub type GenTokTree<'a> = TokTree<'a, ForeignAtom<'a>, AtomFactory>;
|
||||
pub type GenTok<'a> = Token<'a, ForeignAtom<'a>, AtomFactory>;
|
||||
|
||||
pub fn do_extra(f: &AtomFactory, r: Range<u32>, ctx: SysCtx) -> api::TokenTree {
|
||||
api::TokenTree { range: r, token: api::Token::Atom(f.clone().build(ctx)) }
|
||||
pub async fn do_extra(f: &AtomFactory, r: Range<u32>, ctx: SysCtx) -> api::TokenTree {
|
||||
api::TokenTree { range: r, token: api::Token::Atom(f.clone().build(ctx).await) }
|
||||
}
|
||||
|
||||
fn with_export(mem: GenMember, public: bool) -> Vec<GenItem> {
|
||||
(public.then(|| GenItemKind::Export(mem.name.clone()).at(Pos::Inherit)).into_iter())
|
||||
.chain([GenItemKind::Member(mem).at(Pos::Inherit)])
|
||||
(public.then(|| GenItemKind::Export(mem.name.clone())).into_iter())
|
||||
.chain([GenItemKind::Member(mem)])
|
||||
.map(|kind| GenItem { comments: vec![], kind })
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub struct GenItem {
|
||||
pub kind: GenItemKind,
|
||||
pub comments: Vec<Comment>,
|
||||
pub pos: Pos,
|
||||
pub comments: Vec<String>,
|
||||
}
|
||||
impl GenItem {
|
||||
pub fn into_api(self, ctx: &mut impl TreeIntoApiCtx) -> api::Item {
|
||||
pub async fn into_api(self, ctx: &mut impl TreeIntoApiCtx) -> api::Item {
|
||||
let kind = match self.kind {
|
||||
GenItemKind::Export(n) => api::ItemKind::Export(n.to_api()),
|
||||
GenItemKind::Member(mem) => api::ItemKind::Member(mem.into_api(ctx)),
|
||||
GenItemKind::Export(n) => api::ItemKind::Export(ctx.sys().i.i::<String>(&n).await.to_api()),
|
||||
GenItemKind::Member(mem) => api::ItemKind::Member(mem.into_api(ctx).await),
|
||||
GenItemKind::Import(cn) => api::ItemKind::Import(cn.tok().to_api()),
|
||||
GenItemKind::Macro(prio, rules) => api::ItemKind::Macro(api::MacroBlock {
|
||||
priority: prio,
|
||||
rules: rules.into_iter().map(|r| r.to_api()).collect_vec(),
|
||||
}),
|
||||
GenItemKind::Macro(priority, gen_rules) => {
|
||||
let mut rules = Vec::with_capacity(gen_rules.len());
|
||||
for rule in gen_rules {
|
||||
rules.push(rule.into_api(ctx).await)
|
||||
}
|
||||
api::ItemKind::Macro(api::MacroBlock { priority, rules })
|
||||
},
|
||||
};
|
||||
let comments = self.comments.into_iter().map(|c| c.to_api()).collect_vec();
|
||||
api::Item { location: self.pos.to_api(), comments, kind }
|
||||
let comments = join_all(self.comments.iter().map(|c| async {
|
||||
api::Comment {
|
||||
location: api::Location::Inherit,
|
||||
text: ctx.sys().i.i::<String>(c).await.to_api(),
|
||||
}
|
||||
}))
|
||||
.await;
|
||||
api::Item { location: api::Location::Inherit, comments, kind }
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn cnst(public: bool, name: &str, value: impl ToExpr) -> Vec<GenItem> {
|
||||
with_export(GenMember { name: intern(name).await, kind: MemKind::Const(value.to_expr()) }, public)
|
||||
pub fn cnst(public: bool, name: &str, value: impl ToExpr) -> Vec<GenItem> {
|
||||
with_export(GenMember { name: name.to_string(), kind: MemKind::Const(value.to_expr()) }, public)
|
||||
}
|
||||
pub async fn module(
|
||||
public: bool,
|
||||
@@ -75,31 +84,31 @@ pub async fn root_mod(
|
||||
name: &str,
|
||||
imports: impl IntoIterator<Item = Sym>,
|
||||
items: impl IntoIterator<Item = Vec<GenItem>>,
|
||||
) -> (Tok<String>, MemKind) {
|
||||
) -> (String, MemKind) {
|
||||
let kind = MemKind::Mod {
|
||||
imports: imports.into_iter().collect(),
|
||||
items: items.into_iter().flatten().collect(),
|
||||
};
|
||||
(intern(name).await, kind)
|
||||
(name.to_string(), kind)
|
||||
}
|
||||
pub async fn fun<I, O>(exported: bool, name: &str, xf: impl ExprFunc<I, O>) -> Vec<GenItem> {
|
||||
let fac =
|
||||
LazyMemberFactory::new(move |sym| async { MemKind::Const(Fun::new(sym, xf).to_expr()) });
|
||||
with_export(GenMember { name: intern(name).await, kind: MemKind::Lazy(fac) }, exported)
|
||||
LazyMemberFactory::new(move |sym| async { MemKind::Const(Fun::new(sym, xf).await.to_expr()) });
|
||||
with_export(GenMember { name: name.to_string(), kind: MemKind::Lazy(fac) }, exported)
|
||||
}
|
||||
pub fn macro_block(prio: Option<f64>, rules: impl IntoIterator<Item = Rule>) -> Vec<GenItem> {
|
||||
let prio = prio.map(|p| NotNan::new(p).unwrap());
|
||||
vec![GenItemKind::Macro(prio, rules.into_iter().collect_vec()).gen()]
|
||||
vec![GenItem {
|
||||
kind: GenItemKind::Macro(prio, rules.into_iter().collect_vec()),
|
||||
comments: vec![],
|
||||
}]
|
||||
}
|
||||
|
||||
pub async fn comments<'a>(
|
||||
pub fn comments<'a>(
|
||||
cmts: impl IntoIterator<Item = &'a str>,
|
||||
mut val: Vec<GenItem>,
|
||||
) -> Vec<GenItem> {
|
||||
let cmts = join_all(
|
||||
cmts.into_iter().map(|c| async { Comment { text: intern(c).await, pos: Pos::Inherit } }),
|
||||
)
|
||||
.await;
|
||||
let cmts = cmts.into_iter().map(|c| c.to_string()).collect_vec();
|
||||
for v in val.iter_mut() {
|
||||
v.comments.extend(cmts.iter().cloned());
|
||||
}
|
||||
@@ -108,12 +117,12 @@ pub async fn comments<'a>(
|
||||
|
||||
trait_set! {
|
||||
trait LazyMemberCallback =
|
||||
FnOnce(Sym) -> LocalBoxFuture<'static, MemKind> + Send + Sync + DynClone
|
||||
FnOnce(Sym) -> LocalBoxFuture<'static, MemKind> + DynClone
|
||||
}
|
||||
pub struct LazyMemberFactory(Box<dyn LazyMemberCallback>);
|
||||
impl LazyMemberFactory {
|
||||
pub fn new<F: Future<Output = MemKind> + 'static>(
|
||||
cb: impl FnOnce(Sym) -> F + Send + Sync + Clone + 'static,
|
||||
cb: impl FnOnce(Sym) -> F + Clone + 'static,
|
||||
) -> Self {
|
||||
Self(Box::new(|s| cb(s).boxed_local()))
|
||||
}
|
||||
@@ -125,49 +134,45 @@ impl Clone for LazyMemberFactory {
|
||||
|
||||
pub enum GenItemKind {
|
||||
Member(GenMember),
|
||||
Export(Tok<String>),
|
||||
Export(String),
|
||||
Import(Sym),
|
||||
Macro(Option<NotNan<f64>>, Vec<Rule>),
|
||||
}
|
||||
impl GenItemKind {
|
||||
pub fn at(self, pos: Pos) -> GenItem { GenItem { kind: self, comments: vec![], pos } }
|
||||
pub fn gen(self) -> GenItem { GenItem { kind: self, comments: vec![], pos: Pos::Inherit } }
|
||||
pub fn gen_equiv(self, comments: Vec<Comment>) -> GenItem {
|
||||
GenItem { kind: self, comments, pos: Pos::Inherit }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct GenMember {
|
||||
name: Tok<String>,
|
||||
name: String,
|
||||
kind: MemKind,
|
||||
}
|
||||
impl GenMember {
|
||||
pub fn into_api(self, ctx: &mut impl TreeIntoApiCtx) -> api::Member {
|
||||
pub async fn into_api(self, ctx: &mut impl TreeIntoApiCtx) -> api::Member {
|
||||
let name = ctx.sys().i.i::<String>(&self.name).await;
|
||||
api::Member {
|
||||
name: self.name.to_api(),
|
||||
kind: self.kind.into_api(&mut ctx.push_path(self.name)),
|
||||
kind: self.kind.into_api(&mut ctx.push_path(name.clone())).await,
|
||||
name: name.to_api(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum MemKind {
|
||||
Const(Expr),
|
||||
Const(GExpr),
|
||||
Mod { imports: Vec<Sym>, items: Vec<GenItem> },
|
||||
Lazy(LazyMemberFactory),
|
||||
}
|
||||
impl MemKind {
|
||||
pub fn into_api(self, ctx: &mut impl TreeIntoApiCtx) -> api::MemberKind {
|
||||
pub async fn into_api(self, ctx: &mut impl TreeIntoApiCtx) -> api::MemberKind {
|
||||
match self {
|
||||
Self::Lazy(lazy) => api::MemberKind::Lazy(ctx.with_lazy(lazy)),
|
||||
Self::Const(c) =>
|
||||
api::MemberKind::Const(c.api_return(ctx.sys(), &mut |_| panic!("Slot in const tree"))),
|
||||
Self::Mod { imports, items } => api::MemberKind::Module(api::Module {
|
||||
items: (imports.into_iter())
|
||||
.map(|t| GenItemKind::Import(t).gen())
|
||||
.chain(items)
|
||||
.map(|i| i.into_api(ctx))
|
||||
.collect_vec(),
|
||||
}),
|
||||
Self::Const(c) => api::MemberKind::Const(c.api_return(ctx.sys(), ctx.req()).await),
|
||||
Self::Mod { imports, items } => {
|
||||
let all_items = (imports.into_iter())
|
||||
.map(|t| GenItem { comments: vec![], kind: GenItemKind::Import(t) })
|
||||
.chain(items);
|
||||
let mut items = Vec::new();
|
||||
for i in all_items {
|
||||
items.push(i.into_api(ctx).boxed_local().await)
|
||||
}
|
||||
api::MemberKind::Module(api::Module { items })
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -175,30 +180,42 @@ impl MemKind {
|
||||
pub trait TreeIntoApiCtx {
|
||||
fn sys(&self) -> SysCtx;
|
||||
fn with_lazy(&mut self, fac: LazyMemberFactory) -> api::TreeId;
|
||||
fn with_rule(&mut self, rule: Rc<Rule>) -> api::MacroId;
|
||||
fn push_path(&mut self, seg: Tok<String>) -> impl TreeIntoApiCtx;
|
||||
fn req(&self) -> &impl ReqHandlish;
|
||||
}
|
||||
|
||||
pub struct TIACtxImpl<'a, 'b> {
|
||||
pub struct TIACtxImpl<'a, 'b, RH: ReqHandlish> {
|
||||
pub sys: SysCtx,
|
||||
pub basepath: &'a [Tok<String>],
|
||||
pub path: Substack<'a, Tok<String>>,
|
||||
pub lazy: &'b mut HashMap<api::TreeId, MemberRecord>,
|
||||
pub lazy_members: &'b mut HashMap<api::TreeId, MemberRecord>,
|
||||
pub rules: &'b mut HashMap<api::MacroId, Rc<Rule>>,
|
||||
pub req: &'a RH,
|
||||
}
|
||||
|
||||
impl<'a, 'b> TreeIntoApiCtx for TIACtxImpl<'a, 'b> {
|
||||
impl<RH: ReqHandlish> TreeIntoApiCtx for TIACtxImpl<'_, '_, RH> {
|
||||
fn sys(&self) -> SysCtx { self.sys.clone() }
|
||||
fn push_path(&mut self, seg: Tok<String>) -> impl TreeIntoApiCtx {
|
||||
TIACtxImpl {
|
||||
req: self.req,
|
||||
lazy_members: self.lazy_members,
|
||||
rules: self.rules,
|
||||
sys: self.sys.clone(),
|
||||
lazy: self.lazy,
|
||||
basepath: self.basepath,
|
||||
path: self.path.push(seg),
|
||||
}
|
||||
}
|
||||
fn with_lazy(&mut self, fac: LazyMemberFactory) -> api::TreeId {
|
||||
let id = api::TreeId(NonZero::new((self.lazy.len() + 2) as u64).unwrap());
|
||||
let id = api::TreeId(NonZero::new((self.lazy_members.len() + 2) as u64).unwrap());
|
||||
let path = self.basepath.iter().cloned().chain(self.path.unreverse()).collect_vec();
|
||||
self.lazy.insert(id, MemberRecord::Gen(path, fac));
|
||||
self.lazy_members.insert(id, MemberRecord::Gen(path, fac));
|
||||
id
|
||||
}
|
||||
fn with_rule(&mut self, rule: Rc<Rule>) -> orchid_api::MacroId {
|
||||
let id = api::MacroId(NonZero::new((self.lazy_members.len() + 1) as u64).unwrap());
|
||||
self.rules.insert(id, rule);
|
||||
id
|
||||
}
|
||||
fn req(&self) -> &impl ReqHandlish { self.req }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user