diff --git a/orchid-extension/src/parser.rs b/orchid-extension/src/parser.rs index 5fb9280..24a9573 100644 --- a/orchid-extension/src/parser.rs +++ b/orchid-extension/src/parser.rs @@ -1,7 +1,8 @@ use std::marker::PhantomData; -use futures::FutureExt; +use async_stream::stream; use futures::future::{LocalBoxFuture, join_all}; +use futures::{FutureExt, Stream, StreamExt, pin_mut}; use itertools::Itertools; use orchid_api::ResolveNames; use orchid_base::error::{OrcRes, Reporter}; @@ -171,16 +172,31 @@ pub struct ConstCtx { constid: api::ParsedConstId, } impl ConstCtx { - pub async fn names(&self, names: [&Sym; N]) -> [Option; N] { + pub fn names<'a>( + &'a self, + names: impl IntoIterator + Clone + 'a, + ) -> impl Stream)> + 'a { let resolve_names = ResolveNames { constid: self.constid, sys: self.ctx.sys_id(), - names: names.into_iter().map(|n| n.to_api()).collect_vec(), + names: names.clone().into_iter().map(|n| n.to_api()).collect_vec(), }; - let names = self.ctx.reqnot().request(resolve_names).await; + stream! { + let new_names = self.ctx.reqnot().request(resolve_names).await; + for (name, name_opt) in names.into_iter().zip(new_names) { + yield (name.clone(), match name_opt { + None => None, + Some(name) => Some(Sym::from_api(name, self.ctx.i()).await) + }) + } + } + } + pub async fn names_n(&self, names: [&Sym; N]) -> [Option; N] { let mut results = [const { None }; N]; - for (i, name) in names.into_iter().enumerate().filter_map(|(i, n)| Some((i, n?))) { - results[i] = Some(Sym::from_api(name, self.ctx.i()).await); + let names = self.names(names).enumerate().filter_map(|(i, n)| async move { Some((i, n.1?)) }); + pin_mut!(names); + while let Some((i, name)) = names.next().await { + results[i] = Some(name); } results } diff --git a/orchid-std/src/macros/instantiate_tpl.rs b/orchid-std/src/macros/instantiate_tpl.rs index 20eb346..700169e 100644 --- a/orchid-std/src/macros/instantiate_tpl.rs +++ b/orchid-std/src/macros/instantiate_tpl.rs @@ -12,7 +12,7 @@ use orchid_extension::expr::Expr; use orchid_extension::gen_expr::GExpr; use orchid_extension::system::SysCtx; -use crate::macros::mactree::{MacTok, MacTree}; +use crate::macros::mactree::{MacTok, MacTree, map_mactree}; #[derive(Clone)] pub struct InstantiateTplCall { @@ -53,42 +53,12 @@ impl OwnedAtom for InstantiateTplCall { if self.argv.len() < self.argc { return self.to_expr(); } - instantiate_tpl(&self.tpl, &mut self.argv.into_iter(), &mut false).to_expr() + let mut args = self.argv.into_iter(); + map_mactree(&self.tpl, &mut false, &mut |tpl| match &*tpl.tok { + MacTok::Ph(_) => panic!("instantiate_tpl received a placeholder"), + MacTok::Slot => Some(args.next().expect("Not enough arguments to fill all slots!")), + _ => None, + }) + .to_expr() } } -fn instantiate_tpl( - tpl: &MacTree, - argv: &mut impl Iterator, - changed: &mut bool, -) -> MacTree { - let tok = match &*tpl.tok { - MacTok::Slot => { - *changed = true; - return argv.next().expect("Not enough arguments to fill all slots!"); - }, - MacTok::Lambda(arg, body) => MacTok::Lambda( - ro(changed, |changed| instantiate_tpl(arg, argv, changed)), - instantiate_tpl_v(body, argv, changed), - ), - MacTok::Name(_) | MacTok::Value(_) => return tpl.clone(), - MacTok::Ph(_) => panic!("instantiate_tpl received a placeholder"), - MacTok::S(p, body) => MacTok::S(*p, instantiate_tpl_v(body, argv, changed)), - }; - if *changed { MacTree { pos: tpl.pos.clone(), tok: Rc::new(tok) } } else { tpl.clone() } -} -fn instantiate_tpl_v( - tpl: &[MacTree], - argv: &mut impl Iterator, - changed: &mut bool, -) -> Vec { - tpl.iter().map(|tree| ro(changed, |changed| instantiate_tpl(tree, argv, changed))).collect_vec() -} - -/// reverse "or". Inside, the flag is always false, but raising it will raise -/// the outside flag too. -fn ro(flag: &mut bool, cb: impl FnOnce(&mut bool) -> T) -> T { - let mut new_flag = false; - let val = cb(&mut new_flag); - *flag |= new_flag; - val -} diff --git a/orchid-std/src/macros/let_line.rs b/orchid-std/src/macros/let_line.rs index 593dee7..53f8a32 100644 --- a/orchid-std/src/macros/let_line.rs +++ b/orchid-std/src/macros/let_line.rs @@ -1,4 +1,5 @@ use futures::future::LocalBoxFuture; +use hashbrown::HashMap; use itertools::Itertools; use orchid_base::error::{OrcRes, mk_errv}; use orchid_base::interner::Tok; @@ -10,6 +11,8 @@ use orchid_extension::parser::{ }; use substack::Substack; +use crate::macros::mactree::{MacTok, MacTree, map_mactree, map_mactree_v}; + type ExprGenerator = Box FnOnce(ConstCtx, Substack<'a, Sym>) -> LocalBoxFuture<'a, GExpr>>; @@ -31,29 +34,36 @@ impl Parser for LetLine { return Err(err.await); }; let Parsed { tail, .. } = expect_tok(&ctx, tail, ctx.i().i("=").await).await?; - fn do_tokv(line: GenSnippet<'_>) -> ExprGenerator { - let first: ExprGenerator = if let Some((idx, arg)) = + fn parse_tokv(line: GenSnippet<'_>) -> Vec { + let first: MacTree = if let Some((idx, arg)) = line.iter().enumerate().find_map(|(i, x)| Some((i, x.as_lambda()?))) { - Box::new(move |ctx, stack| Box::pin(async move { - let name = ctx.names([]) - })) } else { - }; todo!() } - let expr_generator = do_tokv(tail); + let mut names = HashMap::new(); + let aliased = parse_tokv(tail); + map_mactree_v(&aliased, &mut false, &mut |tpl| { + if let MacTok::Name(n) = &*tpl.tok { + names.insert(n.clone(), n); + } + None + }); Ok(vec![ParsedLine { comments, sr: line.sr(), kind: ParsedLineKind::Mem(ParsedMem { exported, name, - kind: ParsedMemKind::cnst(async |ctx| expr_generator(ctx, Substack::Bottom).await), + kind: ParsedMemKind::cnst(async |ctx| { + let mut names_str = ctx.names(names.keys()); + while let Some(()) = names_str.next().await { + names[] + } + todo!() + }), }), }]) } } - -fn update_names(tree: MacTree) \ No newline at end of file diff --git a/orchid-std/src/macros/mactree.rs b/orchid-std/src/macros/mactree.rs index bc72bbc..c55fa07 100644 --- a/orchid-std/src/macros/mactree.rs +++ b/orchid-std/src/macros/mactree.rs @@ -3,6 +3,7 @@ use std::fmt::Display; use std::rc::Rc; use futures::future::join_all; +use itertools::Itertools; use orchid_api::Paren; use orchid_base::format::{FmtCtx, FmtUnit, Format, Variants}; use orchid_base::interner::Tok; @@ -18,7 +19,9 @@ pub struct MacTree { pub pos: Pos, pub tok: Rc, } -impl MacTree {} +impl MacTree { + fn tok(&self) -> &MacTok { &*self.tok } +} impl Atomic for MacTree { type Data = (); type Variant = OwnedVariant; @@ -99,33 +102,33 @@ pub enum PhKind { Vector { at_least_one: bool, priority: u8 }, } -pub fn map_mactree( - tpl: &MacTree, - map: &mut impl FnMut(MacTree) -> Option, - argv: &mut impl Iterator, +pub fn map_mactree Option>( + src: &MacTree, changed: &mut bool, + map: &mut F, ) -> MacTree { - let tok = match &*tpl.tok { - MacTok::Slot => { + let tok = match map(src.clone()) { + Some(new_tok) => { *changed = true; - return argv.next().expect("Not enough arguments to fill all slots!"); + return new_tok; + }, + None => match &*src.tok { + MacTok::Lambda(arg, body) => MacTok::Lambda( + ro(changed, |changed| map_mactree(arg, changed, map)), + map_mactree_v(body, changed, map), + ), + MacTok::Name(_) | MacTok::Value(_) | MacTok::Slot | MacTok::Ph(_) => return src.clone(), + MacTok::S(p, body) => MacTok::S(*p, map_mactree_v(body, changed, map)), }, - MacTok::Lambda(arg, body) => MacTok::Lambda( - ro(changed, |changed| instantiate_tpl(arg, argv, changed)), - instantiate_tpl_v(body, argv, changed), - ), - MacTok::Name(_) | MacTok::Value(_) => return tpl.clone(), - MacTok::Ph(_) => panic!("instantiate_tpl received a placeholder"), - MacTok::S(p, body) => MacTok::S(*p, instantiate_tpl_v(body, argv, changed)), }; - if *changed { MacTree { pos: tpl.pos.clone(), tok: Rc::new(tok) } } else { tpl.clone() } + if *changed { MacTree { pos: src.pos.clone(), tok: Rc::new(tok) } } else { src.clone() } } -pub fn map_mactree_v( - tpl: &[MacTree], - argv: &mut impl Iterator, +pub fn map_mactree_v Option>( + src: &[MacTree], changed: &mut bool, + map: &mut F, ) -> Vec { - tpl.iter().map(|tree| ro(changed, |changed| instantiate_tpl(tree, argv, changed))).collect_vec() + src.iter().map(|tree| ro(changed, |changed| map_mactree(tree, changed, map))).collect_vec() } /// reverse "or". Inside, the flag is always false, but raising it will raise