Skip to main content

mist_parser/parser/items/
function.rs

1use crate::{
2    Rule,
3    ast::*,
4    ast_ensure, ast_expr,
5    error::{AstError, AstResult, IntoErr, collect_recovered},
6    parser::{consume_rule, listen_rule},
7};
8
9impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for FunctionDecl {
10    type Error = AstError<'a, Self>;
11
12    fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
13        ast_ensure!(pair, Rule::function_decl, Rule::method, Rule::method_no_body => {
14        let mut inner = pair.into_inner();
15            let visibility = Visibility::try_from(&mut inner);
16            let return_type = TypeExpr::try_from(inner.next().unwrap());
17            let name = Identifier::try_from(inner.next().unwrap());
18
19            let generics = consume_rule(&mut inner, Rule::generics_decl)
20                .map(GenericsDecl::try_from)
21                .transpose()
22                .map(|v| v.unwrap_or_default());
23
24            let self_param = consume_rule(&mut inner, Rule::self_param).map(|param| {
25                let mut param_inner = param.into_inner();
26                let name = Pattern::Id(Identifier(String::from("self")));
27
28                let mutable = listen_rule(&mut param_inner, Rule::mutable);
29
30                let is_ref = listen_rule(&mut param_inner, Rule::deref_px);
31
32                VarDecl {
33                    mutable: mutable && !is_ref,
34                    name: name.clone(),
35                    type_: Some(TypeExpr(
36                        TypeExprKind::Path(Path(vec![Identifier("Self".to_string())])),
37                        if is_ref {
38                            vec![if mutable {
39                                TypePostfix::RefMut
40                            } else {
41                                TypePostfix::Ref
42                            }]
43                        } else {
44                            Vec::new()
45                        },
46                    )),
47                }
48            });
49
50            let params = consume_rule(&mut inner, Rule::param_list)
51                .map({
52                    let self_param = self_param.clone();
53                    |params_pair| -> AstResult<'a, ParamList> {
54                        let mut params = ParamList::try_from(params_pair)?;
55                        if let Some(x) = self_param {
56                            params.0.insert(0, x);
57                        }
58                        Ok(params)
59                    }
60                })
61                .unwrap_or_else(|| Ok(ParamList(self_param.into_iter().collect())));
62
63            let body = inner.next().map(Block::try_from).transpose();
64
65            ast_expr!(Self {
66                visibility: visibility,
67                return_type: return_type,
68                name: name,
69                generics: generics,
70                params: params,
71                body: body,
72            })
73        })
74    }
75}
76
77impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for ParamList {
78    type Error = AstError<'a, Self>;
79
80    fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
81        Ok(ParamList(collect_recovered(pair.into_inner()).get()?))
82    }
83}