Skip to main content

microcad_lang/resolve/symbol/
iterators.rs

1// Copyright © 2026 The µcad authors <info@ucad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4//! Symbol iterators
5
6use crate::resolve::*;
7
8/// Iterator over children of a symbol.
9pub struct Children {
10    symbol: Symbol,
11    index: usize,
12}
13
14impl Children {
15    /// Create children iterator from symbol.
16    pub fn new(symbol: Symbol) -> Self {
17        Self { symbol, index: 0 }
18    }
19}
20
21impl Iterator for Children {
22    type Item = Symbol;
23
24    fn next(&mut self) -> Option<Self::Item> {
25        let symbol = self.symbol.inner.borrow();
26        let child = symbol
27            .children
28            .get_index(self.index)
29            .map(|(_, child)| child);
30        self.index += 1;
31        child.cloned()
32    }
33}
34
35/// Iterator that recursively iterates over children of a symbol.
36pub struct RecurseChildren {
37    stack: Symbols,
38}
39
40impl RecurseChildren {
41    /// Create recursive children iterator from symbol (inluding symbol itself).
42    pub(crate) fn new(symbol: Symbol) -> Self {
43        Self {
44            stack: vec![symbol].into(),
45        }
46    }
47}
48
49impl Iterator for RecurseChildren {
50    type Item = Symbol;
51
52    fn next(&mut self) -> Option<Self::Item> {
53        if let Some(symbol) = self.stack.pop() {
54            self.stack
55                .extend(symbol.inner.borrow().children.values().rev().cloned());
56
57            Some(symbol)
58        } else {
59            None
60        }
61    }
62}
63
64#[test]
65fn test_recurse_children() {
66    use crate::rc::*;
67
68    let mut root = Symbol::new(
69        SymbolDef::SourceFile(Rc::new(SourceFile::new(
70            None,
71            StatementList::default(),
72            String::new(),
73            0,
74        ))),
75        None,
76    );
77
78    let mut foo = Symbol::new(
79        SymbolDef::Tester(Identifier::no_ref("foo")),
80        Some(root.clone()),
81    );
82    {
83        let mut baz = Symbol::new(
84            SymbolDef::Tester(Identifier::no_ref("baz")),
85            Some(foo.clone()),
86        );
87        {
88            let bam = Symbol::new(
89                SymbolDef::Tester(Identifier::no_ref("bam")),
90                Some(baz.clone()),
91            );
92            baz.add_symbol(bam).expect("test error");
93        }
94
95        foo.add_symbol(baz).expect("test error");
96    }
97    root.add_symbol(foo).expect("test error");
98
99    let bar = Symbol::new(
100        SymbolDef::Tester(Identifier::no_ref("bar")),
101        Some(root.clone()),
102    );
103    root.add_symbol(bar).expect("test error");
104
105    let s = root
106        .riter()
107        .map(|symbol| format!("{}", symbol.id()))
108        .collect::<Vec<_>>()
109        .join(" ");
110
111    assert_eq!(s, "<NO ID> foo baz bam bar");
112}