partway through fixes, macro system needs resdesign
Some checks failed
Rust / build (push) Has been cancelled
Some checks failed
Rust / build (push) Has been cancelled
This commit is contained in:
@@ -2,9 +2,8 @@ use std::borrow::Cow;
|
||||
|
||||
use never::Never;
|
||||
use orchid_base::fmt;
|
||||
use orchid_extension::Expr;
|
||||
use orchid_extension::gen_expr::new_atom;
|
||||
use orchid_extension::{Atomic, OwnedAtom, OwnedVariant, TAtom, ToExpr, exec};
|
||||
use orchid_extension::{Atomic, Expr, OwnedAtom, OwnedVariant, TAtom, ToExpr, exec};
|
||||
|
||||
use crate::macros::mactree::{MacTok, MacTree};
|
||||
|
||||
|
||||
@@ -4,16 +4,16 @@ use futures::{FutureExt, StreamExt, stream};
|
||||
use hashbrown::HashMap;
|
||||
use itertools::Itertools;
|
||||
use orchid_base::{
|
||||
Comment, OrcRes, Paren, Parsed, Snippet, Sym, expect_tok, is, report, sym, token_errv,
|
||||
Comment, OrcRes, Paren, Parsed, Snippet, Sym, expect_tok, fmt, is, report, token_errv,
|
||||
try_pop_no_fluff, with_reporter,
|
||||
};
|
||||
use orchid_extension::gen_expr::{call, new_atom};
|
||||
use orchid_extension::{
|
||||
ConstCtx, PSnippet, PTok, PTokTree, ParsCtx, ParsedLine, Parser, TAtom, TryFromExpr,
|
||||
};
|
||||
|
||||
use crate::macros::mactree::{MacTok, MacTree, MacTreeSeq};
|
||||
use crate::macros::ph_lexer::PhAtom;
|
||||
use crate::macros::resolve::{ArgStack, resolve};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct LetLine;
|
||||
@@ -35,10 +35,16 @@ impl Parser for LetLine {
|
||||
};
|
||||
let Parsed { tail, .. } = expect_tok(tail, is("=").await).await?;
|
||||
let aliased = parse_tokv(tail).await;
|
||||
eprintln!("Parsed tokv: {}", fmt(&aliased).await);
|
||||
Ok(vec![ParsedLine::cnst(&line.sr(), &comments, exported, name, async move |ctx| {
|
||||
let macro_input =
|
||||
MacTok::S(Paren::Round, with_reporter(dealias_mac_v(&aliased, &ctx)).await?).at(sr.pos());
|
||||
Ok(call(sym!(macros::resolve), new_atom(macro_input)))
|
||||
eprintln!("Dealiased tokv: {}", fmt(¯o_input).await);
|
||||
let gx = resolve(macro_input, ArgStack::end()).await;
|
||||
eprintln!("resolves to: {}", fmt(&gx).await);
|
||||
let x = gx.create().await;
|
||||
eprintln!("created as: {}", fmt(&x).await);
|
||||
Ok(x)
|
||||
})])
|
||||
}
|
||||
}
|
||||
@@ -63,6 +69,7 @@ pub async fn dealias_mac_v(aliased: &MacTreeSeq, ctx: &ConstCtx) -> MacTreeSeq {
|
||||
|
||||
pub async fn parse_tokv(line: PSnippet<'_>) -> MacTreeSeq {
|
||||
if let Some((idx, arg)) = line.iter().enumerate().find_map(|(i, x)| Some((i, x.as_lambda()?))) {
|
||||
eprintln!("Found a lambda while parsing tokv");
|
||||
let (head, lambda) = line.split_at(idx as u32);
|
||||
let (_, body) = lambda.split_first().unwrap();
|
||||
let body = parse_tokv(body).boxed_local().await;
|
||||
|
||||
@@ -1,83 +1,79 @@
|
||||
use orchid_base::sym;
|
||||
use orchid_extension::TAtom;
|
||||
use orchid_extension::gen_expr::{call, new_atom};
|
||||
use orchid_extension::tree::{GenMember, fun, prefix};
|
||||
use orchid_extension::{TAtom, exec};
|
||||
|
||||
use crate::macros::mactree::MacTree;
|
||||
use crate::macros::resolve::resolve;
|
||||
use crate::macros::resolve::{ArgStack, resolve};
|
||||
use crate::macros::utils::{build_macro, mactree, mactreev};
|
||||
use crate::{HomoTpl, UntypedTuple};
|
||||
|
||||
pub async fn gen_macro_lib() -> Vec<GenMember> {
|
||||
prefix("macros", [
|
||||
fun(true, "resolve", async |tpl: TAtom<MacTree>| resolve(tpl.own().await).await),
|
||||
fun(true, "resolve", async |tpl: TAtom<MacTree>| {
|
||||
resolve(tpl.own().await, ArgStack::end()).await
|
||||
}),
|
||||
prefix("common", [
|
||||
build_macro(None, ["..", "_", "="]).finish(),
|
||||
build_macro(Some(1), ["+"])
|
||||
.rule(mactreev!("...$" lhs 1 macros::common::+ "...$" rhs 0), [async |[lhs, rhs]| {
|
||||
call(sym!(std::ops::add::resolve), (resolve(lhs).await, resolve(rhs).await)).await
|
||||
.rule(mactreev!("...$" lhs 1 macros::common::+ "...$" rhs 0), [async |cx, [lhs, rhs]| {
|
||||
call(sym!(std::ops::add::resolve), (cx.recur(lhs), cx.recur(rhs))).await
|
||||
}])
|
||||
.finish(),
|
||||
build_macro(Some(1), ["-"])
|
||||
.rule(mactreev!("...$" lhs 1 macros::common::- "...$" rhs 0), [async |[lhs, rhs]| {
|
||||
call(sym!(std::ops::sub::resolve), (resolve(lhs).await, resolve(rhs).await)).await
|
||||
.rule(mactreev!("...$" lhs 1 macros::common::- "...$" rhs 0), [async |cx, [lhs, rhs]| {
|
||||
call(sym!(std::ops::sub::resolve), (cx.recur(lhs), cx.recur(rhs))).await
|
||||
}])
|
||||
.finish(),
|
||||
build_macro(Some(2), ["*"])
|
||||
.rule(mactreev!("...$" lhs 1 macros::common::* "...$" rhs 0), [async |[lhs, rhs]| {
|
||||
call(sym!(std::ops::mul::resolve), (resolve(lhs).await, resolve(rhs).await)).await
|
||||
.rule(mactreev!("...$" lhs 1 macros::common::* "...$" rhs 0), [async |cx, [lhs, rhs]| {
|
||||
call(sym!(std::ops::mul::resolve), (cx.recur(lhs), cx.recur(rhs))).await
|
||||
}])
|
||||
.finish(),
|
||||
build_macro(Some(2), ["/"])
|
||||
.rule(mactreev!("...$" lhs 1 macros::common::/ "...$" rhs 0), [async |[lhs, rhs]| {
|
||||
call(sym!(std::ops::div::resolve), (resolve(lhs).await, resolve(rhs).await)).await
|
||||
.rule(mactreev!("...$" lhs 1 macros::common::/ "...$" rhs 0), [async |cx, [lhs, rhs]| {
|
||||
call(sym!(std::ops::div::resolve), (cx.recur(lhs), cx.recur(rhs))).await
|
||||
}])
|
||||
.finish(),
|
||||
build_macro(Some(2), ["%"])
|
||||
.rule(mactreev!("...$" lhs 1 macros::common::% "...$" rhs 0), [async |[lhs, rhs]| {
|
||||
call(sym!(std::ops::mod::resolve), (resolve(lhs).await, resolve(rhs).await)).await
|
||||
.rule(mactreev!("...$" lhs 1 macros::common::% "...$" rhs 0), [async |cx, [lhs, rhs]| {
|
||||
call(sym!(std::ops::mod::resolve), (cx.recur(lhs), cx.recur(rhs))).await
|
||||
}])
|
||||
.finish(),
|
||||
build_macro(Some(3), ["."])
|
||||
.rule(mactreev!("...$" lhs 1 macros::common::. "...$" rhs 0), [async |[lhs, rhs]| {
|
||||
call(sym!(std::ops::get::resolve), (resolve(lhs).await, resolve(rhs).await)).await
|
||||
.rule(mactreev!("...$" lhs 1 macros::common::. "...$" rhs 0), [async |cx, [lhs, rhs]| {
|
||||
call(sym!(std::ops::get::resolve), (cx.recur(lhs), cx.recur(rhs))).await
|
||||
}])
|
||||
.finish(),
|
||||
build_macro(None, ["comma_list", ","])
|
||||
.rule(
|
||||
mactreev!(macros::common::comma_list ( "...$" head 0 macros::common::, "...$" tail 1)),
|
||||
[async |[head, tail]| {
|
||||
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(new_atom(head)).await?);
|
||||
Ok(tail)
|
||||
})
|
||||
.await
|
||||
[async |mut cx, [head, tail]| {
|
||||
let mut tail: HomoTpl<TAtom<MacTree>> =
|
||||
cx.exec(cx.recur(mactree!(macros::common::comma_list "push" tail ;))).await?;
|
||||
tail.0.insert(0, cx.exec(new_atom(head)).await?);
|
||||
Ok(tail)
|
||||
}],
|
||||
)
|
||||
.rule(mactreev!(macros::common::comma_list ( "...$" final_tail 0 )), [async |[tail]| {
|
||||
HomoTpl(vec![new_atom(tail)])
|
||||
}])
|
||||
.rule(mactreev!(macros::common::comma_list()), [async |[]| UntypedTuple(Vec::new())])
|
||||
.rule(mactreev!(macros::common::comma_list ( "...$" final_tail 0 )), [
|
||||
async |_cx, [tail]| HomoTpl(vec![new_atom(tail)]),
|
||||
])
|
||||
.rule(mactreev!(macros::common::comma_list()), [async |_cx, []| UntypedTuple(Vec::new())])
|
||||
.finish(),
|
||||
build_macro(None, ["semi_list", ";"])
|
||||
.rule(
|
||||
mactreev!(macros::common::semi_list ( "...$" head 0 macros::common::; "...$" tail 1)),
|
||||
[async |[head, tail]| {
|
||||
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(new_atom(head)).await?);
|
||||
Ok(tail)
|
||||
})
|
||||
.await
|
||||
[async |mut cx, [head, tail]| {
|
||||
let mut tail: HomoTpl<TAtom<MacTree>> =
|
||||
cx.exec(cx.recur(mactree!(macros::common::semi_list "push" tail ;))).await?;
|
||||
tail.0.insert(0, cx.exec(new_atom(head)).await?);
|
||||
Ok(tail)
|
||||
}],
|
||||
)
|
||||
.rule(mactreev!(macros::common::semi_list ( "...$" final_tail 0 )), [async |[tail]| {
|
||||
HomoTpl(vec![new_atom(tail)])
|
||||
}])
|
||||
.rule(mactreev!(macros::common::semi_list()), [async |[]| UntypedTuple(Vec::new())])
|
||||
.rule(mactreev!(macros::common::semi_list ( "...$" final_tail 0 )), [
|
||||
async |_cx, [tail]| HomoTpl(vec![new_atom(tail)]),
|
||||
])
|
||||
.rule(mactreev!(macros::common::semi_list()), [async |_cx, []| UntypedTuple(Vec::new())])
|
||||
.finish(),
|
||||
]),
|
||||
])
|
||||
|
||||
@@ -8,10 +8,8 @@ use orchid_base::{
|
||||
Comment, OrcRes, Paren, Parsed, Snippet, Token, clone, expect_end, expect_tok, is, line_items,
|
||||
mk_errv, report, sym, token_errv, try_pop_no_fluff, with_reporter,
|
||||
};
|
||||
use orchid_extension::TAtom;
|
||||
use orchid_extension::{ToExpr, TryFromExpr};
|
||||
use orchid_extension::gen_expr::{call, new_atom};
|
||||
use orchid_extension::{PSnippet, ParsCtx, ParsedLine, Parser};
|
||||
use orchid_extension::{PSnippet, ParsCtx, ParsedLine, Parser, TAtom, ToExpr, TryFromExpr};
|
||||
|
||||
use crate::macros::let_line::{dealias_mac_v, parse_tokv};
|
||||
use crate::macros::macro_value::{Macro, MacroData, Rule};
|
||||
|
||||
@@ -13,6 +13,7 @@ use crate::macros::macro_value::Macro;
|
||||
use crate::macros::mactree_lexer::MacTreeLexer;
|
||||
use crate::macros::match_macros::{MatcherAtom, gen_match_macro_lib};
|
||||
use crate::macros::ph_lexer::{PhAtom, PhLexer};
|
||||
use crate::macros::resolve::ArgStack;
|
||||
use crate::macros::stdlib::gen_std_macro_lib;
|
||||
use crate::macros::utils::MacroBodyArgCollector;
|
||||
use crate::{MacTree, StdSystem};
|
||||
@@ -38,6 +39,7 @@ impl SystemCard for MacroSystem {
|
||||
Some(PhAtom::ops()),
|
||||
Some(MacroBodyArgCollector::ops()),
|
||||
Some(MatcherAtom::ops()),
|
||||
Some(ArgStack::ops()),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,8 @@ use std::borrow::Cow;
|
||||
use std::rc::Rc;
|
||||
|
||||
use never::Never;
|
||||
use orchid_base::IStr;
|
||||
use orchid_base::Sym;
|
||||
use orchid_extension::Atomic;
|
||||
use orchid_extension::{OwnedAtom, OwnedVariant};
|
||||
use orchid_base::{IStr, Sym};
|
||||
use orchid_extension::{Atomic, OwnedAtom, OwnedVariant};
|
||||
|
||||
use crate::macros::mactree::MacTreeSeq;
|
||||
use crate::macros::rule::matcher::Matcher;
|
||||
|
||||
@@ -9,9 +9,7 @@ use orchid_api_derive::Coding;
|
||||
use orchid_base::{
|
||||
FmtCtx, FmtUnit, Format, IStr, OrcErrv, Paren, Pos, Sym, Variants, indent, tl_cache,
|
||||
};
|
||||
use orchid_extension::Atomic;
|
||||
use orchid_extension::Expr;
|
||||
use orchid_extension::{OwnedAtom, OwnedVariant};
|
||||
use orchid_extension::{Atomic, Expr, OwnedAtom, OwnedVariant};
|
||||
|
||||
fn union_rc_sets(seq: impl IntoIterator<Item = Rc<HashSet<Sym>>>) -> Rc<HashSet<Sym>> {
|
||||
let mut acc = Rc::<HashSet<Sym>>::default();
|
||||
@@ -172,9 +170,10 @@ impl MacTok {
|
||||
impl Format for MacTok {
|
||||
async fn print<'a>(&'a self, c: &'a (impl FmtCtx + ?Sized + 'a)) -> FmtUnit {
|
||||
match self {
|
||||
Self::Value(v) => v.print(c).await,
|
||||
Self::Value(v) => tl_cache!(Rc<Variants>: Rc::new(Variants::default().bounded("$({0b})")))
|
||||
.units([v.print(c).await]),
|
||||
Self::Lambda(arg, b) => tl_cache!(Rc<Variants>: Rc::new(Variants::default()
|
||||
.unbounded("\\{0} {1l}")
|
||||
// .unbounded("\\{0} {1l}")
|
||||
.bounded("(\\{0} {1b})")))
|
||||
.units([arg.print(c).boxed_local().await, b.print(c).await]),
|
||||
Self::Name(n) => format!("{n}").into(),
|
||||
|
||||
@@ -2,12 +2,10 @@ use std::ops::RangeInclusive;
|
||||
|
||||
use futures::FutureExt;
|
||||
use itertools::chain;
|
||||
use orchid_base::Paren;
|
||||
use orchid_base::{OrcRes, PARENS, is, mk_errv};
|
||||
use orchid_base::{OrcRes, PARENS, Paren, is, mk_errv};
|
||||
use orchid_extension::gen_expr::new_atom;
|
||||
use orchid_extension::{LexContext, Lexer, err_not_applicable};
|
||||
use orchid_extension::p_tree2gen;
|
||||
use orchid_extension::tree::{GenTok, GenTokTree, x_tok};
|
||||
use orchid_extension::{LexContext, Lexer, err_not_applicable, p_tree2gen};
|
||||
|
||||
use crate::macros::instantiate_tpl::InstantiateTplCall;
|
||||
use crate::macros::let_line::parse_tok;
|
||||
|
||||
@@ -6,14 +6,12 @@ use futures::{Stream, StreamExt, stream};
|
||||
use never::Never;
|
||||
use orchid_api_derive::Coding;
|
||||
use orchid_base::{OrcRes, Sym, fmt, is, mk_errv, sym};
|
||||
use orchid_extension::ToExpr;
|
||||
use orchid_extension::{ExecHandle, exec};
|
||||
use orchid_extension::{Expr, ExprHandle};
|
||||
use orchid_extension::gen_expr::{GExpr, arg, bot, call, call_v, lam, new_atom};
|
||||
use orchid_extension::gen_expr::{bot, call, call_v, lam, new_atom};
|
||||
use orchid_extension::tree::{GenMember, fun, prefix};
|
||||
use orchid_extension::{Atomic, OwnedAtom, OwnedVariant, TAtom};
|
||||
use orchid_extension::{
|
||||
Atomic, ExecHandle, Expr, ExprHandle, OwnedAtom, OwnedVariant, TAtom, ToExpr, exec,
|
||||
};
|
||||
|
||||
use crate::macros::resolve::resolve;
|
||||
use crate::macros::utils::{build_macro, mactree, mactreev};
|
||||
use crate::std::reflection::sym_atom::SymAtom;
|
||||
use crate::{HomoTpl, MacTok, MacTree, OrcOpt, Tpl, UntypedTuple, api};
|
||||
@@ -83,78 +81,63 @@ pub async fn gen_match_macro_lib() -> Vec<GenMember> {
|
||||
}),
|
||||
build_macro(None, ["match", "match_rule", "_row", "=>"])
|
||||
.rule(mactreev!("pattern::match" "...$" value 0 { "..$" rules 0 }), [
|
||||
async |[value, rules]| {
|
||||
exec(async move |mut h| {
|
||||
let rule_lines = h
|
||||
.exec::<HomoTpl<TAtom<MacTree>>>(call(
|
||||
sym!(macros::resolve),
|
||||
new_atom(mactree!(macros::common::semi_list "push" rules.clone();)),
|
||||
))
|
||||
.await?;
|
||||
let mut rule_atoms = Vec::<(TAtom<MatcherAtom>, Expr)>::new();
|
||||
for line_mac in rule_lines.0.iter() {
|
||||
let Tpl((matcher, body)) = h
|
||||
.exec(call(
|
||||
sym!(macros::resolve),
|
||||
new_atom(mactree!(pattern::_row "push" line_mac.own().await ;)),
|
||||
))
|
||||
.await?;
|
||||
rule_atoms.push((matcher, body));
|
||||
}
|
||||
let base_case = lam::<0>(bot(mk_errv(
|
||||
async |mut cx, [value, rules]| {
|
||||
let rule_lines: HomoTpl<TAtom<MacTree>> =
|
||||
cx.exec(cx.recur(mactree!(macros::common::semi_list "push" rules.clone();))).await?;
|
||||
let mut rule_atoms = Vec::<(TAtom<MatcherAtom>, Expr)>::new();
|
||||
for line_mac in rule_lines.0.iter() {
|
||||
let Tpl((matcher, body)) =
|
||||
cx.exec(cx.recur(mactree!(pattern::_row "push" line_mac.own().await ;))).await?;
|
||||
rule_atoms.push((matcher, body));
|
||||
}
|
||||
let base_case = lam(async |_| {
|
||||
bot(mk_errv(
|
||||
is("No branches match").await,
|
||||
"None of the patterns matches this value",
|
||||
[rules.pos()],
|
||||
)))
|
||||
.await;
|
||||
let match_expr = stream::iter(rule_atoms.into_iter().rev())
|
||||
.fold(base_case, async |tail, (mat, body)| {
|
||||
lam::<0>(call(sym!(pattern::match_one), (mat, arg(0), body, call(tail, arg(0)))))
|
||||
.await
|
||||
})
|
||||
.await;
|
||||
Ok(call(match_expr, resolve(value).await))
|
||||
))
|
||||
})
|
||||
.await
|
||||
.await;
|
||||
let match_expr = stream::iter(rule_atoms.into_iter().rev())
|
||||
.fold(base_case, |tail, (mat, body)| {
|
||||
lam(async move |x| {
|
||||
call(sym!(pattern::match_one), (mat, x, body, call(tail, x))).await
|
||||
})
|
||||
})
|
||||
.await;
|
||||
Ok(call(match_expr, cx.recur(value)))
|
||||
},
|
||||
])
|
||||
.rule(mactreev!(pattern::match_rule (( "...$" pattern 0 ))), [async |[pattern]| {
|
||||
resolve(mactree!(pattern::match_rule "push" pattern; )).await
|
||||
.rule(mactreev!(pattern::match_rule (( "...$" pattern 0 ))), [async |cx, [pattern]| {
|
||||
cx.recur(mactree!(pattern::match_rule "push" pattern; )).to_gen().await
|
||||
}])
|
||||
.rule(mactreev!(pattern::match_rule ( macros::common::_ )), [async |[]| {
|
||||
.rule(mactreev!(pattern::match_rule ( macros::common::_ )), [async |_cx, []| {
|
||||
Ok(new_atom(MatcherAtom {
|
||||
keys: Vec::new(),
|
||||
matcher: lam::<0>(OrcOpt(Some(Tpl(())))).await.create().await,
|
||||
matcher: lam(async |_| OrcOpt(Some(Tpl(()))).to_gen().await).await.create().await,
|
||||
}))
|
||||
}])
|
||||
.rule(mactreev!(pattern::_row ( "...$" pattern 0 pattern::=> "...$" value 1 )), [
|
||||
async |[pattern, mut value]| {
|
||||
exec(async move |mut h| -> OrcRes<Tpl<(TAtom<MatcherAtom>, GExpr)>> {
|
||||
let Ok(pat) = h
|
||||
.exec::<TAtom<MatcherAtom>>(call(
|
||||
sym!(macros::resolve),
|
||||
new_atom(mactree!(pattern::match_rule "push" pattern.clone();)),
|
||||
))
|
||||
.await
|
||||
else {
|
||||
return Err(mk_errv(
|
||||
is("Invalid pattern").await,
|
||||
format!("Could not parse {} as a match pattern", fmt(&pattern).await),
|
||||
[pattern.pos()],
|
||||
));
|
||||
};
|
||||
value = (pat.keys())
|
||||
.fold(value, async |value, name| mactree!("l_" name; ( "push" value ; )))
|
||||
.await;
|
||||
Ok(Tpl((pat, resolve(value).await)))
|
||||
})
|
||||
.await
|
||||
async |mut cx, [pattern, mut value]| -> OrcRes<Tpl<(TAtom<MatcherAtom>, _)>> {
|
||||
let Ok(pat): OrcRes<TAtom<MatcherAtom>> =
|
||||
cx.exec(cx.recur(mactree!(pattern::match_rule "push" pattern.clone();))).await
|
||||
else {
|
||||
return Err(mk_errv(
|
||||
is("Invalid pattern").await,
|
||||
format!("Could not parse {} as a match pattern", fmt(&pattern).await),
|
||||
[pattern.pos()],
|
||||
));
|
||||
};
|
||||
value = (pat.keys())
|
||||
.fold(value, async |value, name| mactree!("l_" name; ( "push" value ; )))
|
||||
.await;
|
||||
Ok(Tpl((pat, cx.recur(value))))
|
||||
},
|
||||
])
|
||||
.finish(),
|
||||
fun(true, "ref_body", async |val| OrcOpt(Some(UntypedTuple(vec![val])))),
|
||||
build_macro(None, ["ref"])
|
||||
.rule(mactreev!(pattern::match_rule(pattern::ref "$" name)), [async |[name]| {
|
||||
.rule(mactreev!(pattern::match_rule(pattern::ref "$" name)), [async |_cx, [name]| {
|
||||
let MacTok::Name(name) = name.tok() else {
|
||||
return Err(mk_errv(
|
||||
is("pattern 'ref' requires a name to bind to").await,
|
||||
|
||||
@@ -8,6 +8,7 @@ pub mod mactree;
|
||||
mod mactree_lexer;
|
||||
pub mod match_macros;
|
||||
mod ph_lexer;
|
||||
pub mod postmac;
|
||||
mod resolve;
|
||||
mod rule;
|
||||
pub mod stdlib;
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
use orchid_api_derive::Coding;
|
||||
use orchid_base::{FmtUnit, OrcRes, es, is, mk_errv, name_char, name_start};
|
||||
use orchid_extension::Atomic;
|
||||
use orchid_extension::gen_expr::new_atom;
|
||||
use orchid_extension::{LexContext, Lexer, err_not_applicable};
|
||||
use orchid_extension::tree::{GenTokTree, x_tok};
|
||||
use orchid_extension::{ThinAtom, ThinVariant};
|
||||
use orchid_extension::{Atomic, LexContext, Lexer, ThinAtom, ThinVariant, err_not_applicable};
|
||||
|
||||
use crate::macros::mactree::{Ph, PhKind};
|
||||
|
||||
|
||||
53
orchid-std/src/macros/postmac.rs
Normal file
53
orchid-std/src/macros/postmac.rs
Normal file
@@ -0,0 +1,53 @@
|
||||
use std::any::TypeId;
|
||||
use std::borrow::Cow;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use never::Never;
|
||||
use orchid_extension::gen_expr::GExpr;
|
||||
use orchid_extension::{
|
||||
Atomic, ClonableToExprDyn, MethodSetBuilder, OwnedAtom, OwnedVariant, ToExpr, ToExprFuture,
|
||||
};
|
||||
|
||||
fn assert_not_gexpr<T: 'static>() {
|
||||
assert_ne!(
|
||||
TypeId::of::<T>(),
|
||||
TypeId::of::<GExpr>(),
|
||||
"Cannot output GExpr, use PostMac::boxed or PostMac::boxed_clone"
|
||||
);
|
||||
}
|
||||
|
||||
struct PostMacCx<'a>(PhantomData<&'a ()>);
|
||||
impl PostMacCx<'_> {
|
||||
pub fn ex<T: ToExpr>(&self, val: PostMac<T>) -> T { val.0 }
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct PostMac<T: ToExpr + 'static>(T);
|
||||
impl<T: ToExpr + 'static> PostMac<T> {
|
||||
pub fn new(t: T) -> Self {
|
||||
assert_not_gexpr::<T>();
|
||||
Self(t)
|
||||
}
|
||||
}
|
||||
impl<T: Future<Output: ToExpr + Clone + 'static> + Clone + 'static> PostMac<ToExprFuture<T>> {
|
||||
pub fn with(f: impl for<'a> FnOnce(PostMacCx<'a>) -> T + Clone + 'static) -> Self {
|
||||
assert_not_gexpr::<T>();
|
||||
PostMac(ToExprFuture(f(PostMacCx(PhantomData))))
|
||||
}
|
||||
}
|
||||
impl<T: ToExpr + Clone + 'static> PostMac<T> {
|
||||
pub fn atom(self) -> PostMacAtom { PostMac(Box::new(self.0)) }
|
||||
}
|
||||
impl<T: ToExpr + 'static> From<T> for PostMac<T> {
|
||||
fn from(value: T) -> Self { Self(value) }
|
||||
}
|
||||
pub type PostMacAtom = PostMac<Box<dyn ClonableToExprDyn>>;
|
||||
impl Atomic for PostMacAtom {
|
||||
type Data = ();
|
||||
type Variant = OwnedVariant;
|
||||
fn reg_methods() -> MethodSetBuilder<Self> { MethodSetBuilder::new() }
|
||||
}
|
||||
impl OwnedAtom for PostMacAtom {
|
||||
type Refs = Never;
|
||||
async fn val(&self) -> Cow<'_, Self::Data> { Cow::Owned(()) }
|
||||
}
|
||||
@@ -1,71 +1,146 @@
|
||||
use std::borrow::Cow;
|
||||
use std::collections::VecDeque;
|
||||
use std::ops::{Add, Range};
|
||||
use std::rc::Rc;
|
||||
|
||||
use async_fn_stream::stream;
|
||||
use futures::{FutureExt, StreamExt, stream};
|
||||
use hashbrown::{HashMap, HashSet};
|
||||
use itertools::Itertools;
|
||||
use never::Never;
|
||||
use orchid_base::{NameLike, Paren, Pos, Sym, VPath, fmt, is, log, mk_errv};
|
||||
use orchid_extension::gen_expr::{GExpr, arg, bot, call, call_v, dyn_lambda, new_atom};
|
||||
use orchid_extension::{ReflMemKind, TAtom, ToExpr, exec, refl};
|
||||
use orchid_extension::gen_expr::{GExpr, GExprKind, bot, call, call_v, new_atom};
|
||||
use orchid_extension::{
|
||||
Atomic, ExecHandle, OwnedAtom, OwnedVariant, ReflMemKind, TAtom, ToExpr, ToExprFuture, exec, refl,
|
||||
};
|
||||
use subslice_offset::SubsliceOffset;
|
||||
use substack::Substack;
|
||||
|
||||
use crate::macros::macro_value::{Macro, Rule};
|
||||
use crate::macros::mactree::MacTreeSeq;
|
||||
use crate::macros::postmac::{PostMac, PostMacAtom};
|
||||
use crate::macros::rule::state::{MatchState, StateEntry};
|
||||
use crate::{MacTok, MacTree};
|
||||
|
||||
pub async fn resolve(val: MacTree) -> GExpr {
|
||||
exec(async move |mut h| {
|
||||
writeln!(log("debug"), "Macro-resolving {}", fmt(&val).await).await;
|
||||
let root = refl();
|
||||
let mut macros = HashMap::new();
|
||||
for n in val.glossary() {
|
||||
let (foot, body) = n.split_last_seg();
|
||||
let new_name = VPath::new(body.iter().cloned())
|
||||
.name_with_suffix(is(&format!("__macro__{foot}")).await)
|
||||
.to_sym()
|
||||
.await;
|
||||
if let Ok(ReflMemKind::Const) = root.get_by_path(&new_name).await.map(|m| m.kind()) {
|
||||
let Ok(mac) = h.exec::<TAtom<Macro>>(new_name).await else { continue };
|
||||
let mac = mac.own().await;
|
||||
macros.entry(mac.0.canonical_name.clone()).or_insert(mac);
|
||||
pub enum ArgStackKind {
|
||||
End,
|
||||
Cons(Sym, ArgStack),
|
||||
}
|
||||
#[derive(Clone)]
|
||||
pub struct ArgStack {
|
||||
kind: Rc<ArgStackKind>,
|
||||
len: usize,
|
||||
}
|
||||
impl ArgStack {
|
||||
pub fn end() -> Self { ArgStack { kind: Rc::new(ArgStackKind::End), len: 0 } }
|
||||
}
|
||||
impl Default for ArgStack {
|
||||
fn default() -> Self { Self::end() }
|
||||
}
|
||||
impl Atomic for ArgStack {
|
||||
type Data = ();
|
||||
type Variant = OwnedVariant;
|
||||
}
|
||||
impl OwnedAtom for ArgStack {
|
||||
type Refs = Never;
|
||||
async fn val(&self) -> Cow<'_, Self::Data> { Cow::Owned(()) }
|
||||
}
|
||||
|
||||
/// # TODO
|
||||
///
|
||||
/// convert macro system to return MacTree or otherwise bring it up to
|
||||
/// speed with the new [ToExpr] / [GExpr] division
|
||||
///
|
||||
/// Idea: MacTree needs to be passed wherever the meaning of an expression can
|
||||
/// change depending on where in the tree it is bound
|
||||
///
|
||||
/// Idea: lowering MacTree to ToExpr implementors is possible by just knowing
|
||||
/// what names are bound, not their values, but lowering it to GExpr is not.
|
||||
///
|
||||
/// Problem: The required information is stackbound, so recursive macro matching
|
||||
/// needs to be a single coroutine. Even when it forks out to Orchid, recursive
|
||||
/// calls need to point back to this coroutine. Being a coroutine, this
|
||||
/// recursion can overflow the Rust stack.
|
||||
///
|
||||
/// Limits:
|
||||
///
|
||||
/// - The concrete MacTree being generated sometimes depends on recursive macro
|
||||
/// calls which need to complete before we return a MacTree
|
||||
/// - Any placeholders representing expressions must be recursed over before
|
||||
/// returning in a MacTree
|
||||
/// - Exactly one of these things must be done on a subtree
|
||||
///
|
||||
/// Takeaways:
|
||||
///
|
||||
/// - Resolution should not lower to GExpr
|
||||
/// - Consider separate types MacTree vs resolved tree
|
||||
/// - MacTree can be built for the purpose of passing into recur
|
||||
/// - Resolved tree can be built for the purpose of returning
|
||||
/// - cannot contain [...], {...}, (), ( ... \. )
|
||||
/// - is pretty much GExpr with sym / dynamic arg binding instead of
|
||||
/// numbered. Can this be a wrapper type over ToExpr instead?
|
||||
/// - In order to move recursive state off the stack, we need a loophole
|
||||
/// for lambdas
|
||||
/// - Ensures that resolution only happens exactly once which is important
|
||||
/// because double resolve can produce bugs that are difficult to catch
|
||||
/// - Macros may return ResolvedTree but they can also return a datastructure
|
||||
/// containing MacTree
|
||||
/// - Macros may never lower ResolvedTree to GExpr directly because it may
|
||||
/// refer to bound arguments by name
|
||||
/// - Macros returning datastructures can only ever be called as logic while
|
||||
/// those returning ResolvedTree can only ever be inlined
|
||||
/// - this is a type system concern so addressing it here is unnecessary
|
||||
///
|
||||
/// Problems:
|
||||
/// - ToExpr are not usually copiable by default
|
||||
/// - plain-orchid macros should be able to annotate data-to-return and
|
||||
/// data-to-resolve with the same tick symbol to limit conceptual complexity,
|
||||
/// - the case where a macro deliberately wants to bind a name explicitly within
|
||||
/// a subexpression is tricky
|
||||
///
|
||||
/// The best option probably remains for resolve to process and return MacTree,
|
||||
/// and for there to be a separate "lower" function. Nothing as yet suggests
|
||||
/// however that macros can't be allowed to return different types
|
||||
pub async fn resolve(h: &mut ExecHandle<'_>, val: MacTree, arg_stk: ArgStack) -> PostMacAtom {
|
||||
writeln!(log("debug"), "Macro-resolving {}", fmt(&val).await).await;
|
||||
let root = refl();
|
||||
let mut macros = HashMap::new();
|
||||
for n in val.glossary() {
|
||||
let (foot, body) = n.split_last_seg();
|
||||
let new_name = VPath::new(body.iter().cloned())
|
||||
.name_with_suffix(is(&format!("__macro__{foot}")).await)
|
||||
.to_sym()
|
||||
.await;
|
||||
if let Ok(ReflMemKind::Const) = root.get_by_path(&new_name).await.map(|m| m.kind()) {
|
||||
let Ok(mac) = h.exec::<TAtom<Macro>>(new_name).await else { continue };
|
||||
let mac = mac.own().await;
|
||||
macros.entry(mac.0.canonical_name.clone()).or_insert(mac);
|
||||
}
|
||||
}
|
||||
let mut exclusive = Vec::new();
|
||||
let mut prios = Vec::<u64>::new();
|
||||
let mut priod = Vec::<FilteredMacroRecord>::new();
|
||||
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(val.glossary()) {
|
||||
record.rules.push(rule_i);
|
||||
}
|
||||
}
|
||||
let mut exclusive = Vec::new();
|
||||
let mut prios = Vec::<u64>::new();
|
||||
let mut priod = Vec::<FilteredMacroRecord>::new();
|
||||
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(val.glossary()) {
|
||||
record.rules.push(rule_i);
|
||||
}
|
||||
}
|
||||
if !record.rules.is_empty() {
|
||||
match mac.0.prio {
|
||||
None => exclusive.push(record),
|
||||
Some(prio) => {
|
||||
let i = prios.partition_point(|p| *p > prio);
|
||||
prios.insert(i, prio);
|
||||
priod.insert(i, record);
|
||||
},
|
||||
}
|
||||
if !record.rules.is_empty() {
|
||||
match mac.0.prio {
|
||||
None => exclusive.push(record),
|
||||
Some(prio) => {
|
||||
let i = prios.partition_point(|p| *p > prio);
|
||||
prios.insert(i, prio);
|
||||
priod.insert(i, record);
|
||||
},
|
||||
}
|
||||
}
|
||||
let mut rctx = ResolveCtx { exclusive, priod };
|
||||
let gex = resolve_one(&mut rctx, Substack::Bottom, &val).await;
|
||||
writeln!(
|
||||
log("debug"),
|
||||
"Macro-resolution over {}\nreturned {}",
|
||||
fmt(&val).await,
|
||||
fmt(&gex).await
|
||||
)
|
||||
.await;
|
||||
gex
|
||||
})
|
||||
.await
|
||||
}
|
||||
let mut rctx = ResolveCtx { exclusive, priod };
|
||||
let gex = resolve_one(&mut rctx, arg_stk, &val).await;
|
||||
writeln!(log("debug"), "Macro-resolution over {}", fmt(&val).await).await;
|
||||
gex
|
||||
}
|
||||
|
||||
/// Rules belonging to one macro that passed a particular filter
|
||||
@@ -83,37 +158,54 @@ struct ResolveCtx<'a> {
|
||||
pub priod: Vec<FilteredMacroRecord<'a>>,
|
||||
}
|
||||
|
||||
async fn resolve_one(
|
||||
ctx: &mut ResolveCtx<'_>,
|
||||
arg_stk: Substack<'_, Sym>,
|
||||
value: &MacTree,
|
||||
) -> GExpr {
|
||||
async fn resolve_one(ctx: &mut ResolveCtx<'_>, arg_stk: ArgStack, value: &MacTree) -> PostMacAtom {
|
||||
eprintln!("Resolving unit {}", fmt(value).await);
|
||||
match value.tok() {
|
||||
MacTok::Ph(_) | MacTok::Slot => panic!("Forbidden element in value mactree"),
|
||||
MacTok::Bottom(err) => bot(err.clone()),
|
||||
MacTok::Value(v) => v.clone().to_gen().await,
|
||||
MacTok::Name(n) => match arg_stk.iter().position(|arg| arg == n) {
|
||||
Some(de_bruijn) => arg((arg_stk.len() - 1 - de_bruijn).try_into().unwrap()),
|
||||
None => n.clone().to_gen().await,
|
||||
MacTok::Bottom(err) => PostMac::new(bot(err.clone())).atom(),
|
||||
MacTok::Value(v) => {
|
||||
eprintln!("Found value {}", fmt(v).await);
|
||||
PostMac::new(v.clone()).atom()
|
||||
},
|
||||
MacTok::Name(n) => {
|
||||
eprintln!("Looking for {n} among [");
|
||||
let mut cur = &arg_stk;
|
||||
let mut counter = 0;
|
||||
while let ArgStackKind::Cons(name, next) = &*cur.kind {
|
||||
cur = next;
|
||||
counter += 1;
|
||||
eprintln!("{name}, ");
|
||||
if name == n {
|
||||
return PostMac::new(GExprKind::Arg(counter).at(value.pos())).atom();
|
||||
}
|
||||
}
|
||||
PostMac::new(n.clone()).atom()
|
||||
},
|
||||
MacTok::Lambda(arg, body) => {
|
||||
eprintln!("Found lambda \\{} {}", fmt(arg).await, fmt(body).await);
|
||||
let MacTok::Name(name) = &*arg.tok else {
|
||||
return bot(mk_errv(
|
||||
return PostMac::new(bot(mk_errv(
|
||||
is("Syntax error after macros").await,
|
||||
"This token ends up as a binding, consider replacing it with a name",
|
||||
[arg.pos()],
|
||||
));
|
||||
)))
|
||||
.atom();
|
||||
};
|
||||
let arg_pos = arg_stk.len() as u64;
|
||||
let arg_stk = arg_stk.push(name.clone());
|
||||
dyn_lambda(arg_pos, resolve_seq(ctx, arg_stk, body.clone(), value.pos()).await).await
|
||||
let arg_stk =
|
||||
ArgStack { len: arg_stk.len + 1, kind: Rc::new(ArgStackKind::Cons(name.clone(), arg_stk)) };
|
||||
let body = resolve_seq(ctx, arg_stk, body.clone(), value.pos()).await;
|
||||
let body2 = body.clone();
|
||||
let pos = value.pos();
|
||||
PostMac::with(async |cx| GExprKind::Lambda(Box::new(cx.ex(body).to_gen().await)).at(pos))
|
||||
.atom()
|
||||
},
|
||||
MacTok::S(Paren::Round, body) => resolve_seq(ctx, arg_stk, body.clone(), value.pos()).await,
|
||||
MacTok::S(..) => bot(mk_errv(
|
||||
MacTok::S(..) => PostMac::new(bot(mk_errv(
|
||||
is("Leftover [] or {} not matched by macro").await,
|
||||
format!("{} was not matched by any macro", fmt(value).await),
|
||||
[value.pos()],
|
||||
)),
|
||||
)))
|
||||
.atom(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,17 +225,18 @@ fn subsection<T>(
|
||||
|
||||
async fn resolve_seq(
|
||||
ctx: &mut ResolveCtx<'_>,
|
||||
arg_stk: Substack<'_, Sym>,
|
||||
arg_stk: ArgStack,
|
||||
val: MacTreeSeq,
|
||||
fallback_pos: Pos,
|
||||
) -> GExpr {
|
||||
) -> PostMacAtom {
|
||||
if val.items.is_empty() {
|
||||
return bot(mk_errv(
|
||||
return PostMac::new(bot(mk_errv(
|
||||
is("Empty sequence").await,
|
||||
"() or (\\arg ) left after macro execution. \
|
||||
This is usually caused by an incomplete call to a macro with bad error detection",
|
||||
[fallback_pos],
|
||||
));
|
||||
)))
|
||||
.atom();
|
||||
}
|
||||
// A sorted collection of overlapping but non-nested matches to exclusive
|
||||
// macros
|
||||
@@ -226,14 +319,15 @@ async fn resolve_seq(
|
||||
})
|
||||
.reduce(|l, r| l + r);
|
||||
if let Some(error) = error {
|
||||
return bot(error);
|
||||
return PostMac::new(bot(error)).atom();
|
||||
}
|
||||
// no conflicts, apply all exclusive matches
|
||||
for (range, mac, rule, state) in x_matches.into_iter().rev() {
|
||||
// backwards so that the non-overlapping ranges remain valid
|
||||
let pos = (state.names().flat_map(|r| r.1).cloned().reduce(Pos::add))
|
||||
.expect("All macro rules must contain at least one locally defined name");
|
||||
let subex = mk_body_call(mac, rule, &state, pos.clone()).await.to_expr().await;
|
||||
let subex =
|
||||
mk_body_call(mac, rule, &state, pos.clone(), arg_stk.clone()).await.to_expr().await;
|
||||
new_val.splice(range, [MacTok::Value(subex).at(pos)]);
|
||||
}
|
||||
};
|
||||
@@ -251,7 +345,8 @@ async fn resolve_seq(
|
||||
let range = pre.len()..new_val.len() - suf.len();
|
||||
let pos = (state.names().flat_map(|pair| pair.1).cloned().reduce(Pos::add))
|
||||
.expect("All macro rules must contain at least one locally defined name");
|
||||
let subex = mk_body_call(mac, rule, &state, pos.clone()).await.to_expr().await;
|
||||
let subex =
|
||||
mk_body_call(mac, rule, &state, pos.clone(), arg_stk.clone()).await.to_expr().await;
|
||||
std::mem::drop(state);
|
||||
new_val.splice(range, [MacTok::Value(subex).at(pos)]);
|
||||
}
|
||||
@@ -267,11 +362,21 @@ async fn resolve_seq(
|
||||
let first = exprs.pop_front().expect(
|
||||
"We checked first that it isn't empty, and named macros get replaced with their results",
|
||||
);
|
||||
stream::iter(exprs).fold(first, async |f, x| call(f, x).await).await
|
||||
PostMac::with(async move |cx| {
|
||||
stream::iter(exprs).fold(cx.ex(first), async |f, x| call(f, cx.ex(x)).await).await
|
||||
})
|
||||
.await
|
||||
.atom()
|
||||
}
|
||||
|
||||
async fn mk_body_call(mac: &Macro, rule: &Rule, state: &MatchState<'_>, pos: Pos) -> GExpr {
|
||||
let mut call_args = vec![];
|
||||
async fn mk_body_call(
|
||||
mac: &Macro,
|
||||
rule: &Rule,
|
||||
state: &MatchState<'_>,
|
||||
pos: Pos,
|
||||
arg_stk: ArgStack,
|
||||
) -> GExpr {
|
||||
let mut call_args = vec![new_atom(arg_stk).at(Pos::None)];
|
||||
for name in rule.ph_names.iter() {
|
||||
call_args.push(match state.get(name).expect("Missing state entry for placeholder") {
|
||||
StateEntry::Scalar(scal) => new_atom((**scal).clone()),
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
use std::fmt;
|
||||
use std::rc::Rc;
|
||||
|
||||
use orchid_base::Sym;
|
||||
use orchid_base::{OrcRes, is};
|
||||
use orchid_base::{OrcRes, Sym, is};
|
||||
|
||||
use super::any_match::any_match;
|
||||
use super::build::mk_any;
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
use std::fmt;
|
||||
|
||||
use itertools::Itertools;
|
||||
use orchid_base::{PARENS, Paren};
|
||||
use orchid_base::{IStr, Side, Sym};
|
||||
use orchid_base::{IStr, PARENS, Paren, Side, Sym};
|
||||
|
||||
pub enum ScalMatcher {
|
||||
Name(Sym),
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
use std::any::Any;
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use orchid_base::Pos;
|
||||
use orchid_base::Sym;
|
||||
use orchid_base::{IStr, join_maps, match_mapping};
|
||||
use orchid_base::{IStr, Pos, Sym, join_maps, match_mapping};
|
||||
|
||||
use crate::macros::MacTree;
|
||||
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
use orchid_extension::tree::{GenMember, prefix};
|
||||
|
||||
use crate::macros::resolve::resolve;
|
||||
use crate::macros::utils::{build_macro, mactree, mactreev};
|
||||
|
||||
pub async fn gen_functional_macro_lib() -> Vec<GenMember> {
|
||||
prefix("std::fn", [build_macro(Some(4), ["|>"])
|
||||
.rule(mactreev!("...$" lhs 0 "std::fn::|>" "$" fun "...$" rhs 0), [async |[lhs, fun, rhs]| {
|
||||
resolve(mactree!(("push" fun ; "push" lhs ;) "pushv" rhs ;)).await
|
||||
}])
|
||||
.rule(mactreev!("...$" lhs 0 "std::fn::|>" "$" fun "...$" rhs 0), [
|
||||
async |cx, [lhs, fun, rhs]| cx.recur(mactree!(("push" fun ; "push" lhs ;) "pushv" rhs ;)),
|
||||
])
|
||||
.finish()])
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ use orchid_extension::tree::{GenMember, fun, prefix};
|
||||
use orchid_extension::{Expr, TAtom, ToExpr, exec};
|
||||
|
||||
use crate::macros::match_macros::MatcherAtom;
|
||||
use crate::macros::resolve::resolve;
|
||||
use crate::macros::utils::{build_macro, mactree, mactreev};
|
||||
use crate::{OrcOpt, Tpl};
|
||||
|
||||
@@ -26,19 +25,16 @@ pub async fn gen_option_macro_lib() -> Vec<GenMember> {
|
||||
),
|
||||
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
|
||||
.exec::<TAtom<MatcherAtom>>(resolve(mactree!(pattern::match_rule "push" sub;)).await)
|
||||
.await?;
|
||||
Ok(new_atom(MatcherAtom {
|
||||
keys: sub.keys().collect().await,
|
||||
matcher: call(sym!(std::option::is_some_body), sub).await.create().await,
|
||||
}))
|
||||
})
|
||||
async |mut cx, [sub]| {
|
||||
let sub: TAtom<MatcherAtom> =
|
||||
cx.exec(cx.recur(mactree!(pattern::match_rule "push" sub;))).await?;
|
||||
Ok(new_atom(MatcherAtom {
|
||||
keys: sub.keys().collect().await,
|
||||
matcher: call(sym!(std::option::is_some_body), sub).await.create().await,
|
||||
}))
|
||||
},
|
||||
])
|
||||
.rule(mactreev!(pattern::match_rule(std::option::none)), [async |[]: [_; _]| {
|
||||
.rule(mactreev!(pattern::match_rule(std::option::none)), [async |_cx, []| {
|
||||
new_atom(MatcherAtom {
|
||||
keys: vec![],
|
||||
matcher: sym!(std::option::is_none_body).to_expr().await,
|
||||
|
||||
@@ -1,41 +1,27 @@
|
||||
use orchid_base::sym;
|
||||
use orchid_extension::TAtom;
|
||||
use orchid_extension::ToExpr;
|
||||
use orchid_extension::exec;
|
||||
use orchid_extension::Expr;
|
||||
use orchid_extension::gen_expr::{call, new_atom};
|
||||
use orchid_extension::gen_expr::call;
|
||||
use orchid_extension::tree::{GenMember, prefix};
|
||||
use orchid_extension::{Expr, TAtom, ToExpr};
|
||||
|
||||
use crate::macros::resolve::resolve;
|
||||
use crate::macros::utils::{build_macro, mactree, mactreev};
|
||||
use crate::std::string::str_atom::IntStrAtom;
|
||||
use crate::{HomoTpl, MacTree, Tpl};
|
||||
|
||||
pub async fn gen_record_macro_lib() -> Vec<GenMember> {
|
||||
prefix("std::record", [build_macro(None, ["r", "_row"])
|
||||
.rule(mactreev!(std::record::r[ "...$" elements 0 ]), [async |[elements]: [_; _]| {
|
||||
exec(async move |mut h| {
|
||||
let tup = h
|
||||
.exec::<HomoTpl<TAtom<MacTree>>>(call(
|
||||
sym!(macros::resolve),
|
||||
new_atom(mactree!((macros::common::comma_list "push" elements ;))),
|
||||
))
|
||||
.await?;
|
||||
let mut record = sym!(std::record::empty).to_gen().await;
|
||||
for item_exprh in tup.0 {
|
||||
let Tpl((key, value)) = h
|
||||
.exec::<Tpl<(TAtom<IntStrAtom>, Expr)>>(
|
||||
resolve(mactree!(std::record::_row "push" item_exprh.own().await ;)).await,
|
||||
)
|
||||
.await?;
|
||||
record = call(sym!(std::record::set), (record, key, value)).await;
|
||||
}
|
||||
Ok(record)
|
||||
})
|
||||
.await
|
||||
.rule(mactreev!(std::record::r[ "...$" elements 0 ]), [async |mut cx, [elements]| {
|
||||
let tup: HomoTpl<TAtom<MacTree>> =
|
||||
cx.exec(cx.recur(mactree!((macros::common::comma_list "push" elements ;)))).await?;
|
||||
let mut record = sym!(std::record::empty).to_gen().await;
|
||||
for item_exprh in tup.0 {
|
||||
let Tpl((key, value)): Tpl<(TAtom<IntStrAtom>, Expr)> =
|
||||
cx.exec(cx.recur(mactree!(std::record::_row "push" item_exprh.own().await ;))).await?;
|
||||
record = call(sym!(std::record::set), (record, key, value)).await;
|
||||
}
|
||||
Ok(record)
|
||||
}])
|
||||
.rule(mactreev!(std::record::_row ( "$" name "...$" value 1 )), [async |[name, value]| {
|
||||
Ok(Tpl((resolve(name).await, resolve(value).await)))
|
||||
.rule(mactreev!(std::record::_row ( "$" name "...$" value 1 )), [async |cx, [name, value]| {
|
||||
Ok(Tpl((cx.recur(name), cx.recur(value))))
|
||||
}])
|
||||
.finish()])
|
||||
}
|
||||
|
||||
@@ -1,24 +1,20 @@
|
||||
use futures::{StreamExt, stream};
|
||||
use orchid_base::{OrcRes, sym};
|
||||
use orchid_extension::TAtom;
|
||||
use orchid_extension::ToExpr;
|
||||
use orchid_extension::exec;
|
||||
use orchid_extension::Expr;
|
||||
use orchid_extension::gen_expr::{GExpr, call, new_atom};
|
||||
use orchid_extension::tree::{GenMember, fun, prefix};
|
||||
use orchid_extension::{Expr, TAtom, ToExpr, exec};
|
||||
|
||||
use crate::macros::match_macros::MatcherAtom;
|
||||
use crate::macros::utils::{build_macro, mactree, mactreev};
|
||||
use crate::macros::utils::{RuleCtx, build_macro, mactree, mactreev};
|
||||
use crate::{HomoTpl, MacTree, OrcOpt};
|
||||
|
||||
pub async fn gen_tuple_macro_lib() -> Vec<GenMember> {
|
||||
prefix("std::tuple", [
|
||||
build_macro(None, ["t"])
|
||||
.rule(mactreev!(std::tuple::t [ "...$" elements 0 ]), [|[elements]: [_; _]| {
|
||||
exec(async move |mut h| {
|
||||
let tup = h
|
||||
.exec::<HomoTpl<TAtom<MacTree>>>(call(sym!(macros::resolve),
|
||||
new_atom(mactree!((macros::common::comma_list "push" elements ;))),
|
||||
.rule(mactreev!(std::tuple::t [ "...$" elements 0 ]), [async |mut cx, [elements]| {
|
||||
let tup: HomoTpl<TAtom<MacTree>> = cx
|
||||
.exec(cx.recur(
|
||||
mactree!((macros::common::comma_list "push" elements ;)),
|
||||
))
|
||||
.await?;
|
||||
let val = stream::iter(&tup.0[..])
|
||||
@@ -33,65 +29,52 @@ pub async fn gen_tuple_macro_lib() -> Vec<GenMember> {
|
||||
})
|
||||
.await;
|
||||
Ok(val)
|
||||
})
|
||||
}])
|
||||
.rule(
|
||||
mactreev!(pattern::match_rule(std::tuple::t[ "...$" elements 0 macros::common::, macros::common::..])),
|
||||
[async |[elements]: [_; _]| parse_tpl(elements, Some(mactree!(macros::common::_))).await],
|
||||
[async |cx, [elements]| parse_tpl(cx, elements, Some(mactree!(macros::common::_))).await],
|
||||
)
|
||||
.rule(
|
||||
mactreev!(pattern::match_rule(
|
||||
std::tuple::t[ "...$" elements 1 macros::common::, macros::common::.. "...$" tail 0]
|
||||
)),
|
||||
[async |[elements, tail]: [_; _]| parse_tpl(elements, Some(tail)).await],
|
||||
[async |cx, [elements, tail]| parse_tpl(cx, elements, Some(tail)).await],
|
||||
)
|
||||
.rule(mactreev!(pattern::match_rule(std::tuple::t[ "...$" elements 0])), [
|
||||
|[elements]: [_; _]| parse_tpl(elements, None),
|
||||
async |cx, [elements]| parse_tpl(cx, elements, None).await,
|
||||
])
|
||||
.finish(),
|
||||
fun(false, "matcher_body", tuple_matcher_body),
|
||||
])
|
||||
}
|
||||
|
||||
fn parse_tpl(elements: MacTree, tail_matcher: Option<MacTree>) -> impl Future<Output = GExpr> {
|
||||
exec(async move |mut h| -> OrcRes<GExpr> {
|
||||
let tup = h
|
||||
.exec::<HomoTpl<TAtom<MacTree>>>(call(sym!(macros::resolve), new_atom(
|
||||
mactree!((macros::common::comma_list "push" elements ;)),
|
||||
)))
|
||||
.await?;
|
||||
let mut subs = Vec::with_capacity(tup.0.len());
|
||||
for mac_a in &tup.0[..] {
|
||||
let sub = h
|
||||
.exec::<TAtom<MatcherAtom>>(call(sym!(macros::resolve), new_atom(
|
||||
mactree!(pattern::match_rule ("push" mac_a.own().await ;)),
|
||||
)))
|
||||
.await?;
|
||||
subs.push(sub);
|
||||
}
|
||||
let tail_matcher = match tail_matcher {
|
||||
Some(mac) => Some(
|
||||
h.exec::<TAtom<MatcherAtom>>(call(sym!(macros::resolve), new_atom(
|
||||
mactree!(pattern::match_rule "push" mac ;),
|
||||
)))
|
||||
.await?,
|
||||
),
|
||||
None => None,
|
||||
};
|
||||
Ok(new_atom(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!(std::tuple::matcher_body), (
|
||||
HomoTpl(subs),
|
||||
OrcOpt(tail_matcher),
|
||||
))
|
||||
async fn parse_tpl(
|
||||
mut cx: RuleCtx<'_>,
|
||||
elements: MacTree,
|
||||
tail_matcher: Option<MacTree>,
|
||||
) -> OrcRes<GExpr> {
|
||||
let tup: HomoTpl<TAtom<MacTree>> =
|
||||
cx.exec(cx.recur(mactree!((macros::common::comma_list "push" elements ;)))).await?;
|
||||
let mut subs = Vec::with_capacity(tup.0.len());
|
||||
for mac_a in &tup.0[..] {
|
||||
let sub: TAtom<MatcherAtom> =
|
||||
cx.exec(cx.recur(mactree!(pattern::match_rule ("push" mac_a.own().await ;)))).await?;
|
||||
subs.push(sub);
|
||||
}
|
||||
let tail_matcher: Option<TAtom<MatcherAtom>> = match tail_matcher {
|
||||
Some(mac) => Some(cx.exec(cx.recur(mactree!(pattern::match_rule "push" mac ;))).await?),
|
||||
None => None,
|
||||
};
|
||||
Ok(new_atom(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!(std::tuple::matcher_body), (HomoTpl(subs), OrcOpt(tail_matcher)))
|
||||
.to_expr()
|
||||
.await,
|
||||
}))
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
fn tuple_matcher_body(
|
||||
|
||||
@@ -6,14 +6,16 @@ use futures::StreamExt;
|
||||
use futures::future::LocalBoxFuture;
|
||||
use itertools::{Itertools, chain};
|
||||
use never::Never;
|
||||
use orchid_base::{NameLike, Sym, VPath, is};
|
||||
use orchid_extension::ToExpr;
|
||||
use orchid_base::{NameLike, OrcRes, Sym, VPath, is};
|
||||
use orchid_extension::gen_expr::{GExpr, new_atom};
|
||||
use orchid_extension::tree::{GenMember, MemKind, cnst, lazy};
|
||||
use orchid_extension::{Atomic, OwnedAtom, OwnedVariant, TAtom};
|
||||
use orchid_extension::{
|
||||
Atomic, ExecHandle, OwnedAtom, OwnedVariant, TAtom, ToExpr, ToExprFuture, TryFromExpr, exec,
|
||||
};
|
||||
|
||||
use crate::macros::macro_value::{Macro, MacroData, Rule};
|
||||
use crate::macros::mactree::MacTreeSeq;
|
||||
use crate::macros::resolve::{ArgStack, resolve};
|
||||
use crate::macros::rule::matcher::Matcher;
|
||||
use crate::{MacTok, MacTree};
|
||||
|
||||
@@ -22,8 +24,9 @@ pub type Args = Vec<MacTree>;
|
||||
#[derive(Clone)]
|
||||
pub struct MacroBodyArgCollector {
|
||||
argc: usize,
|
||||
arg_stack: Option<ArgStack>,
|
||||
args: Args,
|
||||
cb: Rc<dyn Fn(Args) -> LocalBoxFuture<'static, GExpr>>,
|
||||
cb: Rc<dyn for<'a> Fn(RuleCtx<'a>, Args) -> LocalBoxFuture<'a, GExpr>>,
|
||||
}
|
||||
impl Atomic for MacroBodyArgCollector {
|
||||
type Data = ();
|
||||
@@ -39,12 +42,23 @@ impl OwnedAtom for MacroBodyArgCollector {
|
||||
self.clone().call(arg).await
|
||||
}
|
||||
async fn call(mut self, arg: orchid_extension::Expr) -> GExpr {
|
||||
let atom = (TAtom::<MacTree>::downcast(arg.handle()).await).unwrap_or_else(|_| {
|
||||
panic!("This is an intermediary value, the argument types are known in advance")
|
||||
});
|
||||
self.args.push(atom.own().await);
|
||||
if self.arg_stack.is_none() {
|
||||
let atom = (TAtom::<ArgStack>::downcast(arg.handle()).await).unwrap_or_else(|_| {
|
||||
panic!("The argstack is an intermediary value, the argument types are known in advance")
|
||||
});
|
||||
self.arg_stack = Some(atom.own().await);
|
||||
} else {
|
||||
let atom = (TAtom::<MacTree>::downcast(arg.handle()).await).unwrap_or_else(|_| {
|
||||
panic!("This is an intermediary value, the argument types are known in advance")
|
||||
});
|
||||
self.args.push(atom.own().await);
|
||||
}
|
||||
if self.argc == self.args.len() {
|
||||
(self.cb)(self.args).await.to_gen().await
|
||||
exec(async move |handle| {
|
||||
let rule_ctx = RuleCtx { arg_stk: self.arg_stack.unwrap(), handle };
|
||||
(self.cb)(rule_ctx, self.args).await
|
||||
})
|
||||
.await
|
||||
} else {
|
||||
new_atom(self)
|
||||
}
|
||||
@@ -53,6 +67,21 @@ impl OwnedAtom for MacroBodyArgCollector {
|
||||
|
||||
fn body_name(name: &str, counter: usize) -> String { format!("({name})::{counter}") }
|
||||
|
||||
pub struct RuleCtx<'a> {
|
||||
arg_stk: ArgStack,
|
||||
handle: ExecHandle<'a>,
|
||||
}
|
||||
impl RuleCtx<'_> {
|
||||
pub fn recur(&self, mt: MacTree) -> impl ToExpr + use<> {
|
||||
eprintln!("Recursion in macro");
|
||||
let arg_stk = self.arg_stk.clone();
|
||||
ToExprFuture(resolve(mt, arg_stk))
|
||||
}
|
||||
pub async fn exec<T: TryFromExpr>(&mut self, val: impl ToExpr) -> OrcRes<T> {
|
||||
self.handle.exec(val).await
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn build_macro(
|
||||
prio: Option<u64>,
|
||||
own_kws: impl IntoIterator<Item = &'static str>,
|
||||
@@ -74,31 +103,25 @@ impl MacroBuilder {
|
||||
pub(crate) fn rule<const N: usize, R: ToExpr>(
|
||||
mut self,
|
||||
pat: MacTreeSeq,
|
||||
body: [impl AsyncFn([MacTree; N]) -> R + 'static; 1],
|
||||
body: [impl AsyncFn(RuleCtx, [MacTree; N]) -> R + 'static; 1],
|
||||
) -> Self {
|
||||
let [body] = body;
|
||||
let body = Rc::new(body);
|
||||
let name = &body_name(self.own_kws[0], self.body_consts.len());
|
||||
self.body_consts.extend(match N {
|
||||
0 => lazy(true, name, async move |_| {
|
||||
let argv = [].into_iter().collect_array().expect("N is 0");
|
||||
MemKind::Const(body(argv).await.to_gen().await)
|
||||
}),
|
||||
1.. => cnst(
|
||||
true,
|
||||
name,
|
||||
new_atom(MacroBodyArgCollector {
|
||||
argc: N,
|
||||
args: Vec::new(),
|
||||
cb: Rc::new(move |argv| {
|
||||
let arr =
|
||||
argv.into_iter().collect_array::<N>().expect("argc should enforce the length");
|
||||
let body = body.clone();
|
||||
Box::pin(async move { body(arr).await.to_gen().await })
|
||||
}),
|
||||
self.body_consts.extend(cnst(
|
||||
true,
|
||||
name,
|
||||
new_atom(MacroBodyArgCollector {
|
||||
argc: N,
|
||||
arg_stack: None,
|
||||
args: Vec::new(),
|
||||
cb: Rc::new(move |rec, argv| {
|
||||
let arr = argv.into_iter().collect_array::<N>().expect("argc should enforce the length");
|
||||
let body = body.clone();
|
||||
Box::pin(async move { body(rec, arr).await.to_gen().await })
|
||||
}),
|
||||
),
|
||||
});
|
||||
}),
|
||||
));
|
||||
self.patterns.push(pat);
|
||||
self
|
||||
}
|
||||
@@ -282,4 +305,6 @@ macro_rules! mactreev {
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) use {mactree, mactreev, mactreev_impl};
|
||||
pub(crate) use mactree;
|
||||
pub(crate) use mactreev;
|
||||
pub(crate) use mactreev_impl;
|
||||
|
||||
@@ -4,8 +4,7 @@ use std::rc::Rc;
|
||||
|
||||
use futures::AsyncWrite;
|
||||
use orchid_api_traits::Encode;
|
||||
use orchid_extension::Atomic;
|
||||
use orchid_extension::{DeserializeCtx, OwnedAtom, OwnedVariant};
|
||||
use orchid_extension::{Atomic, DeserializeCtx, OwnedAtom, OwnedVariant};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct BlobAtom(pub(crate) Rc<Vec<u8>>);
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
use orchid_api_derive::Coding;
|
||||
use orchid_base::{FmtUnit, OrcRes, sym};
|
||||
use orchid_extension::{ToExpr, TryFromExpr};
|
||||
use orchid_extension::Expr;
|
||||
use orchid_extension::gen_expr::GExpr;
|
||||
use orchid_extension::tree::{GenMember, cnst, comments, fun, prefix};
|
||||
use orchid_extension::{Atomic, TAtom, ThinAtom, ThinVariant};
|
||||
use orchid_extension::{Atomic, Expr, TAtom, ThinAtom, ThinVariant, ToExpr, TryFromExpr};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Coding)]
|
||||
pub struct Bool(pub bool);
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
use orchid_base::{name_char, name_start};
|
||||
use orchid_base::{OrcRes, is};
|
||||
use orchid_base::{OrcRes, is, name_char, name_start};
|
||||
use orchid_extension::gen_expr::new_atom;
|
||||
use orchid_extension::{LexContext, LexedData, Lexer, err_not_applicable};
|
||||
use orchid_extension::tree::GenTok;
|
||||
use orchid_extension::{LexContext, LexedData, Lexer, err_not_applicable};
|
||||
|
||||
use crate::std::string::str_atom::IntStrAtom;
|
||||
|
||||
|
||||
@@ -4,11 +4,12 @@ use std::pin::Pin;
|
||||
use futures::AsyncWrite;
|
||||
use orchid_api_traits::Encode;
|
||||
use orchid_base::{is, mk_errv, sym};
|
||||
use orchid_extension::{ToExpr, TryFromExpr};
|
||||
use orchid_extension::{Expr, ExprHandle};
|
||||
use orchid_extension::gen_expr::{call, new_atom};
|
||||
use orchid_extension::tree::{GenMember, cnst, fun, prefix};
|
||||
use orchid_extension::{Atomic, DeserializeCtx, ForeignAtom, OwnedAtom, OwnedVariant, TAtom};
|
||||
use orchid_extension::{
|
||||
Atomic, DeserializeCtx, Expr, ExprHandle, ForeignAtom, OwnedAtom, OwnedVariant, TAtom, ToExpr,
|
||||
TryFromExpr,
|
||||
};
|
||||
|
||||
use crate::{OrcString, api};
|
||||
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
use itertools::{Itertools, chain};
|
||||
use orchid_base::Sym;
|
||||
use orchid_base::{
|
||||
Import, Parsed, Snippet, expect_tok, line_items, parse_multiname, token_errv,
|
||||
};
|
||||
use orchid_base::{Paren, Token};
|
||||
use orchid_base::{IStr, OrcRes, is, mk_errv};
|
||||
use orchid_extension::{
|
||||
PTokTree, ParsCtx, ParsedLine, ParsedLineKind, p_tree2gen, p_v2gen,
|
||||
IStr, Import, OrcRes, Paren, Parsed, Snippet, Sym, Token, expect_tok, is, line_items, mk_errv,
|
||||
parse_multiname, token_errv,
|
||||
};
|
||||
use orchid_extension::{PTokTree, ParsCtx, ParsedLine, ParsedLineKind, p_tree2gen, p_v2gen};
|
||||
|
||||
pub async fn parse_impls(
|
||||
_: &ParsCtx<'_>,
|
||||
|
||||
@@ -2,9 +2,8 @@ use std::rc::Rc;
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use orchid_base::{Comment, OrcRes, Parsed, Token, expect_end, is, mk_errv, sym, try_pop_no_fluff};
|
||||
use orchid_extension::ToExpr;
|
||||
use orchid_extension::gen_expr::{call, new_atom};
|
||||
use orchid_extension::{PSnippet, ParsCtx, ParsedLine, Parser};
|
||||
use orchid_extension::{PSnippet, ParsCtx, ParsedLine, Parser, ToExpr};
|
||||
|
||||
use crate::std::protocol::parse_impls::parse_impls;
|
||||
use crate::std::protocol::types::Tag;
|
||||
|
||||
@@ -2,9 +2,8 @@ use std::rc::Rc;
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use orchid_base::{Comment, OrcRes, Parsed, Token, expect_end, is, mk_errv, sym, try_pop_no_fluff};
|
||||
use orchid_extension::ToExpr;
|
||||
use orchid_extension::gen_expr::{call, new_atom};
|
||||
use orchid_extension::{PSnippet, ParsCtx, ParsedLine, Parser};
|
||||
use orchid_extension::{PSnippet, ParsCtx, ParsedLine, Parser, ToExpr};
|
||||
|
||||
use crate::std::protocol::parse_impls::parse_impls;
|
||||
use crate::std::protocol::types::Tag;
|
||||
|
||||
@@ -9,10 +9,8 @@ use hashbrown::HashMap;
|
||||
use orchid_api_derive::Coding;
|
||||
use orchid_api_traits::{Encode, Request};
|
||||
use orchid_base::{IStr, Receipt, ReqHandle, ReqHandleExt, Sym, es, sym};
|
||||
use orchid_extension::ToExpr;
|
||||
use orchid_extension::Expr;
|
||||
use orchid_extension::{
|
||||
Atomic, DeserializeCtx, MethodSetBuilder, OwnedAtom, OwnedVariant, Supports,
|
||||
Atomic, DeserializeCtx, Expr, MethodSetBuilder, OwnedAtom, OwnedVariant, Supports, ToExpr,
|
||||
};
|
||||
|
||||
use crate::api;
|
||||
|
||||
@@ -3,10 +3,9 @@ use std::rc::Rc;
|
||||
use hashbrown::HashMap;
|
||||
use itertools::Itertools;
|
||||
use orchid_base::{is, mk_errv};
|
||||
use orchid_extension::TAtom;
|
||||
use orchid_extension::Expr;
|
||||
use orchid_extension::gen_expr::{arg, new_atom};
|
||||
use orchid_extension::gen_expr::new_atom;
|
||||
use orchid_extension::tree::{GenMember, cnst, fun, prefix};
|
||||
use orchid_extension::{Expr, TAtom, get_arg_posv};
|
||||
|
||||
use crate::std::record::record_atom::RecordAtom;
|
||||
use crate::std::string::str_atom::IntStrAtom;
|
||||
@@ -26,7 +25,7 @@ pub fn gen_record_lib() -> Vec<GenMember> {
|
||||
None => Err(mk_errv(
|
||||
is("Key not found in record").await,
|
||||
format!("{} is not in this record, valid keys are {}", key.0, record.0.keys().join(", ")),
|
||||
[arg(0).pos.clone(), arg(1).pos.clone()],
|
||||
get_arg_posv([0, 1]).await,
|
||||
)),
|
||||
}
|
||||
}),
|
||||
|
||||
@@ -4,10 +4,10 @@ use futures::future::join_all;
|
||||
use orchid_api_derive::{Coding, Hierarchy};
|
||||
use orchid_base::{Receipt, ReqHandle, ReqHandleExt, Sym, es, sym};
|
||||
use orchid_extension::gen_expr::new_atom;
|
||||
use orchid_extension::ParserObj;
|
||||
use orchid_extension::tree::{GenMember, merge_trivial};
|
||||
use orchid_extension::{
|
||||
AtomOps, AtomicFeatures, Expr, LexerObj, ReqForSystem, System, SystemCard, SystemCtor, ToExpr,
|
||||
AtomOps, AtomicFeatures, Expr, LexerObj, ParserObj, ReqForSystem, System, SystemCard, SystemCtor,
|
||||
ToExpr,
|
||||
};
|
||||
|
||||
use super::number::num_lib::gen_num_lib;
|
||||
|
||||
@@ -4,7 +4,7 @@ use std::rc::Rc;
|
||||
|
||||
use never::Never;
|
||||
use orchid_base::{ReqHandleExt, fmt, is, mk_errv};
|
||||
use orchid_extension::gen_expr::{bot, call, new_atom};
|
||||
use orchid_extension::gen_expr::{bot, call, new_atom, serialize};
|
||||
use orchid_extension::std_reqs::{ReadLimit, ReadReq, RunCommand};
|
||||
use orchid_extension::{Atomic, Expr, ForeignAtom, OwnedAtom, OwnedVariant, Supports, ToExpr};
|
||||
|
||||
@@ -50,6 +50,6 @@ impl Supports<RunCommand> for ReadStreamCmd {
|
||||
),
|
||||
Some(Ok(v)) => Ok(call(self.succ.clone(), new_atom(BlobAtom(Rc::new(v)))).await),
|
||||
};
|
||||
hand.reply(&req, &Some(ret.to_gen().await.serialize().await)).await
|
||||
hand.reply(&req, &Some(serialize(ret.to_gen().await).await)).await
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,10 +10,9 @@ use orchid_api_traits::{Encode, Request};
|
||||
use orchid_base::{
|
||||
FmtCtx, FmtUnit, IStr, OrcRes, Receipt, ReqHandle, ReqHandleExt, Sym, es, is, mk_errv, sym,
|
||||
};
|
||||
use orchid_extension::{ToExpr, TryFromExpr};
|
||||
use orchid_extension::Expr;
|
||||
use orchid_extension::{
|
||||
AtomMethod, Atomic, DeserializeCtx, MethodSetBuilder, OwnedAtom, OwnedVariant, Supports, TAtom,
|
||||
AtomMethod, Atomic, DeserializeCtx, Expr, MethodSetBuilder, OwnedAtom, OwnedVariant, Supports,
|
||||
TAtom, ToExpr, TryFromExpr,
|
||||
};
|
||||
|
||||
use crate::std::protocol::types::{GetImpl, ProtocolMethod};
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
use itertools::Itertools;
|
||||
use orchid_base::{OrcErr, OrcErrv, OrcRes, Paren, SrcRange, Sym, is, mk_errv, sym, wrap_tokv};
|
||||
use orchid_extension::ToExpr;
|
||||
use orchid_extension::gen_expr::new_atom;
|
||||
use orchid_extension::{LexContext, Lexer, err_not_applicable};
|
||||
use orchid_extension::p_tree2gen;
|
||||
use orchid_extension::tree::{GenTok, GenTokTree, ref_tok, x_tok};
|
||||
use orchid_extension::{LexContext, Lexer, ToExpr, err_not_applicable, p_tree2gen};
|
||||
|
||||
use super::str_atom::IntStrAtom;
|
||||
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
use std::borrow::Cow;
|
||||
use std::io;
|
||||
use std::time::Instant;
|
||||
|
||||
use chrono::TimeDelta;
|
||||
use chrono::{DateTime, TimeDelta, Utc};
|
||||
use never::Never;
|
||||
use orchid_api::ExprTicket;
|
||||
use orchid_api_derive::{Coding, Hierarchy};
|
||||
use orchid_api_traits::Request;
|
||||
use orchid_base::{Numeric, OrcRes, Receipt, ReqHandle, ReqHandleExt};
|
||||
use orchid_extension::gen_expr::{GExpr, call, new_atom};
|
||||
use orchid_extension::std_reqs::{AsDuration, RunCommand};
|
||||
use orchid_extension::gen_expr::{GExpr, call, new_atom, serialize};
|
||||
use orchid_extension::std_reqs::{AsInstant, RunCommand};
|
||||
use orchid_extension::tree::{GenMember, fun, prefix};
|
||||
use orchid_extension::{
|
||||
Atomic, Expr, MethodSetBuilder, OwnedAtom, OwnedVariant, Supports, TAtom, ThinAtom, ThinVariant,
|
||||
@@ -44,18 +43,9 @@ impl TryFromExpr for OrcDT {
|
||||
Ok(TAtom::<OrcDT>::try_from_expr(expr).await?.value)
|
||||
}
|
||||
}
|
||||
impl Supports<AsDuration> for OrcDT {
|
||||
async fn handle<'a>(
|
||||
&self,
|
||||
hand: Box<dyn ReqHandle<'a> + '_>,
|
||||
req: AsDuration,
|
||||
) -> std::io::Result<Receipt<'a>> {
|
||||
hand.reply(&req, &self.0.to_std().unwrap()).await
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct InstantAtom(Instant);
|
||||
pub struct InstantAtom(DateTime<Utc>);
|
||||
impl Atomic for InstantAtom {
|
||||
type Variant = OwnedVariant;
|
||||
type Data = ();
|
||||
@@ -64,6 +54,15 @@ impl OwnedAtom for InstantAtom {
|
||||
type Refs = Never;
|
||||
async fn val(&self) -> Cow<'_, Self::Data> { Cow::Owned(()) }
|
||||
}
|
||||
impl Supports<AsInstant> for InstantAtom {
|
||||
async fn handle<'a>(
|
||||
&self,
|
||||
hand: Box<dyn ReqHandle<'a> + '_>,
|
||||
req: AsInstant,
|
||||
) -> std::io::Result<Receipt<'a>> {
|
||||
hand.reply(&req, &self.0).await
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Now(Expr);
|
||||
@@ -82,7 +81,7 @@ impl Supports<RunCommand> for Now {
|
||||
hand: Box<dyn ReqHandle<'a> + '_>,
|
||||
req: RunCommand,
|
||||
) -> io::Result<Receipt<'a>> {
|
||||
let cont = call(self.0.clone(), new_atom(InstantAtom(Instant::now()))).await.serialize().await;
|
||||
let cont = serialize(call(self.0.clone(), new_atom(InstantAtom(Utc::now()))).await).await;
|
||||
hand.reply(&req, &Some(cont)).await
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user