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
+34 -2
View File
@@ -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 <typename IndexType,
typename std::enable_if_t<std::is_base_of_v<IndexBase, IndexType>>* =
nullptr>
@@ -43,6 +53,28 @@ auto operator!=(IndexType lhs, IndexType rhs) -> bool {
return lhs.index != rhs.index;
}
// The < and > comparisons for only ComparableIndexBase.
template <typename IndexType, typename std::enable_if_t<std::is_base_of_v<
ComparableIndexBase, IndexType>>* = nullptr>
auto operator<(IndexType lhs, IndexType rhs) -> bool {
return lhs.index < rhs.index;
}
template <typename IndexType, typename std::enable_if_t<std::is_base_of_v<
ComparableIndexBase, IndexType>>* = nullptr>
auto operator<=(IndexType lhs, IndexType rhs) -> bool {
return lhs.index <= rhs.index;
}
template <typename IndexType, typename std::enable_if_t<std::is_base_of_v<
ComparableIndexBase, IndexType>>* = nullptr>
auto operator>(IndexType lhs, IndexType rhs) -> bool {
return lhs.index > rhs.index;
}
template <typename IndexType, typename std::enable_if_t<std::is_base_of_v<
ComparableIndexBase, IndexType>>* = nullptr>
auto operator>=(IndexType lhs, IndexType rhs) -> bool {
return lhs.index >= rhs.index;
}
} // namespace Carbon
#endif // CARBON_TOOLCHAIN_COMMON_INDEX_BASE_H_
+19 -60
View File
@@ -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<Internal::TokenizedBufferToken> {
class TokenLocationTranslator : public DiagnosticLocationTranslator<Token> {
public:
explicit TokenLocationTranslator(const TokenizedBuffer* buffer,
int* last_line_lexed_to_column)
+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
+7 -59
View File
@@ -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;
}
+2 -2
View File
@@ -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(
+7 -20
View File
@@ -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;
+1 -1
View File
@@ -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_;
}
}
+22 -73
View File
@@ -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<SemanticsNodeId, SemanticsNodeId> {
@@ -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<SemanticsIdentifierId, SemanticsNodeId> {
@@ -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<SemanticsNodeId, SemanticsNodeBlockId> {
@@ -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());
@@ -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;
}
}