microcad_lang/parse/
call.rs

1// Copyright © 2025 The µcad authors <info@ucad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4use crate::{ord_map::*, parse::*, parser::*, syntax::*};
5
6impl Parse for Call {
7    fn parse(pair: Pair) -> ParseResult<Self> {
8        Parser::ensure_rule(&pair, Rule::call);
9        let mut inner = pair.inner();
10        let first = inner.next().expect("Expected qualified name");
11
12        Ok(Call {
13            name: QualifiedName::parse(first)?,
14            argument_list: crate::find_rule!(pair, argument_list)?,
15            src_ref: pair.clone().into(),
16        })
17    }
18}
19
20impl Parse for ArgumentList {
21    fn parse(pair: Pair) -> ParseResult<Self> {
22        Parser::ensure_rule(&pair, Rule::argument_list);
23        let mut argument_list = ArgumentList(Refer::new(OrdMap::default(), pair.clone().into()));
24
25        match pair.as_rule() {
26            Rule::argument_list => {
27                for pair in pair.inner() {
28                    match pair.as_rule() {
29                        Rule::named_argument | Rule::expression => {
30                            argument_list
31                                .try_push(Argument::parse(pair)?)
32                                .map_err(ParseError::DuplicateArgument)?;
33                        }
34                        Rule::COMMENT => {}
35                        rule => unreachable!("Expected argument, found {rule:?}"),
36                    }
37                }
38
39                Ok(argument_list)
40            }
41            rule => {
42                unreachable!("ArgumentList::parse expected argument list, found {rule:?}")
43            }
44        }
45    }
46}
47
48impl Parse for Argument {
49    fn parse(pair: Pair) -> ParseResult<Self> {
50        match pair.clone().as_rule() {
51            Rule::named_argument => {
52                let mut inner = pair.inner();
53                let first = inner.next().expect(INTERNAL_PARSE_ERROR);
54                let second = inner.next().expect(INTERNAL_PARSE_ERROR);
55
56                Ok(Argument {
57                    id: Some(Identifier::parse(first)?),
58                    expression: Expression::parse(second)?,
59                    src_ref: pair.src_ref(),
60                })
61            }
62            Rule::expression => Ok(Argument {
63                id: None,
64                expression: Expression::parse(pair.clone())?,
65                src_ref: pair.into(),
66            }),
67            rule => unreachable!("Argument::parse expected argument, found {rule:?}"),
68        }
69    }
70}
71
72impl Parse for MethodCall {
73    fn parse(pair: Pair) -> ParseResult<Self> {
74        Ok(MethodCall {
75            name: pair.find(Rule::qualified_name).expect(INTERNAL_PARSE_ERROR),
76            argument_list: pair.find(Rule::argument_list).unwrap_or_default(),
77            src_ref: pair.clone().into(),
78        })
79    }
80}
81
82#[test]
83fn call() {
84    use crate::{parser::*, syntax::*};
85    use pest::Parser as _;
86
87    let pair = Pair::new(
88        Parser::parse(Rule::call, "foo(1, 2, bar = 3, baz = 4)")
89            .expect("test error")
90            .next()
91            .expect("test error"),
92        0,
93    );
94
95    let call = Call::parse(pair).expect("test error");
96
97    assert_eq!(call.name, "foo".into());
98    assert_eq!(call.argument_list.len(), 4);
99
100    // Count named arguments
101    let named = call
102        .argument_list
103        .iter()
104        .filter(|arg| arg.id.is_some())
105        .count();
106    assert_eq!(named, 2);
107}