Updated macro system to process and return mactree and then lower it separately to gexpr

This commit is contained in:
2026-04-11 11:00:22 +00:00
parent 9b4c7fa7d7
commit b44f3c1832
14 changed files with 460 additions and 469 deletions

View File

@@ -1,85 +1,93 @@
use async_fn_stream::stream;
use futures::{StreamExt, stream};
use orchid_base::{OrcRes, sym};
use orchid_extension::gen_expr::{GExpr, call, new_atom};
use orchid_extension::tree::{GenMember, fun, prefix};
use orchid_extension::{Expr, TAtom, ToExpr, exec};
use crate::macros::match_macros::MatcherAtom;
use crate::macros::match_macros::{MatcherAtom, match_one};
use crate::macros::utils::{RuleCtx, build_macro, mactree, mactreev};
use crate::{HomoTpl, MacTree, OrcOpt};
pub async fn gen_tuple_macro_lib() -> Vec<GenMember> {
prefix("std::tuple", [
build_macro(None, ["t"])
.rule(mactreev!(std::tuple::t [ "...$" elements 0 ]), [async |mut cx, [elements]| {
let tup: HomoTpl<TAtom<MacTree>> = cx
.exec(cx.recur(
mactree!((macros::common::comma_list "push" elements ;)),
))
.await?;
let val = stream::iter(&tup.0[..])
.fold(sym!(std::tuple::empty).to_gen().await, async |head, new| {
call(sym!(std::tuple::cat), (
head,
call(sym!(std::tuple::one), call(
sym!(macros::resolve),
new.clone(),
)),
)).await
})
.await;
Ok(val)
}])
.rule(
mactreev!(pattern::match_rule(std::tuple::t[ "...$" elements 0 macros::common::, macros::common::..])),
[async |cx, [elements]| parse_tpl(cx, elements, Some(mactree!(macros::common::_))).await],
)
.rule(
mactreev!(pattern::match_rule(
std::tuple::t[ "...$" elements 1 macros::common::, macros::common::.. "...$" tail 0]
)),
[async |cx, [elements, tail]| parse_tpl(cx, elements, Some(tail)).await],
)
.rule(mactreev!(pattern::match_rule(std::tuple::t[ "...$" elements 0])), [
async |cx, [elements]| parse_tpl(cx, elements, None).await,
])
.finish(),
fun(false, "matcher_body", tuple_matcher_body),
])
build_macro(None, ["t"])
.rule(mactreev!("std::tuple::t" [ "...$" elements 0 ]), async |mut cx, [elements]| {
let tup: HomoTpl<TAtom<MacTree>> =
cx.recur_call(mactree!("macros::common::comma_list" "push" elements)).await?;
let val = stream(async |mut h| {
for item in &tup.0[..] {
h.emit(cx.recur(item.own().await).await).await
}
})
.fold(mactree!("std::tuple::empty"), async |head, new| {
mactree!(
"std::tuple::cat"
"push" head;
("std::tuple::one"
"push" new)
)
})
.await;
Ok(val)
})
.rule(
mactreev!("pattern::match_rule"(
"std::tuple::t"[ "...$" elements 0 "macros::common::," "macros::common::.."]
)),
async |cx, [elements]| parse_tpl(cx, elements, Some(mactree!("macros::common::_"))).await,
)
.rule(
mactreev!("pattern::match_rule"(
"std::tuple::t"[ "...$" elements 1 "macros::common::," "macros::common::.." "...$" tail 0]
)),
async |cx, [elements, tail]| parse_tpl(cx, elements, Some(tail)).await,
)
.rule(
mactreev!("pattern::match_rule"("std::tuple::t"[ "...$" elements 0])),
async |cx, [elements]| parse_tpl(cx, elements, None).await,
)
.finish(),
fun(false, "matcher_body", tuple_matcher_body),
])
}
async fn parse_tpl(
mut cx: RuleCtx<'_>,
elements: MacTree,
tail_matcher: Option<MacTree>,
) -> OrcRes<GExpr> {
) -> OrcRes<MacTree> {
let tup: HomoTpl<TAtom<MacTree>> =
cx.exec(cx.recur(mactree!((macros::common::comma_list "push" elements ;)))).await?;
let mut subs = Vec::with_capacity(tup.0.len());
cx.recur_call(mactree!("macros::common::comma_list" "push" elements)).await?;
let mut keys = Vec::new();
let mut sub_matchers = mactree!("std::tuple::empty");
for mac_a in &tup.0[..] {
let sub: TAtom<MatcherAtom> =
cx.exec(cx.recur(mactree!(pattern::match_rule ("push" mac_a.own().await ;)))).await?;
subs.push(sub);
cx.recur_call(mactree!("pattern::match_rule" ("push" mac_a.own().await))).await?;
let owned = sub.own().await;
keys.extend(owned.keys);
sub_matchers =
mactree!("std::tuple::cat" "push" sub_matchers; ("std::tuple::one" "push" owned.matcher));
}
let tail_matcher: Option<TAtom<MatcherAtom>> = match tail_matcher {
Some(mac) => Some(cx.exec(cx.recur(mactree!(pattern::match_rule "push" mac ;))).await?),
None => None,
let tail_matcher = match tail_matcher {
Some(mac) => {
let atm: TAtom<MatcherAtom> =
cx.recur_call(mactree!("pattern::match_rule" "push" mac)).await?;
let owned = atm.own().await;
keys.extend(owned.keys);
mactree!("std::option::some" "push" owned.matcher)
},
None => mactree!("std::option::none"),
};
Ok(new_atom(MatcherAtom {
keys: stream::iter(&subs[..])
.flat_map(|t| t.keys())
.chain(stream::iter(&tail_matcher).flat_map(|mat| mat.keys()))
.collect()
.await,
matcher: call(sym!(std::tuple::matcher_body), (HomoTpl(subs), OrcOpt(tail_matcher)))
.to_expr()
.await,
}))
Ok(mactree!("Val" new_atom(MatcherAtom {
keys,
matcher: mactree!("std::tuple::matcher_body" "push" sub_matchers; "push" tail_matcher),
})))
}
fn tuple_matcher_body(
children: HomoTpl<TAtom<MatcherAtom>>,
tail: OrcOpt<TAtom<MatcherAtom>>,
children: HomoTpl<Expr>,
tail: OrcOpt<Expr>,
value: HomoTpl<Expr>,
) -> impl Future<Output = GExpr> {
exec(async move |mut h| -> OrcRes<OrcOpt<HomoTpl<Expr>>> {
@@ -88,7 +96,7 @@ fn tuple_matcher_body(
}
let mut binds = Vec::new();
for (sub_mat, sub_val) in children.0.iter().zip(&value.0) {
match sub_mat.run_matcher(&mut h, sub_val.clone()).await? {
match match_one(&mut h, sub_mat.clone(), sub_val.clone()).await? {
OrcOpt(None) => return Ok(OrcOpt(None)),
OrcOpt(Some(subres)) => binds.extend(subres.0),
}
@@ -102,7 +110,7 @@ fn tuple_matcher_body(
call(sym!(std::tuple::cat), (prefix, new.clone())).await
})
.await;
match tail_mat.run_matcher(&mut h, tail_tpl).await? {
match match_one(&mut h, tail_mat, tail_tpl).await? {
OrcOpt(Some(tail_binds)) => binds.extend(tail_binds.0),
OrcOpt(None) => return Ok(OrcOpt(None)),
}