Skip to main content

luaur_analysis/methods/
arc_collector_arc_collector.rs

1//! Faithful port of `Luau::detail::ArcCollector::ArcCollector`
2//! (`Analysis/src/TopoSortStatements.cpp:207-217`).
3//!
4//! ```cpp
5//! ArcCollector(NodeQueue& queue)
6//!     : queue(queue)
7//!     , map(Identifier{std::string{}, 0})
8//!     , currentArc(nullptr)
9//! {
10//!     for (const auto& node : queue)
11//!     {
12//!         if (node->name && !map.contains(*node->name))
13//!             map[*node->name] = node.get();
14//!     }
15//! }
16//! ```
17use crate::records::arc_collector::ArcCollector;
18use crate::records::identifier::Identifier;
19use crate::records::identifier_hash::IdentifierHash;
20use crate::records::node::Node;
21use crate::type_aliases::node_queue::NodeQueue;
22use luaur_common::records::dense_hash_map::DenseHashMap;
23use luaur_common::records::dense_hash_table::DenseHasher;
24
25// Wires the C++ `IdentifierHash::operator()` functor (used as the `Hash`
26// template parameter of `DenseHashMap<Identifier, Node*, IdentifierHash>`) into
27// the container's `DenseHasher` trait so the map is constructible. The hash body
28// itself already lives in `IdentifierHash::identifier_hash_operator_call`.
29impl DenseHasher<Identifier> for IdentifierHash {
30    fn hash(&self, key: &Identifier) -> usize {
31        IdentifierHash::identifier_hash_operator_call(key)
32    }
33}
34
35impl ArcCollector {
36    pub fn arc_collector(&mut self, queue: &mut NodeQueue) {
37        // : queue(queue), map(Identifier{std::string{}, 0}), currentArc(nullptr)
38        self.queue = queue as *mut NodeQueue;
39        self.map = DenseHashMap::new(Identifier::new(
40            alloc::string::String::new(),
41            core::ptr::null(),
42        ));
43        self.current_arc = core::ptr::null_mut();
44
45        // for (const auto& node : queue)
46        //     if (node->name && !map.contains(*node->name))
47        //         map[*node->name] = node.get();
48        let size = queue.size();
49        for i in 0..size {
50            let node_ptr: *mut Node = *queue.at(i);
51            let node = unsafe { &*node_ptr };
52            if let Some(name) = &node.name {
53                if !self.map.contains(name) {
54                    *self.map.get_or_insert(name.clone()) = node_ptr;
55                }
56            }
57        }
58    }
59}