@@ -396,7 +396,10 @@ template <Namespace N> class ForeverStack
{
public:
ForeverStack ()
- : root (Node (Rib (Rib::Kind::Normal))), cursor_reference (root)
+ // FIXME: Is that valid? Do we use the root? If yes, we should give the
+ // crate's node id to ForeverStack's constructor
+ : root (Node (Rib (Rib::Kind::Normal), UNKNOWN_NODEID)),
+ cursor_reference (root)
{
rust_assert (root.is_root ());
rust_assert (root.is_leaf ());
@@ -478,6 +481,12 @@ public:
template <typename S>
tl::optional<NodeId> resolve_path (const std::vector<S> &segments);
+ // FIXME: Documentation
+ tl::optional<Resolver::CanonicalPath> to_canonical_path (NodeId id);
+
+ // FIXME: Documentation
+ tl::optional<Rib &> to_rib (NodeId rib_id);
+
std::string as_debug_string ();
private:
@@ -509,8 +518,10 @@ private:
class Node
{
public:
- Node (Rib rib) : rib (rib) {}
- Node (Rib rib, Node &parent) : rib (rib), parent (parent) {}
+ Node (Rib rib, NodeId id) : rib (rib), id (id) {}
+ Node (Rib rib, NodeId id, Node &parent)
+ : rib (rib), id (id), parent (parent)
+ {}
bool is_root () const;
bool is_leaf () const;
@@ -520,6 +531,8 @@ private:
Rib rib; // this is the "value" of the node - the data it keeps.
std::map<Link, Node, LinkCmp> children; // all the other nodes it links to
+ NodeId id; // The node id of the Node's scope
+
tl::optional<Node &> parent; // `None` only if the node is a root
};
@@ -566,6 +579,12 @@ private:
tl::optional<Node &> resolve_segments (Node &starting_point,
const std::vector<S> &segments,
SegIterator<S> iterator);
+
+ /* Helper functions for forward resolution (to_canonical_path, to_rib...) */
+
+ // FIXME: Documentation
+ tl::optional<std::pair<Node &, std::string>> dfs (Node &starting_point,
+ NodeId to_find);
};
} // namespace Resolver2_0
@@ -66,8 +66,8 @@ ForeverStack<N>::push_inner (Rib rib, Link link)
// the iterator and a boolean. If the value already exists, the iterator
// points to it. Otherwise, it points to the newly emplaced value, so we can
// just update our cursor().
- auto emplace
- = cursor ().children.emplace (std::make_pair (link, Node (rib, cursor ())));
+ auto emplace = cursor ().children.emplace (
+ std::make_pair (link, Node (rib, link.id, cursor ())));
auto it = emplace.first;
auto existed = !emplace.second;
@@ -451,6 +451,92 @@ ForeverStack<N>::resolve_path (const std::vector<S> &segments)
});
}
+template <Namespace N>
+tl::optional<std::pair<typename ForeverStack<N>::Node &, std::string>>
+ForeverStack<N>::dfs (ForeverStack<N>::Node &starting_point, NodeId to_find)
+{
+ auto &values = starting_point.rib.get_values ();
+
+ for (auto &kv : values)
+ if (kv.second == to_find)
+ return {{starting_point, kv.first}};
+
+ for (auto &child : starting_point.children)
+ {
+ auto candidate = dfs (child.second, to_find);
+
+ if (candidate.has_value ())
+ return candidate;
+ }
+
+ return tl::nullopt;
+}
+
+template <Namespace N>
+tl::optional<Resolver::CanonicalPath>
+ForeverStack<N>::to_canonical_path (NodeId id)
+{
+ // find the id in the current forever stack, starting from the root,
+ // performing either a BFS or DFS once the Node containing the ID is found, go
+ // back up to the root (parent().parent().parent()...) accumulate link
+ // segments reverse them that's your canonical path
+
+ return dfs (root, id).map ([this, id] (std::pair<Node &, std::string> tuple) {
+ auto containing_node = tuple.first;
+ auto name = tuple.second;
+
+ auto segments = std::vector<Resolver::CanonicalPath> ();
+
+ reverse_iter (containing_node, [&segments] (Node ¤t) {
+ if (current.is_root ())
+ return KeepGoing::No;
+
+ auto children = current.parent.value ().children;
+ const Link *outer_link = nullptr;
+
+ for (auto &kv : children)
+ {
+ auto &link = kv.first;
+ auto &child = kv.second;
+
+ if (link.id == child.id)
+ {
+ outer_link = &link;
+ break;
+ }
+ }
+
+ rust_assert (outer_link);
+
+ outer_link->path.map ([&segments, outer_link] (Identifier path) {
+ segments.emplace (segments.begin (),
+ Resolver::CanonicalPath::new_seg (outer_link->id,
+ path.as_string ()));
+ });
+
+ return KeepGoing::Yes;
+ });
+
+ auto path = Resolver::CanonicalPath::create_empty ();
+ for (const auto &segment : segments)
+ path = path.append (segment);
+
+ // Finally, append the name
+ path = path.append (Resolver::CanonicalPath::new_seg (id, name));
+ rust_debug ("[ARTHUR] found path: %s. Size: %lu", path.get ().c_str (),
+ segments.size ());
+
+ return path;
+ });
+}
+
+template <Namespace N>
+tl::optional<Rib &>
+ForeverStack<N>::to_rib (NodeId rib_id)
+{
+ return tl::nullopt;
+}
+
template <Namespace N>
void
ForeverStack<N>::stream_rib (std::stringstream &stream, const Rib &rib,