Expand use of IndexBase (#2436)

Initially I'd added this to lexer, this includes parser and semantics. Also adds ComparableIndexBase to unify a few common cases where <> comparisons are supported.

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
This commit is contained in:
Jon Ross-Perkins
2022-12-01 14:09:18 -08:00
committed by GitHub
co-authored by Richard Smith
parent 94cf343b05
commit d50fef1736
9 changed files with 125 additions and 254 deletions
+32 -36
View File
@@ -40,8 +40,8 @@ auto ParseTree::postorder(Node n) const
CARBON_CHECK(n.is_valid());
// The postorder ends after this node, the root, and begins at the start of
// its subtree.
int end_index = n.index_ + 1;
int start_index = end_index - node_impls_[n.index_].subtree_size;
int end_index = n.index + 1;
int start_index = end_index - node_impls_[n.index].subtree_size;
return {PostorderIterator(Node(start_index)),
PostorderIterator(Node(end_index))};
}
@@ -49,8 +49,8 @@ auto ParseTree::postorder(Node n) const
auto ParseTree::children(Node n) const
-> llvm::iterator_range<SiblingIterator> {
CARBON_CHECK(n.is_valid());
int end_index = n.index_ - node_impls_[n.index_].subtree_size;
return {SiblingIterator(*this, Node(n.index_ - 1)),
int end_index = n.index - node_impls_[n.index].subtree_size;
return {SiblingIterator(*this, Node(n.index - 1)),
SiblingIterator(*this, Node(end_index))};
}
@@ -62,38 +62,38 @@ auto ParseTree::roots() const -> llvm::iterator_range<SiblingIterator> {
auto ParseTree::node_has_error(Node n) const -> bool {
CARBON_CHECK(n.is_valid());
return node_impls_[n.index_].has_error;
return node_impls_[n.index].has_error;
}
auto ParseTree::node_kind(Node n) const -> ParseNodeKind {
CARBON_CHECK(n.is_valid());
return node_impls_[n.index_].kind;
return node_impls_[n.index].kind;
}
auto ParseTree::node_token(Node n) const -> TokenizedBuffer::Token {
CARBON_CHECK(n.is_valid());
return node_impls_[n.index_].token;
return node_impls_[n.index].token;
}
auto ParseTree::node_subtree_size(Node n) const -> int32_t {
CARBON_CHECK(n.is_valid());
return node_impls_[n.index_].subtree_size;
return node_impls_[n.index].subtree_size;
}
auto ParseTree::GetNodeText(Node n) const -> llvm::StringRef {
CARBON_CHECK(n.is_valid());
return tokens_->GetTokenText(node_impls_[n.index_].token);
return tokens_->GetTokenText(node_impls_[n.index].token);
}
auto ParseTree::PrintNode(llvm::raw_ostream& output, Node n, int depth,
bool preorder) const -> bool {
const auto& n_impl = node_impls_[n.index()];
const auto& n_impl = node_impls_[n.index];
output.indent(2 * depth);
output << "{";
// If children are being added, include node_index in order to disambiguate
// nodes.
if (preorder) {
output << "node_index: " << n.index_ << ", ";
output << "node_index: " << n << ", ";
}
output << "kind: '" << n_impl.kind.name() << "', text: '"
<< tokens_->GetTokenText(n_impl.token) << "'";
@@ -128,14 +128,14 @@ auto ParseTree::Print(llvm::raw_ostream& output) const -> void {
int depth;
std::tie(n, depth) = node_stack.pop_back_val();
for (Node sibling_n : children(n)) {
indents[sibling_n.index()] = depth + 1;
indents[sibling_n.index] = depth + 1;
node_stack.push_back({sibling_n, depth + 1});
}
}
output << "[\n";
for (Node n : postorder()) {
PrintNode(output, n, indents[n.index()], /*adding_children=*/false);
PrintNode(output, n, indents[n.index], /*adding_children=*/false);
output << ",\n";
}
output << "]\n";
@@ -192,12 +192,12 @@ auto ParseTree::Verify() const -> std::optional<Error> {
llvm::SmallVector<ParseTree::Node> nodes;
// Traverse the tree in postorder.
for (Node n : postorder()) {
const auto& n_impl = node_impls_[n.index()];
const auto& n_impl = node_impls_[n.index];
if (n_impl.has_error && !has_errors_) {
return Error(llvm::formatv(
"Node #{0} has errors, but the tree is not marked as having any.",
n.index()));
n.index));
}
int subtree_size = 1;
@@ -207,9 +207,9 @@ auto ParseTree::Verify() const -> std::optional<Error> {
return Error(
llvm::formatv("Node #{0} is a {1} with bracket {2}, but didn't "
"find the bracket.",
n.index(), n_impl.kind, n_impl.kind.bracket()));
n, n_impl.kind, n_impl.kind.bracket()));
}
auto child_impl = node_impls_[nodes.pop_back_val().index()];
auto child_impl = node_impls_[nodes.pop_back_val().index];
subtree_size += child_impl.subtree_size;
if (n_impl.kind.bracket() == child_impl.kind) {
break;
@@ -221,35 +221,35 @@ auto ParseTree::Verify() const -> std::optional<Error> {
return Error(llvm::formatv(
"Node #{0} is a {1} with child_count {2}, but only had {3} "
"nodes to consume.",
n.index(), n_impl.kind, n_impl.kind.child_count(), i));
n, n_impl.kind, n_impl.kind.child_count(), i));
}
auto child_impl = node_impls_[nodes.pop_back_val().index()];
auto child_impl = node_impls_[nodes.pop_back_val().index];
subtree_size += child_impl.subtree_size;
}
}
if (n_impl.subtree_size != subtree_size) {
return Error(llvm::formatv(
"Node #{0} is a {1} with subtree_size of {2}, but calculated {3}.",
n.index(), n_impl.kind, n_impl.subtree_size, subtree_size));
"Node #{0} is a {1} with subtree_size of {2}, but calculated {3}.", n,
n_impl.kind, n_impl.subtree_size, subtree_size));
}
nodes.push_back(n);
}
// Remaining nodes should all be roots in the tree; make sure they line up.
CARBON_CHECK(nodes.back().index() ==
CARBON_CHECK(nodes.back().index ==
static_cast<int32_t>(node_impls_.size()) - 1)
<< nodes.back().index() << " " << node_impls_.size() - 1;
<< nodes.back() << " " << node_impls_.size() - 1;
int prev_index = -1;
for (const auto& n : nodes) {
const auto& n_impl = node_impls_[n.index()];
const auto& n_impl = node_impls_[n.index];
if (n.index() - n_impl.subtree_size != prev_index) {
return Error(llvm::formatv(
"Node #{0} is a root {1} with subtree_size {2}, but "
"previous root was at #{3}.",
n.index(), n_impl.kind, n_impl.subtree_size, prev_index));
if (n.index - n_impl.subtree_size != prev_index) {
return Error(
llvm::formatv("Node #{0} is a root {1} with subtree_size {2}, but "
"previous root was at #{3}.",
n, n_impl.kind, n_impl.subtree_size, prev_index));
}
prev_index = n.index();
prev_index = n.index;
}
if (!has_errors_ &&
@@ -262,18 +262,14 @@ auto ParseTree::Verify() const -> std::optional<Error> {
return std::nullopt;
}
auto ParseTree::Node::Print(llvm::raw_ostream& output) const -> void {
output << index();
}
auto ParseTree::PostorderIterator::Print(llvm::raw_ostream& output) const
-> void {
output << node_.index();
output << node_;
}
auto ParseTree::SiblingIterator::Print(llvm::raw_ostream& output) const
-> void {
output << node_.index();
output << node_;
}
} // namespace Carbon