sway_core/language/
module.rs

1use sway_types::Ident;
2
3/// The name used within a module to refer to one of its submodules.
4///
5/// If an alias was given to the `mod`, this will be the alias. If not, this is the submodule's
6/// library name.
7pub type ModName = Ident;
8
9pub trait HasModule<T>
10where
11    T: HasSubmodules<Self>,
12    Self: Sized,
13{
14    /// Returns the module of this submodule.
15    fn module(&self) -> &T;
16}
17
18pub trait HasSubmodules<E>
19where
20    E: HasModule<Self>,
21    Self: Sized,
22{
23    /// Returns the submodules of this module.
24    fn submodules(&self) -> &[(ModName, E)];
25
26    /// An iterator yielding all submodules recursively, depth-first.
27    fn submodules_recursive(&self) -> SubmodulesRecursive<Self, E> {
28        SubmodulesRecursive {
29            _module_type: std::marker::PhantomData,
30            submods: self.submodules().iter(),
31            current: None,
32        }
33    }
34}
35
36type NamedSubmodule<E> = (ModName, E);
37type SubmoduleItem<'module, T, E> = (
38    &'module NamedSubmodule<E>,
39    Box<SubmodulesRecursive<'module, T, E>>,
40);
41
42/// Iterator type for iterating over submodules.
43///
44/// Used rather than `impl Iterator` to enable recursive submodule iteration.
45pub struct SubmodulesRecursive<'module, T, E> {
46    _module_type: std::marker::PhantomData<T>,
47    submods: std::slice::Iter<'module, NamedSubmodule<E>>,
48    current: Option<SubmoduleItem<'module, T, E>>,
49}
50
51impl<'module, T, E> Iterator for SubmodulesRecursive<'module, T, E>
52where
53    T: HasSubmodules<E> + 'module,
54    E: HasModule<T>,
55{
56    type Item = &'module (ModName, E);
57    fn next(&mut self) -> Option<Self::Item> {
58        loop {
59            self.current = match self.current.take() {
60                None => match self.submods.next() {
61                    None => return None,
62                    Some(submod) => {
63                        Some((submod, Box::new(submod.1.module().submodules_recursive())))
64                    }
65                },
66                Some((submod, mut submods)) => match submods.next() {
67                    Some(next) => {
68                        self.current = Some((submod, submods));
69                        return Some(next);
70                    }
71                    None => return Some(submod),
72                },
73            }
74        }
75    }
76}