From d50fef1736f1ac0a5dee4e75ca1ec84c575280f2 Mon Sep 17 00:00:00 2001 From: Jon Ross-Perkins Date: Thu, 1 Dec 2022 14:09:18 -0800 Subject: [PATCH] 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 --- toolchain/common/index_base.h | 36 ++++++- toolchain/lexer/tokenized_buffer.h | 79 ++++----------- toolchain/parser/parse_tree.cpp | 68 +++++++------ toolchain/parser/parse_tree.h | 66 ++----------- toolchain/semantics/semantics_ir.cpp | 4 +- toolchain/semantics/semantics_ir.h | 27 ++---- toolchain/semantics/semantics_node.cpp | 2 +- toolchain/semantics/semantics_node.h | 95 +++++-------------- .../semantics_parse_tree_handler.cpp | 2 +- 9 files changed, 125 insertions(+), 254 deletions(-) diff --git a/toolchain/common/index_base.h b/toolchain/common/index_base.h index 2495b2ed1e79..d2a91ed6d874 100644 --- a/toolchain/common/index_base.h +++ b/toolchain/common/index_base.h @@ -22,14 +22,24 @@ class DataIterator; // DataIndex is designed to be passed by value, not reference or pointer. They // are also designed to be small and efficient to store in data structures. struct IndexBase { - IndexBase() : index(-1) {} - explicit IndexBase(int index) : index(index) {} + static constexpr int32_t InvalidIndex = -1; + + constexpr IndexBase() : index(InvalidIndex) {} + constexpr explicit IndexBase(int index) : index(index) {} auto Print(llvm::raw_ostream& output) const -> void { output << index; } + auto is_valid() -> bool { return index != InvalidIndex; } + int32_t index; }; +// Like IndexBase, but also provides < and > comparison operators. +struct ComparableIndexBase : public IndexBase { + using IndexBase::IndexBase; +}; + +// Equality comparison for both IndexBase and ComparableIndexBase. template >* = nullptr> @@ -43,6 +53,28 @@ auto operator!=(IndexType lhs, IndexType rhs) -> bool { return lhs.index != rhs.index; } +// The < and > comparisons for only ComparableIndexBase. +template >* = nullptr> +auto operator<(IndexType lhs, IndexType rhs) -> bool { + return lhs.index < rhs.index; +} +template >* = nullptr> +auto operator<=(IndexType lhs, IndexType rhs) -> bool { + return lhs.index <= rhs.index; +} +template >* = nullptr> +auto operator>(IndexType lhs, IndexType rhs) -> bool { + return lhs.index > rhs.index; +} +template >* = nullptr> +auto operator>=(IndexType lhs, IndexType rhs) -> bool { + return lhs.index >= rhs.index; +} + } // namespace Carbon #endif // CARBON_TOOLCHAIN_COMMON_INDEX_BASE_H_ diff --git a/toolchain/lexer/tokenized_buffer.h b/toolchain/lexer/tokenized_buffer.h index 617bb8d0c8e2..f5be0ce53f0b 100644 --- a/toolchain/lexer/tokenized_buffer.h +++ b/toolchain/lexer/tokenized_buffer.h @@ -26,46 +26,6 @@ namespace Carbon { class TokenizedBuffer; -namespace Internal { - -// A lightweight handle to a lexed token in a `TokenizedBuffer`. -// -// This type's preferred name is `TokenizedBuffer::Token` and is only defined -// outside the class to break a dependency cycle. -// -// `Token` objects are designed to be passed by value, not reference or -// pointer. They are also designed to be small and efficient to store in data -// structures. -// -// `Token` objects from the same `TokenizedBuffer` can be compared with each -// other, both for being the same token within the buffer, and to establish -// relative position within the token stream that has been lexed out of the -// buffer. `Token` objects from different `TokenizedBuffer`s cannot be -// meaningfully compared. -// -// All other APIs to query a `Token` are on the `TokenizedBuffer`. -class TokenizedBufferToken : public IndexBase { - public: - using Token = TokenizedBufferToken; - - using IndexBase::IndexBase; - - friend auto operator<(Token lhs, Token rhs) -> bool { - return lhs.index < rhs.index; - } - friend auto operator<=(Token lhs, Token rhs) -> bool { - return lhs.index <= rhs.index; - } - friend auto operator>(Token lhs, Token rhs) -> bool { - return lhs.index > rhs.index; - } - friend auto operator>=(Token lhs, Token rhs) -> bool { - return lhs.index >= rhs.index; - } -}; - -} // namespace Internal - // A buffer of tokenized Carbon source code. // // This is constructed by lexing the source code text into a series of tokens. @@ -77,7 +37,21 @@ class TokenizedBufferToken : public IndexBase { class TokenizedBuffer { public: // A lightweight handle to a lexed token in a `TokenizedBuffer`. - using Token = Internal::TokenizedBufferToken; + // + // `Token` objects are designed to be passed by value, not reference or + // pointer. They are also designed to be small and efficient to store in data + // structures. + // + // `Token` objects from the same `TokenizedBuffer` can be compared with each + // other, both for being the same token within the buffer, and to establish + // relative position within the token stream that has been lexed out of the + // buffer. `Token` objects from different `TokenizedBuffer`s cannot be + // meaningfully compared. + // + // All other APIs to query a `Token` are on the `TokenizedBuffer`. + struct Token : public ComparableIndexBase { + using ComparableIndexBase::ComparableIndexBase; + }; // A lightweight handle to a lexed line in a `TokenizedBuffer`. // @@ -90,22 +64,8 @@ class TokenizedBuffer { // same line or the relative position of different lines within the source. // // All other APIs to query a `Line` are on the `TokenizedBuffer`. - class Line : public IndexBase { - public: - using IndexBase::IndexBase; - - friend auto operator<(Line lhs, Line rhs) -> bool { - return lhs.index < rhs.index; - } - friend auto operator<=(Line lhs, Line rhs) -> bool { - return lhs.index <= rhs.index; - } - friend auto operator>(Line lhs, Line rhs) -> bool { - return lhs.index > rhs.index; - } - friend auto operator>=(Line lhs, Line rhs) -> bool { - return lhs.index >= rhs.index; - } + struct Line : public ComparableIndexBase { + using ComparableIndexBase::ComparableIndexBase; }; // A lightweight handle to a lexed identifier in a `TokenizedBuffer`. @@ -119,7 +79,7 @@ class TokenizedBuffer { // identifier spelling. Where the identifier was written is not preserved. // // All other APIs to query a `Identifier` are on the `TokenizedBuffer`. - class Identifier : public IndexBase { + struct Identifier : public IndexBase { using IndexBase::IndexBase; }; @@ -206,8 +166,7 @@ class TokenizedBuffer { // A diagnostic location translator that maps token locations into source // buffer locations. - class TokenLocationTranslator - : public DiagnosticLocationTranslator { + class TokenLocationTranslator : public DiagnosticLocationTranslator { public: explicit TokenLocationTranslator(const TokenizedBuffer* buffer, int* last_line_lexed_to_column) diff --git a/toolchain/parser/parse_tree.cpp b/toolchain/parser/parse_tree.cpp index 8228786796cf..8d9f11665a2e 100644 --- a/toolchain/parser/parse_tree.cpp +++ b/toolchain/parser/parse_tree.cpp @@ -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 { 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 { 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 { llvm::SmallVector 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 { 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 { 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(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 { 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 diff --git a/toolchain/parser/parse_tree.h b/toolchain/parser/parse_tree.h index bd2a72173c56..af2db73a21ad 100644 --- a/toolchain/parser/parse_tree.h +++ b/toolchain/parser/parse_tree.h @@ -42,7 +42,7 @@ namespace Carbon { // applied. class ParseTree { public: - class Node; + struct Node; class PostorderIterator; class SiblingIterator; @@ -241,60 +241,8 @@ class ParseTree { // // That said, nodes can be compared and are part of a depth-first pre-order // sequence across all nodes in the parse tree. -class ParseTree::Node { - public: - // Node handles are default constructable, but such a node cannot be used - // for anything. It just allows it to be initialized later through - // assignment. Any other operation on a default constructed node is an - // error. - Node() = default; - - friend auto operator==(Node lhs, Node rhs) -> bool { - return lhs.index_ == rhs.index_; - } - friend auto operator!=(Node lhs, Node rhs) -> bool { - return lhs.index_ != rhs.index_; - } - friend auto operator<(Node lhs, Node rhs) -> bool { - return lhs.index_ < rhs.index_; - } - friend auto operator<=(Node lhs, Node rhs) -> bool { - return lhs.index_ <= rhs.index_; - } - friend auto operator>(Node lhs, Node rhs) -> bool { - return lhs.index_ > rhs.index_; - } - friend auto operator>=(Node lhs, Node rhs) -> bool { - return lhs.index_ >= rhs.index_; - } - - // Returns an opaque integer identifier of the node in the tree. Clients - // should not expect any particular semantics from this value. - // - // TODO: Maybe we can switch to stream operator overloads? - [[nodiscard]] auto index() const -> int { return index_; } - - // Prints the node index. - auto Print(llvm::raw_ostream& output) const -> void; - - // Returns true if the node is valid; in other words, it was not default - // initialized. - auto is_valid() -> bool { return index_ != InvalidValue; } - - private: - friend ParseTree; - friend PostorderIterator; - friend SiblingIterator; - - // Value for uninitialized nodes. - static constexpr int InvalidValue = -1; - - // Constructs a node with a specific index into the parse tree's postorder - // sequence of node implementations. - explicit Node(int index) : index_(index) {} - - // The index of this node's implementation in the postorder sequence. - int32_t index_ = InvalidValue; +struct ParseTree::Node : public ComparableIndexBase { + using ComparableIndexBase::ComparableIndexBase; }; // A random-access iterator to the depth-first postorder sequence of parse nodes @@ -320,15 +268,15 @@ class ParseTree::PostorderIterator auto operator*() const -> Node { return node_; } auto operator-(const PostorderIterator& rhs) const -> int { - return node_.index_ - rhs.node_.index_; + return node_.index - rhs.node_.index; } auto operator+=(int offset) -> PostorderIterator& { - node_.index_ += offset; + node_.index += offset; return *this; } auto operator-=(int offset) -> PostorderIterator& { - node_.index_ -= offset; + node_.index -= offset; return *this; } @@ -373,7 +321,7 @@ class ParseTree::SiblingIterator using iterator_facade_base::operator++; auto operator++() -> SiblingIterator& { - node_.index_ -= std::abs(tree_->node_impls_[node_.index_].subtree_size); + node_.index -= std::abs(tree_->node_impls_[node_.index].subtree_size); return *this; } diff --git a/toolchain/semantics/semantics_ir.cpp b/toolchain/semantics/semantics_ir.cpp index 369c3768b5ca..57c627d21a1b 100644 --- a/toolchain/semantics/semantics_ir.cpp +++ b/toolchain/semantics/semantics_ir.cpp @@ -26,7 +26,7 @@ auto SemanticsIR::MakeBuiltinIR() -> SemanticsIR { SemanticsNodeId(TypeOfTypeType))); semantics.cross_references_[SemanticsBuiltinKind::TypeType().AsInt()] = SemanticsCrossReference(BuiltinIR, block_id, type_type); - CARBON_CHECK(type_type.id == TypeOfTypeType) + CARBON_CHECK(type_type.index == TypeOfTypeType) << "TypeType's type must be self-referential."; constexpr int32_t TypeOfInvalidType = 1; @@ -35,7 +35,7 @@ auto SemanticsIR::MakeBuiltinIR() -> SemanticsIR { SemanticsNodeId(TypeOfInvalidType))); semantics.cross_references_[SemanticsBuiltinKind::InvalidType().AsInt()] = SemanticsCrossReference(BuiltinIR, block_id, invalid_type); - CARBON_CHECK(invalid_type.id == TypeOfInvalidType) + CARBON_CHECK(invalid_type.index == TypeOfInvalidType) << "InvalidType's type must be self-referential."; auto integer_literal_type = semantics.AddNode( diff --git a/toolchain/semantics/semantics_ir.h b/toolchain/semantics/semantics_ir.h index 86276577a48f..5418bc1ab2d4 100644 --- a/toolchain/semantics/semantics_ir.h +++ b/toolchain/semantics/semantics_ir.h @@ -18,22 +18,9 @@ class SemanticsIRForTest; namespace Carbon { // The ID of a cross-referenced IR (within cross_reference_irs_). -struct SemanticsCrossReferenceIRId { - SemanticsCrossReferenceIRId() : id(-1) {} - constexpr explicit SemanticsCrossReferenceIRId(int32_t id) : id(id) {} - - friend auto operator==(SemanticsCrossReferenceIRId lhs, - SemanticsCrossReferenceIRId rhs) -> bool { - return lhs.id == rhs.id; - } - friend auto operator!=(SemanticsCrossReferenceIRId lhs, - SemanticsCrossReferenceIRId rhs) -> bool { - return lhs.id != rhs.id; - } - - auto Print(llvm::raw_ostream& out) const -> void { out << "ir" << id; } - - int32_t id; +struct SemanticsCrossReferenceIRId : public IndexBase { + using IndexBase::IndexBase; + auto Print(llvm::raw_ostream& out) const -> void { out << "ir" << index; } }; // A cross-reference between node blocks or IRs; essentially, anything that's @@ -87,8 +74,8 @@ class SemanticsIR { -> SemanticsNodeId { if (node_id.is_cross_reference()) { auto ref = cross_references_[node_id.GetAsCrossReference()]; - auto type = cross_reference_irs_[ref.ir.id] - ->node_blocks_[ref.node_block.id][ref.node.id] + auto type = cross_reference_irs_[ref.ir.index] + ->node_blocks_[ref.node_block.index][ref.node.index] .type(); if (type.is_cross_reference() || (ref.ir == ThisIR && ref.node_block == block_id)) { @@ -103,7 +90,7 @@ class SemanticsIR { CARBON_FATAL() << "Need to think more about this case"; } } else { - return node_blocks_[block_id.id][node_id.id].type(); + return node_blocks_[block_id.index][node_id.index].type(); } } @@ -135,7 +122,7 @@ class SemanticsIR { // Adds a node to a specified block, returning an ID to reference the node. auto AddNode(SemanticsNodeBlockId block_id, SemanticsNode node) -> SemanticsNodeId { - auto& block = node_blocks_[block_id.id]; + auto& block = node_blocks_[block_id.index]; SemanticsNodeId node_id(block.size()); block.push_back(node); return node_id; diff --git a/toolchain/semantics/semantics_node.cpp b/toolchain/semantics/semantics_node.cpp index 1f6337266a5a..8493142341bb 100644 --- a/toolchain/semantics/semantics_node.cpp +++ b/toolchain/semantics/semantics_node.cpp @@ -31,7 +31,7 @@ void SemanticsNode::Print(llvm::raw_ostream& out) const { #include "toolchain/semantics/semantics_node_kind.def" } out << ")"; - if (type_.id != -1) { + if (type_.index != -1) { out << ": " << type_; } } diff --git a/toolchain/semantics/semantics_node.h b/toolchain/semantics/semantics_node.h index 677aeb520f8c..6d6149c91037 100644 --- a/toolchain/semantics/semantics_node.h +++ b/toolchain/semantics/semantics_node.h @@ -16,12 +16,12 @@ namespace Carbon { // Type-safe storage of Node IDs. -struct SemanticsNodeId { +struct SemanticsNodeId : public IndexBase { static constexpr int32_t CrossReferenceBit = 0x8000'0000; // Constructs a cross-reference node ID. - static auto MakeCrossReference(int32_t id) -> SemanticsNodeId { - return SemanticsNodeId(id | CrossReferenceBit); + static auto MakeCrossReference(int32_t index) -> SemanticsNodeId { + return SemanticsNodeId(index | CrossReferenceBit); } // Constructs a cross-reference node ID for a builtin. This relies on // SemanticsIR guarantees for builtin cross-reference placement. @@ -30,91 +30,40 @@ struct SemanticsNodeId { return MakeCrossReference(kind.AsInt()); } - SemanticsNodeId() : id(-1) {} - explicit SemanticsNodeId(int32_t id) : id(id) {} - SemanticsNodeId(SemanticsNodeId const&) = default; - auto operator=(const SemanticsNodeId& other) -> SemanticsNodeId& = default; + using IndexBase::IndexBase; - auto is_cross_reference() const -> bool { return id & CrossReferenceBit; } + auto is_cross_reference() const -> bool { return index & CrossReferenceBit; } // Returns the ID for a cross-reference, just handling removal of the marker // bit. auto GetAsCrossReference() const -> int32_t { - return id & ~CrossReferenceBit; - } - - friend auto operator==(SemanticsNodeId lhs, SemanticsNodeId rhs) -> bool { - return lhs.id == rhs.id; - } - friend auto operator!=(SemanticsNodeId lhs, SemanticsNodeId rhs) -> bool { - return lhs.id != rhs.id; + return index & ~CrossReferenceBit; } auto Print(llvm::raw_ostream& out) const -> void { if (is_cross_reference()) { out << "node_xref" << GetAsCrossReference(); } else { - out << "node" << id; + out << "node" << index; } } - - int32_t id; }; // Type-safe storage of identifiers. -struct SemanticsIdentifierId { - SemanticsIdentifierId() : id(-1) {} - explicit SemanticsIdentifierId(int32_t id) : id(id) {} - - friend auto operator==(SemanticsIdentifierId lhs, SemanticsIdentifierId rhs) - -> bool { - return lhs.id == rhs.id; - } - friend auto operator!=(SemanticsIdentifierId lhs, SemanticsIdentifierId rhs) - -> bool { - return lhs.id != rhs.id; - } - - auto Print(llvm::raw_ostream& out) const -> void { out << "ident" << id; } - - int32_t id; +struct SemanticsIdentifierId : public IndexBase { + using IndexBase::IndexBase; + auto Print(llvm::raw_ostream& out) const -> void { out << "ident" << index; } }; // Type-safe storage of integer literals. -struct SemanticsIntegerLiteralId { - SemanticsIntegerLiteralId() : id(-1) {} - explicit SemanticsIntegerLiteralId(int32_t id) : id(id) {} - - friend auto operator==(SemanticsIntegerLiteralId lhs, - SemanticsIntegerLiteralId rhs) -> bool { - return lhs.id == rhs.id; - } - friend auto operator!=(SemanticsIntegerLiteralId lhs, - SemanticsIntegerLiteralId rhs) -> bool { - return lhs.id != rhs.id; - } - - auto Print(llvm::raw_ostream& out) const -> void { out << "int" << id; } - - int32_t id; +struct SemanticsIntegerLiteralId : public IndexBase { + using IndexBase::IndexBase; + auto Print(llvm::raw_ostream& out) const -> void { out << "int" << index; } }; // Type-safe storage of node blocks. -struct SemanticsNodeBlockId { - SemanticsNodeBlockId() : id(-1) {} - explicit SemanticsNodeBlockId(int32_t id) : id(id) {} - - friend auto operator==(SemanticsNodeBlockId lhs, SemanticsNodeBlockId rhs) - -> bool { - return lhs.id == rhs.id; - } - friend auto operator!=(SemanticsNodeBlockId lhs, SemanticsNodeBlockId rhs) - -> bool { - return lhs.id != rhs.id; - } - - auto Print(llvm::raw_ostream& out) const -> void { out << "block" << id; } - - int32_t id; +struct SemanticsNodeBlockId : public IndexBase { + using IndexBase::IndexBase; + auto Print(llvm::raw_ostream& out) const -> void { out << "block" << index; } }; // The standard structure for nodes. @@ -128,7 +77,7 @@ class SemanticsNode { SemanticsNodeId type, SemanticsNodeId lhs, SemanticsNodeId rhs) -> SemanticsNode { return SemanticsNode(parse_node, SemanticsNodeKind::BinaryOperatorAdd(), - type, lhs.id, rhs.id); + type, lhs.index, rhs.index); } auto GetAsBinaryOperatorAdd() const -> std::pair { @@ -140,7 +89,7 @@ class SemanticsNode { SemanticsIdentifierId name, SemanticsNodeId node) -> SemanticsNode { return SemanticsNode(parse_node, SemanticsNodeKind::BindName(), - SemanticsNodeId(), name.id, node.id); + SemanticsNodeId(), name.index, node.index); } auto GetAsBindName() const -> std::pair { @@ -163,7 +112,7 @@ class SemanticsNode { static auto MakeCodeBlock(ParseTree::Node parse_node, SemanticsNodeBlockId node_block) -> SemanticsNode { return SemanticsNode(parse_node, SemanticsNodeKind::CodeBlock(), - SemanticsNodeId(), node_block.id); + SemanticsNodeId(), node_block.index); } auto GetAsCodeBlock() const -> SemanticsNodeBlockId { CARBON_CHECK(kind_ == SemanticsNodeKind::CodeBlock()); @@ -186,7 +135,7 @@ class SemanticsNode { SemanticsNodeBlockId node_block) -> SemanticsNode { return SemanticsNode(parse_node, SemanticsNodeKind::FunctionDefinition(), - SemanticsNodeId(), decl.id, node_block.id); + SemanticsNodeId(), decl.index, node_block.index); } auto GetAsFunctionDefinition() const -> std::pair { @@ -200,7 +149,7 @@ class SemanticsNode { return SemanticsNode(parse_node, SemanticsNodeKind::IntegerLiteral(), SemanticsNodeId::MakeBuiltinReference( SemanticsBuiltinKind::IntegerLiteralType()), - integer.id); + integer.index); } auto GetAsIntegerLiteral() const -> SemanticsIntegerLiteralId { CARBON_CHECK(kind_ == SemanticsNodeKind::IntegerLiteral()); @@ -233,7 +182,7 @@ class SemanticsNode { SemanticsNodeId type, SemanticsNodeId expr) -> SemanticsNode { return SemanticsNode(parse_node, SemanticsNodeKind::ReturnExpression(), - type, expr.id); + type, expr.index); } auto GetAsReturnExpression() const -> SemanticsNodeId { CARBON_CHECK(kind_ == SemanticsNodeKind::ReturnExpression()); diff --git a/toolchain/semantics/semantics_parse_tree_handler.cpp b/toolchain/semantics/semantics_parse_tree_handler.cpp index 11019498c165..d5f750f3bd53 100644 --- a/toolchain/semantics/semantics_parse_tree_handler.cpp +++ b/toolchain/semantics/semantics_parse_tree_handler.cpp @@ -113,7 +113,7 @@ auto SemanticsParseTreeHandler::Build() -> void { break; } default: { - CARBON_FATAL() << "In ParseTree at index " << parse_node.index() + CARBON_FATAL() << "In ParseTree at index " << parse_node << ", unhandled NodeKind " << parse_kind; } }