From 4e4dc381ea51804cf9fb850533b99b2a19cdd562 Mon Sep 17 00:00:00 2001 From: Lawrence Bethlenfalvy Date: Sun, 30 Nov 2025 02:30:42 +0100 Subject: [PATCH] Fixed match, and enabled macro keywords to share names with constants --- examples/hello-world/main.orc | 4 +- orchid-std/src/macros/macro_lib.rs | 36 +++++++++------- orchid-std/src/macros/macro_line.rs | 62 +++++++++++++--------------- orchid-std/src/macros/macro_value.rs | 4 +- orchid-std/src/macros/resolve.rs | 33 ++++++++++----- orchid-std/src/macros/std_macros.rs | 6 +-- orchid-std/src/macros/utils.rs | 10 ++--- 7 files changed, 82 insertions(+), 73 deletions(-) diff --git a/examples/hello-world/main.orc b/examples/hello-world/main.orc index 0160166..28343f6 100644 --- a/examples/hello-world/main.orc +++ b/examples/hello-world/main.orc @@ -1,6 +1,6 @@ let my_tuple = option::some t[1, 2] let main = match my_tuple { - option::of t[ref head, ..] => head; - option::empty => "foo"; + option::some t[ref head, ..] => head; + option::none => "foo"; } diff --git a/orchid-std/src/macros/macro_lib.rs b/orchid-std/src/macros/macro_lib.rs index ecc64bb..ba4e59f 100644 --- a/orchid-std/src/macros/macro_lib.rs +++ b/orchid-std/src/macros/macro_lib.rs @@ -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 { prefix("macros", [ @@ -30,35 +32,37 @@ pub async fn gen_macro_lib() -> Vec { .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::>>(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::>>(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(), ]), ]) diff --git a/orchid-std/src/macros/macro_line.rs b/orchid-std/src/macros/macro_line.rs index 2882216..a38842b 100644 --- a/orchid-std/src/macros/macro_line.rs +++ b/orchid-std/src/macros/macro_line.rs @@ -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::>() - .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::>() + .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) diff --git a/orchid-std/src/macros/macro_value.rs b/orchid-std/src/macros/macro_value.rs index 6650eb4..ee532d5 100644 --- a/orchid-std/src/macros/macro_value.rs +++ b/orchid-std/src/macros/macro_value.rs @@ -25,8 +25,8 @@ pub struct Macro(pub Rc); pub struct Rule { pub pattern: MacTreeSeq, pub matcher: Matcher, - pub placeholders: Vec>, - pub body_name: Tok, + pub ph_names: Vec>, + pub body: Tok, } impl Atomic for Macro { type Data = (); diff --git a/orchid-std/src/macros/resolve.rs b/orchid-std/src/macros/resolve.rs index 44220cd..bde6cea 100644 --- a/orchid-std/src/macros/resolve.rs +++ b/orchid-std/src/macros/resolve.rs @@ -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::>(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::>(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()) } diff --git a/orchid-std/src/macros/std_macros.rs b/orchid-std/src/macros/std_macros.rs index dca29e5..7b6846a 100644 --- a/orchid-std/src/macros/std_macros.rs +++ b/orchid-std/src/macros/std_macros.rs @@ -27,8 +27,8 @@ pub async fn gen_std_macro_lib() -> Vec { 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)), [ + 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 { }) }, ]) - .rule(mactreev!(pattern::match_rule(std::option::empty)), [|[]: [_; _]| { + .rule(mactreev!(pattern::match_rule(std::option::none)), [|[]: [_; _]| { exec(async |mut h| { Ok(MatcherAtom { keys: vec![], diff --git a/orchid-std/src/macros/utils.rs b/orchid-std/src/macros/utils.rs index 4232657..a24eb1c 100644 --- a/orchid-std/src/macros/utils.rs +++ b/orchid-std/src/macros/utils.rs @@ -100,7 +100,7 @@ impl MacroBuilder { pub(crate) fn finish(self) -> Vec { 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))