Fixed match, and enabled macro keywords to share names with constants

This commit is contained in:
2025-11-30 02:30:42 +01:00
parent ecf151158d
commit 4e4dc381ea
7 changed files with 82 additions and 73 deletions

View File

@@ -1,6 +1,6 @@
let my_tuple = option::some t[1, 2] let my_tuple = option::some t[1, 2]
let main = match my_tuple { let main = match my_tuple {
option::of t[ref head, ..] => head; option::some t[ref head, ..] => head;
option::empty => "foo"; option::none => "foo";
} }

View File

@@ -3,12 +3,14 @@ use orchid_extension::atom::TAtom;
use orchid_extension::atom_owned::own; use orchid_extension::atom_owned::own;
use orchid_extension::context::i; use orchid_extension::context::i;
use orchid_extension::conv::ToExpr; use orchid_extension::conv::ToExpr;
use orchid_extension::coroutine_exec::exec;
use orchid_extension::gen_expr::{call, sym_ref}; use orchid_extension::gen_expr::{call, sym_ref};
use orchid_extension::tree::{GenMember, fun, prefix}; use orchid_extension::tree::{GenMember, fun, prefix};
use crate::macros::mactree::MacTree; use crate::macros::mactree::MacTree;
use crate::macros::resolve::resolve; use crate::macros::resolve::resolve;
use crate::macros::utils::{build_macro, mactree, mactreev}; use crate::macros::utils::{build_macro, mactree, mactreev};
use crate::{HomoTpl, UntypedTuple};
pub async fn gen_macro_lib() -> Vec<GenMember> { pub async fn gen_macro_lib() -> Vec<GenMember> {
prefix("macros", [ prefix("macros", [
@@ -30,35 +32,37 @@ pub async fn gen_macro_lib() -> Vec<GenMember> {
.rule( .rule(
mactreev!(macros::common::comma_list ( "...$" head 0 macros::common::, "...$" tail 1)), mactreev!(macros::common::comma_list ( "...$" head 0 macros::common::, "...$" tail 1)),
[async |[head, tail]| { [async |[head, tail]| {
call(sym_ref(sym!(std::tuple::cat; i())), [ exec(async |mut h| {
call(sym_ref(sym!(std::tuple::one; i())), [head.to_gen().await]), let recur = resolve(mactree!(macros::common::comma_list "push" tail ;)).await;
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]| { .rule(mactreev!(macros::common::comma_list ( "...$" final_tail 0 )), [async |[tail]| {
call(sym_ref(sym!(std::tuple::one; i())), [tail.to_gen().await]) HomoTpl(vec![tail.to_gen().await])
}])
.rule(mactreev!(macros::common::comma_list()), [async |[]| {
sym_ref(sym!(std::tuple::empty; i()))
}]) }])
.rule(mactreev!(macros::common::comma_list()), [async |[]| UntypedTuple(Vec::new())])
.finish(), .finish(),
build_macro(None, ["semi_list", ";"]) build_macro(None, ["semi_list", ";"])
.rule( .rule(
mactreev!(macros::common::semi_list ( "...$" head 0 macros::common::; "...$" tail 1)), mactreev!(macros::common::semi_list ( "...$" head 0 macros::common::; "...$" tail 1)),
[async |[head, tail]| { [async |[head, tail]| {
call(sym_ref(sym!(std::tuple::cat; i())), [ exec(async |mut h| {
call(sym_ref(sym!(std::tuple::one; i())), [head.to_gen().await]), let recur = resolve(mactree!(macros::common::semi_list "push" tail ;)).await;
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]| { .rule(mactreev!(macros::common::semi_list ( "...$" final_tail 0 )), [async |[tail]| {
call(sym_ref(sym!(std::tuple::one; i())), [tail.to_gen().await]) HomoTpl(vec![tail.to_gen().await])
}])
.rule(mactreev!(macros::common::semi_list()), [async |[]| {
sym_ref(sym!(std::tuple::empty; i()))
}]) }])
.rule(mactreev!(macros::common::semi_list()), [async |[]| UntypedTuple(Vec::new())])
.finish(), .finish(),
]), ]),
]) ])

View File

@@ -1,8 +1,8 @@
use std::cell::RefCell;
use std::rc::Rc; use std::rc::Rc;
use async_fn_stream::stream;
use async_once_cell::OnceCell; use async_once_cell::OnceCell;
use futures::{StreamExt, stream}; use futures::StreamExt;
use itertools::Itertools; use itertools::Itertools;
use orchid_base::error::{OrcRes, Reporter, mk_errv}; use orchid_base::error::{OrcRes, Reporter, mk_errv};
use orchid_base::parse::{ use orchid_base::parse::{
@@ -14,7 +14,7 @@ use orchid_base::{clone, sym};
use orchid_extension::atom::TAtom; use orchid_extension::atom::TAtom;
use orchid_extension::context::i; use orchid_extension::context::i;
use orchid_extension::conv::{ToExpr, TryFromExpr}; 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 orchid_extension::parser::{PSnippet, ParsCtx, ParsedLine, Parser};
use crate::macros::let_line::{dealias_mac_v, parse_tokv}; 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 mac_cell = Rc::new(OnceCell::new());
let rules = Rc::new(RefCell::new(Some(rules))); let rules = Rc::new(rules);
for (kw, sr) in &*keywords { for (kw, sr) in &*keywords {
clone!(mac_cell, rules, module, macro_name, prio); clone!(mac_cell, rules, module, macro_name, prio);
lines.push(ParsedLine::cnst(&sr.clone(), &comments, true, kw.clone(), async move |cctx| { let kw_key = i().i(&format!("__macro__{kw}")).await;
let mac = mac_cell lines.push(ParsedLine::cnst(&sr.clone(), &comments, true, kw_key, async move |cctx| {
.get_or_init(async { let mac_future = async {
let rep = Reporter::new(); let rep = Reporter::new();
let rules = rules.borrow_mut().take().expect("once cell initializer runs"); let rules = stream(async |mut h| {
let rules = stream::iter(rules) for (body, ph_names, pattern_rel) in rules.iter() {
.then(|(body_name, placeholders, pattern_rel)| { let pattern = dealias_mac_v(pattern_rel, &cctx, &rep).await;
let cctx = &cctx; let ph_names = ph_names.iter().map(|(ph, _)| ph.name.clone()).collect_vec();
let rep = &rep; match Matcher::new(pattern.clone()).await {
async move { Ok(matcher) =>
let pattern = dealias_mac_v(&pattern_rel, cctx, rep).await; h.emit(Rule { body: body.clone(), matcher, pattern, ph_names }).await,
let pattern_res = Matcher::new(pattern.clone()).await; Err(e) => rep.report(e),
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) => { .collect::<Vec<_>>()
rep.report(e); .await;
None match rep.errv() {
}, Some(e) => Err(e),
} None => Ok(Macro(Rc::new(MacroData {
}
})
.flat_map(stream::iter)
.collect::<Vec<_>>()
.await;
Macro(Rc::new(MacroData {
canonical_name: module.suffix([macro_name], &i()).await, canonical_name: module.suffix([macro_name], &i()).await,
module, module,
prio: prio.map(|i| i.0 as u64), prio: prio.map(|i| i.0 as u64),
rules, rules,
})) }))),
}) }
.await; };
atom(mac.clone()) mac_cell.get_or_init(mac_future).await.clone().to_gen().await
})) }))
} }
Ok(lines) Ok(lines)

View File

@@ -25,8 +25,8 @@ pub struct Macro(pub Rc<MacroData>);
pub struct Rule { pub struct Rule {
pub pattern: MacTreeSeq, pub pattern: MacTreeSeq,
pub matcher: Matcher, pub matcher: Matcher,
pub placeholders: Vec<Tok<String>>, pub ph_names: Vec<Tok<String>>,
pub body_name: Tok<String>, pub body: Tok<String>,
} }
impl Atomic for Macro { impl Atomic for Macro {
type Data = (); type Data = ();

View File

@@ -7,7 +7,7 @@ use itertools::Itertools;
use orchid_base::error::mk_errv; use orchid_base::error::mk_errv;
use orchid_base::format::fmt; use orchid_base::format::fmt;
use orchid_base::location::Pos; use orchid_base::location::Pos;
use orchid_base::name::Sym; use orchid_base::name::{NameLike, Sym, VPath};
use orchid_base::tree::Paren; use orchid_base::tree::Paren;
use orchid_extension::atom::TAtom; use orchid_extension::atom::TAtom;
use orchid_extension::atom_owned::own; use orchid_extension::atom_owned::own;
@@ -24,17 +24,22 @@ use crate::macros::mactree::MacTreeSeq;
use crate::macros::rule::state::{MatchState, StateEntry}; use crate::macros::rule::state::{MatchState, StateEntry};
use crate::{MacTok, MacTree}; use crate::{MacTok, MacTree};
pub async fn resolve(tpl: MacTree) -> GExpr { pub async fn resolve(val: MacTree) -> GExpr {
exec(async move |mut h| { exec(async move |mut h| {
let ctx = ctx(); let ctx = ctx();
// if ctx.logger().is_active() { // 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 root = refl();
let mut macros = HashMap::new(); let mut macros = HashMap::new();
for n in tpl.glossary() { for n in val.glossary() {
if let Ok(ReflMemKind::Const) = root.get_by_path(n).await.map(|m| m.kind()) { let (foot, body) = n.split_last_seg();
let Ok(mac) = h.exec::<TAtom<Macro>>(sym_ref(n.clone())).await else { continue }; 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; let mac = own(&mac).await;
macros.entry(mac.0.canonical_name.clone()).or_insert(mac); 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() { for (_, mac) in macros.iter() {
let mut record = FilteredMacroRecord { mac, rules: Vec::new() }; let mut record = FilteredMacroRecord { mac, rules: Vec::new() };
for (rule_i, rule) in mac.0.rules.iter().enumerate() { 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); record.rules.push(rule_i);
} }
} }
@@ -61,7 +66,14 @@ pub async fn resolve(tpl: MacTree) -> GExpr {
} }
} }
let mut rctx = ResolveCtx { h, exclusive, priod }; 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 .await
} }
@@ -270,13 +282,12 @@ async fn resolve_seq(
async fn mk_body_call(mac: &Macro, rule: &Rule, state: &MatchState<'_>, pos: Pos) -> GExpr { async fn mk_body_call(mac: &Macro, rule: &Rule, state: &MatchState<'_>, pos: Pos) -> GExpr {
let mut call_args = vec![]; 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") { call_args.push(match state.get(name).expect("Missing state entry for placeholder") {
StateEntry::Scalar(scal) => (**scal).clone().to_gen().await, StateEntry::Scalar(scal) => (**scal).clone().to_gen().await,
StateEntry::Vec(vec) => StateEntry::Vec(vec) =>
MacTok::S(Paren::Round, MacTreeSeq::new(vec.iter().cloned())).at(Pos::None).to_gen().await, 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) call(sym_ref(mac.0.module.suffix([rule.body.clone()], &i()).await), call_args).at(pos.clone())
.at(pos.clone())
} }

View File

@@ -27,8 +27,8 @@ pub async fn gen_std_macro_lib() -> Vec<GenMember> {
fun(false, "is_none_body", async |val: OrcOpt<Expr>| { fun(false, "is_none_body", async |val: OrcOpt<Expr>| {
if val.0.is_none() { OrcOpt(Some(Tpl(()))) } else { OrcOpt(None) } if val.0.is_none() { OrcOpt(Some(Tpl(()))) } else { OrcOpt(None) }
}), }),
build_macro(None, ["of", "empty"]) build_macro(None, ["some", "none"])
.rule(mactreev!(pattern::match_rule ( std::option::of "...$" sub_pattern 0)), [ .rule(mactreev!(pattern::match_rule ( std::option::some "...$" sub_pattern 0)), [
|[sub]: [_; _]| { |[sub]: [_; _]| {
exec(async move |mut h| { exec(async move |mut h| {
let sub = 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| { exec(async |mut h| {
Ok(MatcherAtom { Ok(MatcherAtom {
keys: vec![], keys: vec![],

View File

@@ -100,7 +100,7 @@ impl MacroBuilder {
pub(crate) fn finish(self) -> Vec<GenMember> { pub(crate) fn finish(self) -> Vec<GenMember> {
let Self { own_kws, prio, patterns, body_consts } = self; let Self { own_kws, prio, patterns, body_consts } = self;
let name = own_kws[0]; 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) let module = (Sym::new(path.split_last_seg().1.iter().cloned(), &i()).await)
.expect("Default macro in global root"); .expect("Default macro in global root");
MemKind::Const( MemKind::Const(
@@ -120,8 +120,8 @@ impl MacroBuilder {
h.emit(Rule { h.emit(Rule {
matcher: Matcher::new(pattern.clone()).await.unwrap(), matcher: Matcher::new(pattern.clone()).await.unwrap(),
pattern, pattern,
placeholders, ph_names: placeholders,
body_name: i().i(&format!("({name})::{counter}")).await, body: i().i(&format!("({name})::{counter}")).await,
}) })
.await; .await;
} }
@@ -134,9 +134,9 @@ impl MacroBuilder {
) )
}); });
let kw_consts = own_kws[1..].iter().flat_map(|kw| { 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()) 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()) .to_sym(&i())
.await; .await;
MemKind::Const(sym_ref(main_const_name)) MemKind::Const(sym_ref(main_const_name))