Add a fixed-size ValueStore (#5628)

Trying to build a type around the common idiom we have for types based
on an Id range. The primary advantage of this is it makes clear the `Id`
association, and drops the `.index` use.

Lowering was motivating me because it has a few of these, and check
probably has more (e.g. `tree_and_subtrees_getters`), but I'm just
changing a handful of examples to show the concept and see if there's
agreement.

I wanted to inherit from ValueStoreTypes, but name lookup didn't seem to
find the types without `using` statements, at which point there didn't
seem to be much reason to use inheritance.
This commit is contained in:
Jon Ross-Perkins
2025-06-06 22:10:12 +00:00
committed by GitHub
parent b7c582ad22
commit 2e297b5258
9 changed files with 149 additions and 49 deletions
+13 -14
View File
@@ -7,15 +7,16 @@
#include <tuple>
#include <utility>
#include "toolchain/base/fixed_size_value_store.h"
#include "toolchain/lex/token_index.h"
namespace Carbon::Parse {
TreeAndSubtrees::TreeAndSubtrees(const Lex::TokenizedBuffer& tokens,
const Tree& tree)
: tokens_(&tokens), tree_(&tree) {
subtree_sizes_.reserve(tree_->size());
: tokens_(&tokens),
tree_(&tree),
subtree_sizes_(SubtreeSizeStore::MakeForOverwrite(tree_->size())) {
// A stack of nodes which haven't yet been used as children.
llvm::SmallVector<NodeId> size_stack;
for (auto n : tree.postorder()) {
@@ -31,7 +32,7 @@ TreeAndSubtrees::TreeAndSubtrees(const Lex::TokenizedBuffer& tokens,
for (auto i : llvm::seq(kind.child_count())) {
auto child = size_stack.pop_back_val();
CARBON_CHECK(static_cast<size_t>(child.index) < subtree_sizes_.size());
size += subtree_sizes_[child.index];
size += subtree_sizes_.Get(child);
if (kind.has_bracket() && i == kind.child_count() - 1) {
CARBON_CHECK(kind.bracket() == tree.node_kind(child),
"Node {0} with child count {1} needs bracket {2}, found "
@@ -45,28 +46,26 @@ TreeAndSubtrees::TreeAndSubtrees(const Lex::TokenizedBuffer& tokens,
CARBON_CHECK(!size_stack.empty(), "Node {0} is missing bracket {1}",
kind, kind.bracket());
auto child = size_stack.pop_back_val();
size += subtree_sizes_[child.index];
size += subtree_sizes_.Get(child);
if (kind.bracket() == tree.node_kind(child)) {
break;
}
}
}
size_stack.push_back(n);
subtree_sizes_.push_back(size);
subtree_sizes_.Set(n, size);
}
CARBON_CHECK(static_cast<int>(subtree_sizes_.size()) == tree_->size());
// Remaining nodes should all be roots in the tree; make sure they line up.
CARBON_CHECK(
size_stack.back().index == static_cast<int32_t>(tree_->size()) - 1,
"{0} {1}", size_stack.back(), tree_->size() - 1);
int prev_index = -1;
for (const auto& n : size_stack) {
CARBON_CHECK(n.index - subtree_sizes_[n.index] == prev_index,
CARBON_CHECK(n.index - subtree_sizes_.Get(n) == prev_index,
"NodeId {0} is a root {1} with subtree_size {2}, but previous "
"root was at {3}.",
n, tree_->node_kind(n), subtree_sizes_[n.index], prev_index);
n, tree_->node_kind(n), subtree_sizes_.Get(n), prev_index);
prev_index = n.index;
}
}
@@ -117,14 +116,14 @@ auto TreeAndSubtrees::postorder(NodeId n) const
-> llvm::iterator_range<Tree::PostorderIterator> {
// The postorder ends after this node, the root, and begins at the begin of
// its subtree.
int begin_index = n.index - subtree_sizes_[n.index] + 1;
int begin_index = n.index - subtree_sizes_.Get(n) + 1;
return Tree::PostorderIterator::MakeRange(NodeId(begin_index), n);
}
auto TreeAndSubtrees::children(NodeId n) const
-> llvm::iterator_range<SiblingIterator> {
CARBON_CHECK(n.has_value());
int end_index = n.index - subtree_sizes_[n.index];
int end_index = n.index - subtree_sizes_.Get(n);
return llvm::iterator_range<SiblingIterator>(
SiblingIterator(*this, NodeId(n.index - 1)),
SiblingIterator(*this, NodeId(end_index)));
@@ -153,8 +152,8 @@ auto TreeAndSubtrees::PrintNode(llvm::raw_ostream& output, NodeId n, int depth,
output << ", has_error: yes";
}
if (subtree_sizes_[n.index] > 1) {
output << ", subtree_size: " << subtree_sizes_[n.index];
if (subtree_sizes_.Get(n) > 1) {
output << ", subtree_size: " << subtree_sizes_.Get(n);
if (preorder) {
output << ", children: [\n";
return true;