tytanic_filter/ast/
func.rs

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