tytanic_filter/ast/
func.rs1use ecow::EcoVec;
2use ecow::eco_vec;
3use pest::iterators::Pair;
4use pest::pratt_parser::PrattParser;
5
6use super::Error;
7use super::Expr;
8use super::Id;
9use super::PairExt;
10use super::PairsExt;
11use super::Rule;
12use crate::eval;
13use crate::eval::Context;
14use crate::eval::Eval;
15use crate::eval::Test;
16use crate::eval::Value;
17
18#[derive(Debug, Clone, PartialEq, Eq, Hash)]
20pub struct Func {
21 pub id: Id,
23
24 pub args: EcoVec<Expr>,
26}
27
28impl<T: Test> Eval<T> for Func {
29 fn eval(&self, ctx: &Context<T>) -> Result<Value<T>, eval::Error> {
30 let func: eval::Func<T> = ctx.resolve(&self.id)?.expect_type()?;
31 let args = self
32 .args
33 .iter()
34 .map(|e| e.eval(ctx))
35 .collect::<Result<Vec<_>, _>>()?;
36
37 func.call(ctx, &args)
38 }
39}
40
41impl Func {
42 pub(super) fn parse(pair: Pair<'_, Rule>, pratt: &PrattParser<Rule>) -> Result<Self, Error> {
43 pair.expect_rules(&[Rule::func])?;
44 let mut pairs = pair.into_inner();
45
46 let id = pairs.expect_pair(&[Rule::id])?;
47 let id = Id::parse(id)?;
48
49 let args = pairs.expect_pair(&[Rule::func_args])?;
50 let mut pairs = args.into_inner();
51
52 let _ = pairs.expect_pair(&[Rule::func_args_delim_open])?;
53 let args_or_close =
54 pairs.expect_pair(&[Rule::func_args_inner, Rule::func_args_delim_close])?;
55 let args = if args_or_close.as_rule() == Rule::func_args_inner {
56 let _ = pairs.expect_pair(&[Rule::func_args_delim_close])?;
57
58 let mut pairs = args_or_close.into_inner();
59
60 let mut args = eco_vec![];
61 loop {
62 let Some(arg) = pairs.try_expect_pair(&[Rule::expr])? else {
63 break;
64 };
65
66 args.push(Expr::parse(arg, pratt)?);
67
68 let Some(_) = pairs.try_expect_pair(&[Rule::func_args_sep])? else {
69 break;
70 };
71 }
72
73 args
74 } else {
75 eco_vec![]
76 };
77
78 pairs.expect_end()?;
79
80 Ok(Self { id, args })
81 }
82}