use futures::{StreamExt, stream}; use orchid_base::error::OrcRes; use orchid_base::sym; use orchid_extension::atom::TAtom; use orchid_extension::atom_owned::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, call, sym_ref}; use orchid_extension::tree::{GenMember, fun, prefix}; use crate::macros::match_macros::MatcherAtom; use crate::macros::resolve::resolve; use crate::macros::utils::{build_macro, mactree, mactreev}; use crate::{HomoTpl, MacTree, OrcOpt, Tpl}; pub async fn gen_std_macro_lib() -> Vec { prefix("std", [ prefix("option", [ fun(false, "is_some_body", |sub: TAtom, val: OrcOpt| { exec(async move |mut h| { let Some(sub_val) = val.0 else { return Ok(OrcOpt(None)) }; h.exec::>(call(sub.to_gen().await, [sub_val.to_gen().await])).await }) }), fun(false, "is_none_body", async |val: OrcOpt| { if val.0.is_none() { OrcOpt(Some(Tpl(()))) } else { OrcOpt(None) } }), build_macro(None, ["of", "empty"]) .rule(mactreev!(pattern::match_rule ( std::option::of "...$" sub_pattern 0)), [ |[sub]: [_; _]| { exec(async move |mut h| { let sub = h .exec::>( resolve(mactree!(pattern::match_rule "push" sub;)).await, ) .await?; Ok(MatcherAtom { keys: sub.keys().collect().await, matcher: h .register(call(sym_ref(sym!(std::option::is_some_body; i())), [sub .to_gen() .await])) .await, }) }) }, ]) .rule(mactreev!(pattern::match_rule(std::option::empty)), [|[]: [_; _]| { exec(async |mut h| { Ok(MatcherAtom { keys: vec![], matcher: h.register(sym_ref(sym!(std::option::is_none_body; i()))).await, }) }) }]) .finish(), ]), prefix("tuple", [ build_macro(None, ["t"]) .rule(mactreev!(std::tuple::t [ "...$" elements 0 ]), [|[elements]: [_; _]| { exec(async move |mut h| { let tup = h .exec::>>(call(sym_ref(sym!(macros::resolve; i())), [ mactree!((macros::common::comma_list "push" elements ;)).to_gen().await, ])) .await?; let val = stream::iter(&tup.0[..]) .fold(sym_ref(sym!(std::tuple::empty; i())), async |head, new| { call(sym_ref(sym!(std::tuple::cat; i())), [ head, call(sym_ref(sym!(std::tuple::one; i())), [call( sym_ref(sym!(macros::resolve; i())), [new.clone().to_gen().await], )]), ]) }) .await; Ok(val) }) }]) .rule( mactreev!(pattern::match_rule(std::tuple::t[ "...$" elements 0 macros::common::..])), [async |[elements]: [_; _]| parse_tpl(elements, Some(mactree!(macros::common::_))).await], ) .rule( mactreev!(pattern::match_rule( std::tuple::t[ "...$" elements 1 macros::common::.. "...$" tail 0] )), [async |[elements, tail]: [_; _]| parse_tpl(elements, Some(tail)).await], ) .rule(mactreev!(pattern::match_rule(std::tuple::t[ "...$" elements 0])), [ |[elements]: [_; _]| parse_tpl(elements, None), ]) .finish(), fun(false, "matcher_body", tuple_matcher_body), ]), ]) } fn parse_tpl(elements: MacTree, tail_matcher: Option) -> impl Future { exec(async move |mut h| -> OrcRes { let tup = h .exec::>>(call(sym_ref(sym!(macros::resolve; i())), [ mactree!((macros::common::comma_list "push" elements ;)).to_gen().await, ])) .await?; let mut subs = Vec::with_capacity(tup.0.len()); for mac_a in &tup.0[..] { let mac = own(mac_a).await; let sub = h .exec::>(call(sym_ref(sym!(macros::resolve; i())), [ mactree!(pattern::match_rule "push" mac ;).to_gen().await, ])) .await?; subs.push(sub); } let tail_matcher = match tail_matcher { Some(mac) => Some( h.exec::>(call(sym_ref(sym!(macros::resolve; i())), [ mactree!(pattern::match_rule "push" mac ;).to_gen().await, ])) .await?, ), None => None, }; Ok(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_ref(sym!(std::tuple::matcher_body; i())), [ HomoTpl(subs).to_gen().await, OrcOpt(tail_matcher).to_gen().await, ]) .to_expr() .await, }) }) } fn tuple_matcher_body( children: HomoTpl>, tail: OrcOpt>, value: HomoTpl, ) -> impl Future { exec(async move |mut h| -> OrcRes> { if value.0.len() < children.0.len() { return Ok(OrcOpt(None)); } 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? { OrcOpt(None) => return Ok(OrcOpt(None)), OrcOpt(Some(subres)) => binds.extend(subres.0), } } match tail.0 { None if children.0.len() < value.0.len() => return Ok(OrcOpt(None)), None => (), Some(tail_mat) => { let tail_tpl = stream::iter(&value.0[children.0.len()..]) .fold(sym_ref(sym!(std::tuple::empty; i())), async |prefix, new| { call(sym_ref(sym!(std::tuple::cat; i())), [prefix, new.clone().to_gen().await]) }) .await; match tail_mat.run_matcher(&mut h, tail_tpl).await? { OrcOpt(Some(tail_binds)) => binds.extend(tail_binds.0), OrcOpt(None) => return Ok(OrcOpt(None)), } }, }; todo!() }) }