Fixed match, and enabled macro keywords to share names with constants
This commit is contained in:
@@ -3,12 +3,14 @@ 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::gen_expr::{call, sym_ref};
|
||||
use orchid_extension::tree::{GenMember, fun, prefix};
|
||||
|
||||
use crate::macros::mactree::MacTree;
|
||||
use crate::macros::resolve::resolve;
|
||||
use crate::macros::utils::{build_macro, mactree, mactreev};
|
||||
use crate::{HomoTpl, UntypedTuple};
|
||||
|
||||
pub async fn gen_macro_lib() -> Vec<GenMember> {
|
||||
prefix("macros", [
|
||||
@@ -30,35 +32,37 @@ pub async fn gen_macro_lib() -> Vec<GenMember> {
|
||||
.rule(
|
||||
mactreev!(macros::common::comma_list ( "...$" head 0 macros::common::, "...$" tail 1)),
|
||||
[async |[head, tail]| {
|
||||
call(sym_ref(sym!(std::tuple::cat; i())), [
|
||||
call(sym_ref(sym!(std::tuple::one; i())), [head.to_gen().await]),
|
||||
resolve(mactree!(macros::common::comma_list "push" tail ;)).await,
|
||||
])
|
||||
exec(async |mut h| {
|
||||
let recur = resolve(mactree!(macros::common::comma_list "push" tail ;)).await;
|
||||
let mut tail = h.exec::<HomoTpl<TAtom<MacTree>>>(recur).await?;
|
||||
tail.0.insert(0, h.exec(head).await?);
|
||||
Ok(tail)
|
||||
})
|
||||
.await
|
||||
}],
|
||||
)
|
||||
.rule(mactreev!(macros::common::comma_list ( "...$" final_tail 0 )), [async |[tail]| {
|
||||
call(sym_ref(sym!(std::tuple::one; i())), [tail.to_gen().await])
|
||||
}])
|
||||
.rule(mactreev!(macros::common::comma_list()), [async |[]| {
|
||||
sym_ref(sym!(std::tuple::empty; i()))
|
||||
HomoTpl(vec![tail.to_gen().await])
|
||||
}])
|
||||
.rule(mactreev!(macros::common::comma_list()), [async |[]| UntypedTuple(Vec::new())])
|
||||
.finish(),
|
||||
build_macro(None, ["semi_list", ";"])
|
||||
.rule(
|
||||
mactreev!(macros::common::semi_list ( "...$" head 0 macros::common::; "...$" tail 1)),
|
||||
[async |[head, tail]| {
|
||||
call(sym_ref(sym!(std::tuple::cat; i())), [
|
||||
call(sym_ref(sym!(std::tuple::one; i())), [head.to_gen().await]),
|
||||
resolve(mactree!(macros::common::semi_list "push" tail ;)).await,
|
||||
])
|
||||
exec(async |mut h| {
|
||||
let recur = resolve(mactree!(macros::common::semi_list "push" tail ;)).await;
|
||||
let mut tail = h.exec::<HomoTpl<TAtom<MacTree>>>(recur).await?;
|
||||
tail.0.insert(0, h.exec(head).await?);
|
||||
Ok(tail)
|
||||
})
|
||||
.await
|
||||
}],
|
||||
)
|
||||
.rule(mactreev!(macros::common::semi_list ( "...$" final_tail 0 )), [async |[tail]| {
|
||||
call(sym_ref(sym!(std::tuple::one; i())), [tail.to_gen().await])
|
||||
}])
|
||||
.rule(mactreev!(macros::common::semi_list()), [async |[]| {
|
||||
sym_ref(sym!(std::tuple::empty; i()))
|
||||
HomoTpl(vec![tail.to_gen().await])
|
||||
}])
|
||||
.rule(mactreev!(macros::common::semi_list()), [async |[]| UntypedTuple(Vec::new())])
|
||||
.finish(),
|
||||
]),
|
||||
])
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
use async_fn_stream::stream;
|
||||
use async_once_cell::OnceCell;
|
||||
use futures::{StreamExt, stream};
|
||||
use futures::StreamExt;
|
||||
use itertools::Itertools;
|
||||
use orchid_base::error::{OrcRes, Reporter, mk_errv};
|
||||
use orchid_base::parse::{
|
||||
@@ -14,7 +14,7 @@ use orchid_base::{clone, sym};
|
||||
use orchid_extension::atom::TAtom;
|
||||
use orchid_extension::context::i;
|
||||
use orchid_extension::conv::{ToExpr, TryFromExpr};
|
||||
use orchid_extension::gen_expr::{atom, call, sym_ref};
|
||||
use orchid_extension::gen_expr::{call, sym_ref};
|
||||
use orchid_extension::parser::{PSnippet, ParsCtx, ParsedLine, Parser};
|
||||
|
||||
use crate::macros::let_line::{dealias_mac_v, parse_tokv};
|
||||
@@ -142,43 +142,37 @@ impl Parser for MacroLine {
|
||||
}))
|
||||
}
|
||||
let mac_cell = Rc::new(OnceCell::new());
|
||||
let rules = Rc::new(RefCell::new(Some(rules)));
|
||||
let rules = Rc::new(rules);
|
||||
for (kw, sr) in &*keywords {
|
||||
clone!(mac_cell, rules, module, macro_name, prio);
|
||||
lines.push(ParsedLine::cnst(&sr.clone(), &comments, true, kw.clone(), async move |cctx| {
|
||||
let mac = mac_cell
|
||||
.get_or_init(async {
|
||||
let rep = Reporter::new();
|
||||
let rules = rules.borrow_mut().take().expect("once cell initializer runs");
|
||||
let rules = stream::iter(rules)
|
||||
.then(|(body_name, placeholders, pattern_rel)| {
|
||||
let cctx = &cctx;
|
||||
let rep = &rep;
|
||||
async move {
|
||||
let pattern = dealias_mac_v(&pattern_rel, cctx, rep).await;
|
||||
let pattern_res = Matcher::new(pattern.clone()).await;
|
||||
let placeholders = placeholders.into_iter().map(|(ph, _)| ph.name).collect_vec();
|
||||
match pattern_res {
|
||||
Ok(matcher) => Some(Rule { body_name, matcher, pattern, placeholders }),
|
||||
Err(e) => {
|
||||
rep.report(e);
|
||||
None
|
||||
},
|
||||
}
|
||||
}
|
||||
})
|
||||
.flat_map(stream::iter)
|
||||
.collect::<Vec<_>>()
|
||||
.await;
|
||||
Macro(Rc::new(MacroData {
|
||||
let kw_key = i().i(&format!("__macro__{kw}")).await;
|
||||
lines.push(ParsedLine::cnst(&sr.clone(), &comments, true, kw_key, async move |cctx| {
|
||||
let mac_future = async {
|
||||
let rep = Reporter::new();
|
||||
let rules = stream(async |mut h| {
|
||||
for (body, ph_names, pattern_rel) in rules.iter() {
|
||||
let pattern = dealias_mac_v(pattern_rel, &cctx, &rep).await;
|
||||
let ph_names = ph_names.iter().map(|(ph, _)| ph.name.clone()).collect_vec();
|
||||
match Matcher::new(pattern.clone()).await {
|
||||
Ok(matcher) =>
|
||||
h.emit(Rule { body: body.clone(), matcher, pattern, ph_names }).await,
|
||||
Err(e) => rep.report(e),
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.await;
|
||||
match rep.errv() {
|
||||
Some(e) => Err(e),
|
||||
None => Ok(Macro(Rc::new(MacroData {
|
||||
canonical_name: module.suffix([macro_name], &i()).await,
|
||||
module,
|
||||
prio: prio.map(|i| i.0 as u64),
|
||||
rules,
|
||||
}))
|
||||
})
|
||||
.await;
|
||||
atom(mac.clone())
|
||||
}))),
|
||||
}
|
||||
};
|
||||
mac_cell.get_or_init(mac_future).await.clone().to_gen().await
|
||||
}))
|
||||
}
|
||||
Ok(lines)
|
||||
|
||||
@@ -25,8 +25,8 @@ pub struct Macro(pub Rc<MacroData>);
|
||||
pub struct Rule {
|
||||
pub pattern: MacTreeSeq,
|
||||
pub matcher: Matcher,
|
||||
pub placeholders: Vec<Tok<String>>,
|
||||
pub body_name: Tok<String>,
|
||||
pub ph_names: Vec<Tok<String>>,
|
||||
pub body: Tok<String>,
|
||||
}
|
||||
impl Atomic for Macro {
|
||||
type Data = ();
|
||||
|
||||
@@ -7,7 +7,7 @@ use itertools::Itertools;
|
||||
use orchid_base::error::mk_errv;
|
||||
use orchid_base::format::fmt;
|
||||
use orchid_base::location::Pos;
|
||||
use orchid_base::name::Sym;
|
||||
use orchid_base::name::{NameLike, Sym, VPath};
|
||||
use orchid_base::tree::Paren;
|
||||
use orchid_extension::atom::TAtom;
|
||||
use orchid_extension::atom_owned::own;
|
||||
@@ -24,17 +24,22 @@ use crate::macros::mactree::MacTreeSeq;
|
||||
use crate::macros::rule::state::{MatchState, StateEntry};
|
||||
use crate::{MacTok, MacTree};
|
||||
|
||||
pub async fn resolve(tpl: MacTree) -> GExpr {
|
||||
pub async fn resolve(val: MacTree) -> GExpr {
|
||||
exec(async move |mut h| {
|
||||
let ctx = ctx();
|
||||
// if ctx.logger().is_active() {
|
||||
writeln!(ctx.logger(), "Macro-resolving {}", fmt(&tpl, &i()).await);
|
||||
writeln!(ctx.logger(), "Macro-resolving {}", fmt(&val, &i()).await);
|
||||
// }
|
||||
let root = refl();
|
||||
let mut macros = HashMap::new();
|
||||
for n in tpl.glossary() {
|
||||
if let Ok(ReflMemKind::Const) = root.get_by_path(n).await.map(|m| m.kind()) {
|
||||
let Ok(mac) = h.exec::<TAtom<Macro>>(sym_ref(n.clone())).await else { continue };
|
||||
for n in val.glossary() {
|
||||
let (foot, body) = n.split_last_seg();
|
||||
let new_name = VPath::new(body.iter().cloned())
|
||||
.name_with_suffix(i().i(&format!("__macro__{foot}")).await)
|
||||
.to_sym(&i())
|
||||
.await;
|
||||
if let Ok(ReflMemKind::Const) = root.get_by_path(&new_name).await.map(|m| m.kind()) {
|
||||
let Ok(mac) = h.exec::<TAtom<Macro>>(sym_ref(new_name)).await else { continue };
|
||||
let mac = own(&mac).await;
|
||||
macros.entry(mac.0.canonical_name.clone()).or_insert(mac);
|
||||
}
|
||||
@@ -45,7 +50,7 @@ pub async fn resolve(tpl: MacTree) -> GExpr {
|
||||
for (_, mac) in macros.iter() {
|
||||
let mut record = FilteredMacroRecord { mac, rules: Vec::new() };
|
||||
for (rule_i, rule) in mac.0.rules.iter().enumerate() {
|
||||
if rule.pattern.glossary.is_subset(tpl.glossary()) {
|
||||
if rule.pattern.glossary.is_subset(val.glossary()) {
|
||||
record.rules.push(rule_i);
|
||||
}
|
||||
}
|
||||
@@ -61,7 +66,14 @@ pub async fn resolve(tpl: MacTree) -> GExpr {
|
||||
}
|
||||
}
|
||||
let mut rctx = ResolveCtx { h, exclusive, priod };
|
||||
resolve_one(&mut rctx, Substack::Bottom, &tpl).await
|
||||
let gex = resolve_one(&mut rctx, Substack::Bottom, &val).await;
|
||||
writeln!(
|
||||
ctx.logger(),
|
||||
"Macro-resolution over {}\nreturned {}",
|
||||
fmt(&val, &i()).await,
|
||||
fmt(&gex, &i()).await
|
||||
);
|
||||
gex
|
||||
})
|
||||
.await
|
||||
}
|
||||
@@ -270,13 +282,12 @@ async fn resolve_seq(
|
||||
|
||||
async fn mk_body_call(mac: &Macro, rule: &Rule, state: &MatchState<'_>, pos: Pos) -> GExpr {
|
||||
let mut call_args = vec![];
|
||||
for name in rule.placeholders.iter() {
|
||||
for name in rule.ph_names.iter() {
|
||||
call_args.push(match state.get(name).expect("Missing state entry for placeholder") {
|
||||
StateEntry::Scalar(scal) => (**scal).clone().to_gen().await,
|
||||
StateEntry::Vec(vec) =>
|
||||
MacTok::S(Paren::Round, MacTreeSeq::new(vec.iter().cloned())).at(Pos::None).to_gen().await,
|
||||
});
|
||||
}
|
||||
call(sym_ref(mac.0.module.suffix([rule.body_name.clone()], &i()).await), call_args)
|
||||
.at(pos.clone())
|
||||
call(sym_ref(mac.0.module.suffix([rule.body.clone()], &i()).await), call_args).at(pos.clone())
|
||||
}
|
||||
|
||||
@@ -27,8 +27,8 @@ pub async fn gen_std_macro_lib() -> Vec<GenMember> {
|
||||
fun(false, "is_none_body", async |val: OrcOpt<Expr>| {
|
||||
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)), [
|
||||
build_macro(None, ["some", "none"])
|
||||
.rule(mactreev!(pattern::match_rule ( std::option::some "...$" sub_pattern 0)), [
|
||||
|[sub]: [_; _]| {
|
||||
exec(async move |mut h| {
|
||||
let sub = h
|
||||
@@ -47,7 +47,7 @@ pub async fn gen_std_macro_lib() -> Vec<GenMember> {
|
||||
})
|
||||
},
|
||||
])
|
||||
.rule(mactreev!(pattern::match_rule(std::option::empty)), [|[]: [_; _]| {
|
||||
.rule(mactreev!(pattern::match_rule(std::option::none)), [|[]: [_; _]| {
|
||||
exec(async |mut h| {
|
||||
Ok(MatcherAtom {
|
||||
keys: vec![],
|
||||
|
||||
@@ -100,7 +100,7 @@ impl MacroBuilder {
|
||||
pub(crate) fn finish(self) -> Vec<GenMember> {
|
||||
let Self { own_kws, prio, patterns, body_consts } = self;
|
||||
let name = own_kws[0];
|
||||
let main_const = lazy(true, name, async move |path| {
|
||||
let main_const = lazy(true, &format!("__macro__{name}"), async move |path| {
|
||||
let module = (Sym::new(path.split_last_seg().1.iter().cloned(), &i()).await)
|
||||
.expect("Default macro in global root");
|
||||
MemKind::Const(
|
||||
@@ -120,8 +120,8 @@ impl MacroBuilder {
|
||||
h.emit(Rule {
|
||||
matcher: Matcher::new(pattern.clone()).await.unwrap(),
|
||||
pattern,
|
||||
placeholders,
|
||||
body_name: i().i(&format!("({name})::{counter}")).await,
|
||||
ph_names: placeholders,
|
||||
body: i().i(&format!("({name})::{counter}")).await,
|
||||
})
|
||||
.await;
|
||||
}
|
||||
@@ -134,9 +134,9 @@ impl MacroBuilder {
|
||||
)
|
||||
});
|
||||
let kw_consts = own_kws[1..].iter().flat_map(|kw| {
|
||||
lazy(true, kw, async |path| {
|
||||
lazy(true, &format!("__macro__{kw}"), async move |path| {
|
||||
let main_const_name = VPath::new(path.split_last_seg().1.iter().cloned())
|
||||
.name_with_suffix(i().i(name).await)
|
||||
.name_with_suffix(i().i(&format!("__macro__{name}")).await)
|
||||
.to_sym(&i())
|
||||
.await;
|
||||
MemKind::Const(sym_ref(main_const_name))
|
||||
|
||||
Reference in New Issue
Block a user