partway through fixes, macro system needs resdesign
Some checks failed
Rust / build (push) Has been cancelled
Some checks failed
Rust / build (push) Has been cancelled
This commit is contained in:
@@ -6,14 +6,16 @@ use futures::StreamExt;
|
||||
use futures::future::LocalBoxFuture;
|
||||
use itertools::{Itertools, chain};
|
||||
use never::Never;
|
||||
use orchid_base::{NameLike, Sym, VPath, is};
|
||||
use orchid_extension::ToExpr;
|
||||
use orchid_base::{NameLike, OrcRes, Sym, VPath, is};
|
||||
use orchid_extension::gen_expr::{GExpr, new_atom};
|
||||
use orchid_extension::tree::{GenMember, MemKind, cnst, lazy};
|
||||
use orchid_extension::{Atomic, OwnedAtom, OwnedVariant, TAtom};
|
||||
use orchid_extension::{
|
||||
Atomic, ExecHandle, OwnedAtom, OwnedVariant, TAtom, ToExpr, ToExprFuture, TryFromExpr, exec,
|
||||
};
|
||||
|
||||
use crate::macros::macro_value::{Macro, MacroData, Rule};
|
||||
use crate::macros::mactree::MacTreeSeq;
|
||||
use crate::macros::resolve::{ArgStack, resolve};
|
||||
use crate::macros::rule::matcher::Matcher;
|
||||
use crate::{MacTok, MacTree};
|
||||
|
||||
@@ -22,8 +24,9 @@ pub type Args = Vec<MacTree>;
|
||||
#[derive(Clone)]
|
||||
pub struct MacroBodyArgCollector {
|
||||
argc: usize,
|
||||
arg_stack: Option<ArgStack>,
|
||||
args: Args,
|
||||
cb: Rc<dyn Fn(Args) -> LocalBoxFuture<'static, GExpr>>,
|
||||
cb: Rc<dyn for<'a> Fn(RuleCtx<'a>, Args) -> LocalBoxFuture<'a, GExpr>>,
|
||||
}
|
||||
impl Atomic for MacroBodyArgCollector {
|
||||
type Data = ();
|
||||
@@ -39,12 +42,23 @@ impl OwnedAtom for MacroBodyArgCollector {
|
||||
self.clone().call(arg).await
|
||||
}
|
||||
async fn call(mut self, arg: orchid_extension::Expr) -> GExpr {
|
||||
let atom = (TAtom::<MacTree>::downcast(arg.handle()).await).unwrap_or_else(|_| {
|
||||
panic!("This is an intermediary value, the argument types are known in advance")
|
||||
});
|
||||
self.args.push(atom.own().await);
|
||||
if self.arg_stack.is_none() {
|
||||
let atom = (TAtom::<ArgStack>::downcast(arg.handle()).await).unwrap_or_else(|_| {
|
||||
panic!("The argstack is an intermediary value, the argument types are known in advance")
|
||||
});
|
||||
self.arg_stack = Some(atom.own().await);
|
||||
} else {
|
||||
let atom = (TAtom::<MacTree>::downcast(arg.handle()).await).unwrap_or_else(|_| {
|
||||
panic!("This is an intermediary value, the argument types are known in advance")
|
||||
});
|
||||
self.args.push(atom.own().await);
|
||||
}
|
||||
if self.argc == self.args.len() {
|
||||
(self.cb)(self.args).await.to_gen().await
|
||||
exec(async move |handle| {
|
||||
let rule_ctx = RuleCtx { arg_stk: self.arg_stack.unwrap(), handle };
|
||||
(self.cb)(rule_ctx, self.args).await
|
||||
})
|
||||
.await
|
||||
} else {
|
||||
new_atom(self)
|
||||
}
|
||||
@@ -53,6 +67,21 @@ impl OwnedAtom for MacroBodyArgCollector {
|
||||
|
||||
fn body_name(name: &str, counter: usize) -> String { format!("({name})::{counter}") }
|
||||
|
||||
pub struct RuleCtx<'a> {
|
||||
arg_stk: ArgStack,
|
||||
handle: ExecHandle<'a>,
|
||||
}
|
||||
impl RuleCtx<'_> {
|
||||
pub fn recur(&self, mt: MacTree) -> impl ToExpr + use<> {
|
||||
eprintln!("Recursion in macro");
|
||||
let arg_stk = self.arg_stk.clone();
|
||||
ToExprFuture(resolve(mt, arg_stk))
|
||||
}
|
||||
pub async fn exec<T: TryFromExpr>(&mut self, val: impl ToExpr) -> OrcRes<T> {
|
||||
self.handle.exec(val).await
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn build_macro(
|
||||
prio: Option<u64>,
|
||||
own_kws: impl IntoIterator<Item = &'static str>,
|
||||
@@ -74,31 +103,25 @@ impl MacroBuilder {
|
||||
pub(crate) fn rule<const N: usize, R: ToExpr>(
|
||||
mut self,
|
||||
pat: MacTreeSeq,
|
||||
body: [impl AsyncFn([MacTree; N]) -> R + 'static; 1],
|
||||
body: [impl AsyncFn(RuleCtx, [MacTree; N]) -> R + 'static; 1],
|
||||
) -> Self {
|
||||
let [body] = body;
|
||||
let body = Rc::new(body);
|
||||
let name = &body_name(self.own_kws[0], self.body_consts.len());
|
||||
self.body_consts.extend(match N {
|
||||
0 => lazy(true, name, async move |_| {
|
||||
let argv = [].into_iter().collect_array().expect("N is 0");
|
||||
MemKind::Const(body(argv).await.to_gen().await)
|
||||
}),
|
||||
1.. => cnst(
|
||||
true,
|
||||
name,
|
||||
new_atom(MacroBodyArgCollector {
|
||||
argc: N,
|
||||
args: Vec::new(),
|
||||
cb: Rc::new(move |argv| {
|
||||
let arr =
|
||||
argv.into_iter().collect_array::<N>().expect("argc should enforce the length");
|
||||
let body = body.clone();
|
||||
Box::pin(async move { body(arr).await.to_gen().await })
|
||||
}),
|
||||
self.body_consts.extend(cnst(
|
||||
true,
|
||||
name,
|
||||
new_atom(MacroBodyArgCollector {
|
||||
argc: N,
|
||||
arg_stack: None,
|
||||
args: Vec::new(),
|
||||
cb: Rc::new(move |rec, argv| {
|
||||
let arr = argv.into_iter().collect_array::<N>().expect("argc should enforce the length");
|
||||
let body = body.clone();
|
||||
Box::pin(async move { body(rec, arr).await.to_gen().await })
|
||||
}),
|
||||
),
|
||||
});
|
||||
}),
|
||||
));
|
||||
self.patterns.push(pat);
|
||||
self
|
||||
}
|
||||
@@ -282,4 +305,6 @@ macro_rules! mactreev {
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) use {mactree, mactreev, mactreev_impl};
|
||||
pub(crate) use mactree;
|
||||
pub(crate) use mactreev;
|
||||
pub(crate) use mactreev_impl;
|
||||
|
||||
Reference in New Issue
Block a user