60 lines
1.7 KiB
Rust
60 lines
1.7 KiB
Rust
use std::borrow::Cow;
|
|
|
|
use never::Never;
|
|
use orchid_base::format::fmt;
|
|
use orchid_extension::atom::{Atomic, TAtom};
|
|
use orchid_extension::atom_owned::{OwnedAtom, OwnedVariant, own};
|
|
use orchid_extension::context::i;
|
|
use orchid_extension::conv::ToExpr;
|
|
use orchid_extension::coroutine_exec::exec;
|
|
use orchid_extension::expr::Expr;
|
|
use orchid_extension::gen_expr::GExpr;
|
|
|
|
use crate::macros::mactree::{MacTok, MacTree};
|
|
|
|
#[derive(Clone)]
|
|
pub struct InstantiateTplCall {
|
|
pub(crate) tpl: MacTree,
|
|
pub(crate) argc: usize,
|
|
pub(crate) argv: Vec<MacTree>,
|
|
}
|
|
impl Atomic for InstantiateTplCall {
|
|
type Variant = OwnedVariant;
|
|
type Data = ();
|
|
}
|
|
impl OwnedAtom for InstantiateTplCall {
|
|
async fn val(&self) -> Cow<'_, Self::Data> { Cow::Owned(()) }
|
|
type Refs = Never;
|
|
// Technically must be supported but shouldn't actually ever be called
|
|
async fn call_ref(&self, arg: Expr) -> GExpr {
|
|
if !self.argv.is_empty() {
|
|
eprintln!(
|
|
"Copying partially applied instantiate_tpl call. This is an internal value.\
|
|
\nIt should be fully consumed within generated code."
|
|
);
|
|
}
|
|
self.clone().call(arg).await
|
|
}
|
|
async fn call(mut self, arg: Expr) -> GExpr {
|
|
exec(async move |mut h| {
|
|
match h.exec::<TAtom<MacTree>>(arg.clone()).await {
|
|
Err(_) => panic!("Expected a macro param, found {}", fmt(&arg, &i()).await),
|
|
Ok(t) => self.argv.push(own(&t).await),
|
|
};
|
|
if self.argv.len() < self.argc {
|
|
return self.to_gen().await;
|
|
}
|
|
let mut args = self.argv.into_iter();
|
|
let ret = self.tpl.map(&mut false, &mut |mt| match mt.tok() {
|
|
MacTok::Slot => Some(args.next().expect("Not enough arguments to fill all slots")),
|
|
_ => None,
|
|
});
|
|
assert!(args.next().is_none(), "Too many arguments for all slots");
|
|
ret.to_gen().await
|
|
})
|
|
.await
|
|
.to_gen()
|
|
.await
|
|
}
|
|
}
|