rustpython_ast/
generic.rs

1#![allow(clippy::derive_partial_eq_without_eq)]
2pub use crate::{builtin::*, text_size::TextSize, ConversionFlag, Node};
3use std::fmt::{Debug, Display, Formatter};
4use std::marker::PhantomData;
5
6pub type Suite<R = TextRange> = Vec<Stmt<R>>;
7
8#[cfg(feature = "all-nodes-with-ranges")]
9pub type OptionalRange<R> = R;
10
11#[cfg(not(feature = "all-nodes-with-ranges"))]
12pub type OptionalRange<R> = EmptyRange<R>;
13
14#[cfg(not(feature = "all-nodes-with-ranges"))]
15impl<R> From<R> for OptionalRange<R> {
16    fn from(_: R) -> Self {
17        Self {
18            phantom: PhantomData,
19        }
20    }
21}
22
23#[derive(Eq, PartialEq, Hash, Copy, Clone)]
24pub struct EmptyRange<R> {
25    phantom: PhantomData<R>,
26}
27
28impl<R> EmptyRange<R> {
29    #[inline(always)]
30    pub fn new(_start: TextSize, _end: TextSize) -> Self {
31        Self {
32            phantom: PhantomData,
33        }
34    }
35}
36
37impl<R> Display for EmptyRange<R> {
38    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
39        f.write_str("()")
40    }
41}
42
43impl<R> Debug for EmptyRange<R> {
44    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
45        Display::fmt(self, f)
46    }
47}
48
49impl<R> Default for EmptyRange<R> {
50    fn default() -> Self {
51        EmptyRange {
52            phantom: PhantomData,
53        }
54    }
55}
56
57impl CmpOp {
58    pub fn as_str(&self) -> &'static str {
59        match self {
60            CmpOp::Eq => "==",
61            CmpOp::NotEq => "!=",
62            CmpOp::Lt => "<",
63            CmpOp::LtE => "<=",
64            CmpOp::Gt => ">",
65            CmpOp::GtE => ">=",
66            CmpOp::Is => "is",
67            CmpOp::IsNot => "is not",
68            CmpOp::In => "in",
69            CmpOp::NotIn => "not in",
70        }
71    }
72}
73
74impl<R> Arguments<R> {
75    pub fn empty(range: OptionalRange<R>) -> Self {
76        Self {
77            range,
78            posonlyargs: Vec::new(),
79            args: Vec::new(),
80            vararg: None,
81            kwonlyargs: Vec::new(),
82            kwarg: None,
83        }
84    }
85}
86
87#[allow(clippy::borrowed_box)] // local utility
88fn clone_boxed_expr<R: Clone>(expr: &Box<Expr<R>>) -> Box<Expr<R>> {
89    let expr: &Expr<_> = expr.as_ref();
90    Box::new(expr.clone())
91}
92
93impl<R> ArgWithDefault<R> {
94    pub fn from_arg(def: Arg<R>, default: Option<Expr<R>>) -> Self
95    where
96        R: Clone,
97    {
98        let range = {
99            if cfg!(feature = "all-nodes-with-ranges") {
100                todo!("range recovery is not implemented yet") // def.range.start()..default.range.end()
101            } else {
102                #[allow(clippy::useless_conversion)] // false positive by cfg
103                OptionalRange::from(def.range.clone())
104            }
105        };
106        Self {
107            range,
108            def,
109            default: default.map(Box::new),
110        }
111    }
112
113    pub fn as_arg(&self) -> &Arg<R> {
114        &self.def
115    }
116
117    pub fn to_arg(&self) -> (Arg<R>, Option<Box<Expr<R>>>)
118    where
119        R: Clone,
120    {
121        let ArgWithDefault {
122            range: _,
123            def,
124            default,
125        } = self;
126        (def.clone(), default.as_ref().map(clone_boxed_expr))
127    }
128    pub fn into_arg(self) -> (Arg<R>, Option<Box<Expr<R>>>) {
129        let ArgWithDefault {
130            range: _,
131            def,
132            default,
133        } = self;
134        (def, default)
135    }
136}
137
138impl<R> Arguments<R> {
139    pub fn defaults(&self) -> impl std::iter::Iterator<Item = &Expr<R>> {
140        self.posonlyargs
141            .iter()
142            .chain(self.args.iter())
143            .filter_map(|arg| arg.default.as_ref().map(|e| e.as_ref()))
144    }
145
146    #[allow(clippy::type_complexity)]
147    pub fn split_kwonlyargs(&self) -> (Vec<&Arg<R>>, Vec<(&Arg<R>, &Expr<R>)>) {
148        let mut args = Vec::new();
149        let mut with_defaults = Vec::new();
150        for arg in self.kwonlyargs.iter() {
151            if let Some(ref default) = arg.default {
152                with_defaults.push((arg.as_arg(), &**default));
153            } else {
154                args.push(arg.as_arg());
155            }
156        }
157        (args, with_defaults)
158    }
159
160    pub fn to_python_arguments(&self) -> PythonArguments<R>
161    where
162        R: Clone,
163    {
164        let Arguments {
165            range,
166            posonlyargs,
167            args,
168            vararg,
169            kwonlyargs,
170            kwarg,
171        } = self;
172
173        let mut pos_only = Vec::with_capacity(posonlyargs.len());
174        let mut pos_args = Vec::with_capacity(args.len());
175        let mut defaults = Vec::new();
176        for arg in posonlyargs {
177            let (arg, default) = arg.to_arg();
178            if let Some(default) = default {
179                defaults.push(*default);
180            }
181            pos_only.push(arg);
182        }
183        for arg in args {
184            let (arg, default) = arg.to_arg();
185            if let Some(default) = default {
186                defaults.push(*default);
187            }
188            pos_args.push(arg);
189        }
190
191        let mut kw_only = Vec::with_capacity(kwonlyargs.len());
192        let mut kw_defaults = Vec::new();
193        for arg in kwonlyargs {
194            let (arg, default) = arg.to_arg();
195            if let Some(default) = default {
196                kw_defaults.push(*default);
197            }
198            kw_only.push(arg);
199        }
200
201        PythonArguments {
202            range: range.clone(),
203            posonlyargs: pos_only,
204            args: pos_args,
205            defaults,
206            vararg: vararg.clone(),
207            kwonlyargs: kw_only,
208            kw_defaults,
209            kwarg: kwarg.clone(),
210        }
211    }
212
213    pub fn into_python_arguments(self) -> PythonArguments<R> {
214        let Arguments {
215            range,
216            posonlyargs,
217            args,
218            vararg,
219            kwonlyargs,
220            kwarg,
221        } = self;
222
223        let mut pos_only = Vec::with_capacity(posonlyargs.len());
224        let mut pos_args = Vec::with_capacity(args.len());
225        let mut defaults = Vec::new();
226        for arg in posonlyargs {
227            let (arg, default) = arg.into_arg();
228            if let Some(default) = default {
229                defaults.push(*default);
230            }
231            pos_only.push(arg);
232        }
233        for arg in args {
234            let (arg, default) = arg.into_arg();
235            if let Some(default) = default {
236                defaults.push(*default);
237            }
238            pos_args.push(arg);
239        }
240
241        let mut kw_only = Vec::with_capacity(kwonlyargs.len());
242        let mut kw_defaults = Vec::new();
243        for arg in kwonlyargs {
244            let (arg, default) = arg.into_arg();
245            if let Some(default) = default {
246                kw_defaults.push(*default);
247            }
248            kw_only.push(arg);
249        }
250
251        PythonArguments {
252            range,
253            posonlyargs: pos_only,
254            args: pos_args,
255            defaults,
256            vararg,
257            kwonlyargs: kw_only,
258            kw_defaults,
259            kwarg,
260        }
261    }
262}
263
264impl<R> PythonArguments<R> {
265    pub fn into_arguments(self) -> Arguments<R>
266    where
267        R: Clone,
268    {
269        let PythonArguments {
270            range,
271            posonlyargs,
272            args,
273            defaults,
274            vararg,
275            kwonlyargs,
276            kw_defaults,
277            kwarg,
278        } = self;
279
280        let mut pos_only = Vec::with_capacity(posonlyargs.len());
281        let mut pos_args = Vec::with_capacity(args.len());
282        let args_len = posonlyargs.len() + args.len();
283        // not optimal
284        let mut defaults: Vec<_> = std::iter::repeat_with(|| None)
285            .take(args_len - defaults.len())
286            .chain(defaults.into_iter().map(Some))
287            .collect();
288        debug_assert_eq!(args_len, defaults.len());
289
290        for (arg, default) in std::iter::zip(args, defaults.drain(posonlyargs.len()..)) {
291            let arg = ArgWithDefault::from_arg(arg, default);
292            pos_args.push(arg);
293        }
294
295        for (arg, default) in std::iter::zip(posonlyargs, defaults.drain(..)) {
296            let arg = ArgWithDefault::from_arg(arg, default);
297            pos_only.push(arg);
298        }
299
300        let mut kw_only = Vec::with_capacity(kwonlyargs.len());
301        let kw_defaults: Vec<_> = std::iter::repeat_with(|| None)
302            .take(kw_only.len().saturating_sub(kw_defaults.len()))
303            .chain(kw_defaults.into_iter().map(Some))
304            .collect();
305        for (arg, default) in std::iter::zip(kwonlyargs, kw_defaults) {
306            let arg = ArgWithDefault::from_arg(arg, default);
307            kw_only.push(arg);
308        }
309
310        Arguments {
311            range,
312            posonlyargs: pos_only,
313            args: pos_args,
314            vararg,
315            kwonlyargs: kw_only,
316            kwarg,
317        }
318    }
319}
320
321impl<R> From<Arguments<R>> for PythonArguments<R> {
322    fn from(arguments: Arguments<R>) -> Self {
323        arguments.into_python_arguments()
324    }
325}
326
327include!("gen/generic.rs");