tytanic_filter/ast/
func.rs

1use 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/// A function call node.
19#[derive(Debug, Clone, PartialEq, Eq, Hash)]
20pub struct Func {
21    /// The identifier of this function.
22    pub id: Id,
23
24    /// The arguments of this function.
25    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}