Added support for defining macros in Rust within the macro system

Also fixed a lot of bugs
This commit is contained in:
2025-09-30 21:23:16 +02:00
parent 7971a2b4eb
commit b77653f841
52 changed files with 849 additions and 502 deletions

View File

@@ -1,9 +1,11 @@
use std::borrow::Cow;
use never::Never;
use orchid_extension::atom::{Atomic, TypAtom};
use orchid_base::format::fmt;
use orchid_extension::atom::{Atomic, TAtom};
use orchid_extension::atom_owned::{OwnedAtom, OwnedVariant, own};
use orchid_extension::conv::{ToExpr, TryFromExpr};
use orchid_extension::conv::ToExpr;
use orchid_extension::coroutine_exec::exec;
use orchid_extension::expr::Expr;
use orchid_extension::gen_expr::GExpr;
@@ -24,26 +26,33 @@ impl OwnedAtom for InstantiateTplCall {
type Refs = Never;
// Technically must be supported but shouldn't actually ever be called
async fn call_ref(&self, arg: Expr) -> GExpr {
eprintln!(
"Copying partially applied instantiate_tpl call. This is an internal value.\
\nIt should be fully consumed within generated code."
);
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 {
match TypAtom::<MacTree>::try_from_expr(arg).await {
Err(e) => return Err::<Never, _>(e).to_expr().await,
Ok(t) => self.argv.push(own(t).await),
};
if self.argv.len() < self.argc {
return self.to_expr().await;
}
let mut args = self.argv.into_iter();
let ret = map_mactree(&self.tpl, &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_expr().await
exec("macros::instantiate_tpl", async move |mut h| {
match h.exec::<TAtom<MacTree>>(arg.clone()).await {
Err(_) => panic!("Expected a macro param, found {}", fmt(&arg, arg.ctx().i()).await),
Ok(t) => self.argv.push(own(t).await),
};
if self.argv.len() < self.argc {
return self.to_expr().await;
}
let mut args = self.argv.into_iter();
let ret = map_mactree(&self.tpl, &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_expr().await
})
.await
.to_expr()
.await
}
}