forked from Orchid/orchid
New macro system and stdlib additions
This commit is contained in:
@@ -1,97 +1,65 @@
|
||||
use hashbrown::HashMap;
|
||||
use itertools::{Itertools, chain};
|
||||
use orchid_base::error::Reporter;
|
||||
use orchid_base::{clone, sym};
|
||||
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::func_atom::Lambda;
|
||||
use orchid_extension::gen_expr::{call, sym_ref};
|
||||
use orchid_extension::reflection::{ReflMemKind, refl};
|
||||
use orchid_extension::tree::{GenMember, MemKind, fun, lazy, prefix};
|
||||
use substack::Substack;
|
||||
use orchid_extension::tree::{GenMember, fun, prefix};
|
||||
|
||||
use crate::MacTok;
|
||||
use crate::macros::macro_value::{Macro, Matcher};
|
||||
use crate::macros::mactree::{LowerCtx, MacTree, Ph};
|
||||
use crate::macros::resolve::{ResolveCtx, resolve};
|
||||
use crate::macros::utils::{mactree, mactreev, mk_macro};
|
||||
use crate::macros::mactree::MacTree;
|
||||
use crate::macros::resolve::resolve;
|
||||
use crate::macros::utils::{build_macro, mactree, mactreev};
|
||||
|
||||
pub fn gen_macro_lib() -> Vec<GenMember> {
|
||||
pub async fn gen_macro_lib() -> Vec<GenMember> {
|
||||
prefix("macros", [
|
||||
fun(true, "lower", |tpl: TAtom<MacTree>| async move {
|
||||
let ctx = LowerCtx { sys: tpl.untyped.ctx().clone(), rep: &Reporter::new() };
|
||||
let res = own(tpl).await.lower(ctx, Substack::Bottom).await;
|
||||
if let Some(e) = Reporter::new().errv() { Err(e) } else { Ok(res) }
|
||||
}),
|
||||
fun(true, "recur", async |tpl: TAtom<MacTree>| {
|
||||
call(sym_ref(sym!(macros::lower; tpl.i()).await), [call(
|
||||
sym_ref(sym!(macros::resolve; tpl.i()).await),
|
||||
[tpl.to_expr().await],
|
||||
)])
|
||||
}),
|
||||
fun(true, "resolve", |tpl: TAtom<MacTree>| async move {
|
||||
exec("macros::resolve", async move |mut h| {
|
||||
let ctx = tpl.ctx().clone();
|
||||
let root = refl(&ctx);
|
||||
let tpl = own(tpl.clone()).await;
|
||||
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 };
|
||||
let mac = own(mac).await;
|
||||
macros.entry(mac.canonical_name(&ctx).await).or_insert(mac);
|
||||
}
|
||||
}
|
||||
let mut named = HashMap::new();
|
||||
let mut priod = Vec::new();
|
||||
for (_, mac) in macros.iter() {
|
||||
for rule in mac.0.rules.iter() {
|
||||
if rule.glossary.is_subset(tpl.glossary()) {
|
||||
match &rule.pattern {
|
||||
Matcher::Named(m) =>
|
||||
named.entry(m.head()).or_insert(Vec::new()).push((m, mac, rule)),
|
||||
Matcher::Priod(p) => priod.push((mac.0.prio, (p, mac, rule))),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let priod = priod.into_iter().sorted_unstable_by_key(|(p, _)| *p).map(|(_, r)| r).collect();
|
||||
let mut rctx = ResolveCtx { h, ctx: ctx.clone(), named, priod };
|
||||
let resolve_res = resolve(&mut rctx, &tpl).await;
|
||||
std::mem::drop(rctx);
|
||||
match resolve_res {
|
||||
Some(out_tree) => out_tree.to_expr().await,
|
||||
None => tpl.to_expr().await,
|
||||
}
|
||||
})
|
||||
.await
|
||||
}),
|
||||
fun(true, "resolve", async |tpl: TAtom<MacTree>| resolve(own(&tpl).await).await),
|
||||
// TODO test whether any of this worked
|
||||
lazy(true, "common", async |_, ctx| {
|
||||
let add_macro = {
|
||||
clone!(ctx);
|
||||
mk_macro(Some(1), ["+"], [(
|
||||
mactreev!(ctx.i(); "...$" lhs 0 macros::common::+ "...$" rhs 1),
|
||||
Lambda::new("std::number::add", async move |lhs: TAtom<MacTree>, rhs: TAtom<MacTree>| {
|
||||
mactree!(ctx.i(); std::number::add
|
||||
(macros::recur "'" lhs.ex();)
|
||||
(macros::recur "'" rhs.ex();)
|
||||
)
|
||||
}),
|
||||
)])
|
||||
};
|
||||
let mul_macro = mk_macro(Some(2), ["*"], [(
|
||||
mactreev!(ctx.i(); "...$" lhs 0 macros::common::* "...$" rhs 1),
|
||||
Lambda::new("std::number::mul", async |lhs: TAtom<MacTree>, rhs: TAtom<MacTree>| {
|
||||
mactree!(lhs.ctx().i(); std::number::mul
|
||||
(macros::recur "'" lhs.ex();)
|
||||
(macros::recur "'" rhs.ex();)
|
||||
)
|
||||
}),
|
||||
)]);
|
||||
MemKind::Mod { members: chain!(add_macro, mul_macro).collect_vec() }
|
||||
}),
|
||||
prefix("common", [
|
||||
build_macro(None, ["..", "_"]).finish(),
|
||||
build_macro(Some(1), ["+"])
|
||||
.rule(mactreev!("...$" lhs 0 macros::common::+ "...$" rhs 1), [async |[lhs, rhs]| {
|
||||
call(sym_ref(sym!(std::number::add; i())), [resolve(lhs).await, resolve(rhs).await])
|
||||
}])
|
||||
.finish(),
|
||||
build_macro(Some(2), ["*"])
|
||||
.rule(mactreev!("...$" lhs 0 macros::common::* "...$" rhs 1), [async |[lhs, rhs]| {
|
||||
call(sym_ref(sym!(std::number::mul; i())), [resolve(lhs).await, resolve(rhs).await])
|
||||
}])
|
||||
.finish(),
|
||||
build_macro(None, ["comma_list", ","])
|
||||
.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,
|
||||
])
|
||||
}],
|
||||
)
|
||||
.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()))
|
||||
}])
|
||||
.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())), [resolve(head).await]),
|
||||
resolve(mactree!(macros::common::semi_list "push" tail ;)).await,
|
||||
])
|
||||
}],
|
||||
)
|
||||
.rule(mactreev!(macros::common::semi_list ( "...$" final_tail 0 )), [async |[tail]| {
|
||||
call(sym_ref(sym!(std::tuple::one; i())), [resolve(tail).await])
|
||||
}])
|
||||
.rule(mactreev!(macros::common::semi_list()), [async |[]| {
|
||||
sym_ref(sym!(std::tuple::empty; i()))
|
||||
}])
|
||||
.finish(),
|
||||
]),
|
||||
])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user