mist_parser/parser/items/
function.rs1use crate::{
2 Rule,
3 ast::*,
4 ast_ensure, ast_expr,
5 error::{AstError, AstResult, IntoErr},
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 => {
14 let mut inner = pair.into_inner();
15 let visibility = Visibility::try_from(&mut inner);
16 let name = Identifier::try_from(inner.next().unwrap());
17
18 let generics = consume_rule(&mut inner, Rule::generics_decl)
19 .map(GenericsDecl::try_from)
20 .transpose()
21 .map(|v| v.unwrap_or_default());
22
23 let self_param = consume_rule(&mut inner, Rule::self_param).map(|param| {
24 let mut param_inner = param.into_inner();
25 let is_ref = listen_rule(&mut param_inner, Rule::deref_px);
26 let lifetime = consume_rule(&mut param_inner, Rule::lifetime);
27 let mutable = listen_rule(&mut param_inner, Rule::mutable);
28 let name = Pattern::Path(mutable && !is_ref, Path(vec![Identifier(String::from("self"))]));
29 let self_ty = TypeExpr::Path(Path(vec![Identifier(String::from("Self"))]), None);
30
31 VarDecl {
32 name: name.clone(),
33 type_: Some(if is_ref {
34 TypeExpr::Ref {
35 lifetime:
36 lifetime.map(|v| Identifier::try_from(v.into_inner().next().unwrap()))
37 .transpose()
38 .expect("Failed to get lifetime identifier"),
39 mutable,
40 ty: Box::new(self_ty)
41 }
42 } else {
43 self_ty
44 }),
45 }
46 });
47
48 let params = consume_rule(&mut inner, Rule::param_list)
49 .map({
50 let self_param = self_param.clone();
51 |params_pair| -> AstResult<'a, ParamList> {
52 let mut params = ParamList::try_from(params_pair)?;
53 if let Some(x) = self_param {
54 params.0.insert(0, x);
55 }
56 Ok(params)
57 }
58 })
59 .unwrap_or_else(|| Ok(ParamList(self_param.into_iter().collect())));
60
61 let return_type = consume_rule(&mut inner, Rule::type_expr)
62 .map(TypeExpr::try_from)
63 .transpose();
64
65 let body = inner.next().map(Block::try_from).transpose();
66
67 ast_expr!(Self {
68 visibility: visibility,
69 return_type: return_type,
70 name: name,
71 generics: generics,
72 params: params,
73 body: body,
74 })
75 })
76 }
77}