mist_parser/parser/items/
function.rs1use 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}