tytanic_filter/ast/
func.rs1use 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#[derive(Debug, Clone, PartialEq, Eq, Hash)]
10pub struct Func {
11 pub id: Id,
13
14 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}