move_syn/functions/
signature.rs

1use std::collections::HashMap;
2
3use unsynn::*;
4
5use crate::{Generics, HasGenerics, ItemKind, MaybeRefType, Typed, kw, mutate_delimited_vec};
6
7unsynn! {
8    pub(super) struct Arguments(ParenthesisGroupContaining<CommaDelimitedVec<FunctionArg>>);
9
10    /// E.g., `name: T`, `mut name: T`, `name: &T`, `name: &mut T`.
11    pub struct FunctionArg {
12        mut_: Option<kw::Mut>,
13        ident: Ident,
14        colon: Colon,
15        type_: MaybeRefType,
16    }
17
18    /// `: T`, `: &T`, `: &mut T`, `: (...)`
19    pub(super) struct Returns {
20        colon: Colon,
21        type_: ReturnType,
22    }
23
24    pub(super) enum ReturnType {
25        One(MaybeRefType),
26        Many(ParenthesisGroupContaining<CommaDelimitedVec<MaybeRefType>>),
27    }
28}
29
30impl crate::Module {
31    /// Resolve all function signature types to their fully-qualified paths.
32    pub fn fully_qualify_fun_signature_types(&mut self) -> &mut Self {
33        // Collect all imported types and their paths
34        let imports: HashMap<_, _> = self
35            .items()
36            .filter_map(|item| match &item.kind {
37                ItemKind::Import(import) => Some(import),
38                _ => None,
39            })
40            .flat_map(|import| import.flatten())
41            .collect();
42
43        // Resolve datatype fields' types
44        for item in &mut self.contents.content {
45            match &mut item.kind {
46                ItemKind::Function(fun) => {
47                    let generics = &fun.type_param_idents();
48                    fun.map_types(|ty| ty.resolve(&imports, generics));
49                }
50                ItemKind::NativeFun(native) => {
51                    let generics = &native.type_param_idents();
52                    native.map_types(|ty| ty.resolve(&imports, generics));
53                }
54                _ => (),
55            }
56        }
57
58        self
59    }
60}
61
62impl HasGenerics for super::Function {
63    fn generics(&self) -> Option<&Generics> {
64        self.generics.as_ref()
65    }
66}
67
68impl HasGenerics for super::NativeFun {
69    fn generics(&self) -> Option<&Generics> {
70        self.generics.as_ref()
71    }
72}
73
74impl Typed for super::Function {
75    fn map_types(&mut self, mut f: impl FnMut(&mut crate::Type)) {
76        mutate_delimited_vec(&mut self.args.0.content, |arg| f(&mut arg.type_.r#type));
77        if let Some(ret) = self.ret.as_mut() {
78            ret.map_types(f);
79        }
80    }
81}
82
83impl Typed for super::NativeFun {
84    fn map_types(&mut self, mut f: impl FnMut(&mut crate::Type)) {
85        mutate_delimited_vec(&mut self.args.0.content, |arg| f(&mut arg.type_.r#type));
86        if let Some(ret) = self.ret.as_mut() {
87            ret.map_types(f);
88        }
89    }
90}
91
92impl Typed for Returns {
93    fn map_types(&mut self, mut f: impl FnMut(&mut crate::Type)) {
94        match &mut self.type_ {
95            ReturnType::One(maybe_ref_type) => f(&mut maybe_ref_type.r#type),
96            ReturnType::Many(parenthesis_group) => {
97                mutate_delimited_vec(&mut parenthesis_group.content, |maybe_ref_type| {
98                    f(&mut maybe_ref_type.r#type)
99                })
100            }
101        }
102    }
103}
104
105impl super::Function {
106    /// The input arguments to this function.
107    pub fn arguments(&self) -> impl ExactSizeIterator<Item = &FunctionArg> {
108        self.args.0.content.iter().map(|d| &d.value)
109    }
110
111    /// The output types from this function.
112    pub fn returns(&self) -> impl ExactSizeIterator<Item = &MaybeRefType> {
113        MaybeRefTypeIter::new(self.ret.as_ref())
114    }
115}
116
117impl super::NativeFun {
118    /// The input arguments to this function.
119    pub fn arguments(&self) -> impl ExactSizeIterator<Item = &FunctionArg> {
120        self.args.0.content.iter().map(|d| &d.value)
121    }
122
123    /// The output types from this function.
124    pub fn returns(&self) -> impl ExactSizeIterator<Item = &MaybeRefType> {
125        MaybeRefTypeIter::new(self.ret.as_ref())
126    }
127}
128
129impl FunctionArg {
130    pub const fn ident(&self) -> &Ident {
131        &self.ident
132    }
133
134    pub const fn type_(&self) -> &MaybeRefType {
135        &self.type_
136    }
137}
138
139struct MaybeRefTypeIter<'a> {
140    inner: Option<&'a Returns>,
141    idx: usize,
142}
143
144impl<'a> MaybeRefTypeIter<'a> {
145    const fn new(inner: Option<&'a Returns>) -> Self {
146        Self { inner, idx: 0 }
147    }
148}
149
150impl<'a> Iterator for MaybeRefTypeIter<'a> {
151    type Item = &'a MaybeRefType;
152
153    fn next(&mut self) -> Option<Self::Item> {
154        match &self.inner {
155            None => None,
156            Some(Returns {
157                type_: ReturnType::One(maybe_ref_type),
158                ..
159            }) if self.idx == 0 => {
160                self.idx += 1;
161                Some(maybe_ref_type)
162            }
163            Some(Returns {
164                type_: ReturnType::One(_),
165                ..
166            }) => None,
167            Some(Returns {
168                type_: ReturnType::Many(parenthesis_group),
169                ..
170            }) if self.idx < parenthesis_group.content.len() => {
171                let item = &parenthesis_group.content[self.idx].value;
172                self.idx += 1;
173                Some(item)
174            }
175            Some(Returns {
176                type_: ReturnType::Many(_),
177                ..
178            }) => None,
179        }
180    }
181}
182
183impl<'a> ExactSizeIterator for MaybeRefTypeIter<'a> {
184    fn len(&self) -> usize {
185        match &self.inner {
186            None => 0,
187            Some(Returns {
188                type_: ReturnType::One(_),
189                ..
190            }) => 1,
191            Some(Returns {
192                type_: ReturnType::Many(parenthesis_group),
193                ..
194            }) => parenthesis_group.content.len(),
195        }
196    }
197}