// Part of the Carbon Language project, under the Apache License v2.0 with LLVM // Exceptions. See /LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #ifndef CARBON_TOOLCHAIN_PARSE_NODE_IDS_H_ #define CARBON_TOOLCHAIN_PARSE_NODE_IDS_H_ #include "toolchain/base/index_base.h" #include "toolchain/lex/token_index.h" #include "toolchain/parse/node_kind.h" namespace Carbon::Parse { // Represents an invalid node id of any type struct NoneNodeId {}; // A lightweight handle representing a node in the tree. // // Objects of this type are small and cheap to copy and store. They don't // contain any of the information about the node, and serve as a handle that // can be used with the underlying tree to query for detailed information. struct NodeId : public IdBase { static constexpr llvm::StringLiteral Label = "node"; // A node ID with no value. static constexpr NoneNodeId None; using IdBase::IdBase; // NOLINTNEXTLINE(google-explicit-constructor) constexpr NodeId(NoneNodeId /*none*/) : IdBase(NoneIndex) {} }; // For looking up the type associated with a given id type. template struct NodeForId; // `Id` is a typed version of `NodeId` that references a node of kind // ``: template struct NodeIdForKind : public NodeId { // NOLINTNEXTLINE(readability-identifier-naming) static const NodeKind& Kind; constexpr explicit NodeIdForKind(NodeId node_id) : NodeId(node_id) {} // NOLINTNEXTLINE(google-explicit-constructor) constexpr NodeIdForKind(NoneNodeId /*none*/) : NodeId(NoneIndex) {} }; template const NodeKind& NodeIdForKind::Kind = K; #define CARBON_PARSE_NODE_KIND(KindName) \ using KindName##Id = NodeIdForKind; #include "toolchain/parse/node_kind.def" // NodeId that matches any NodeKind whose `category()` overlaps with `Category`. template struct NodeIdInCategory : public NodeId { // Support conversion from `NodeIdForKind` if Kind's category // overlaps with `Category`. template // NOLINTNEXTLINE(google-explicit-constructor) NodeIdInCategory(NodeIdForKind node_id) : NodeId(node_id) { CARBON_CHECK(Kind.category().HasAnyOf(Category)); } constexpr explicit NodeIdInCategory(NodeId node_id) : NodeId(node_id) {} // NOLINTNEXTLINE(google-explicit-constructor) constexpr NodeIdInCategory(NoneNodeId /*none*/) : NodeId(NoneIndex) {} }; // Aliases for `NodeIdInCategory` to describe particular categories of nodes. using AnyDeclId = NodeIdInCategory; using AnyExprId = NodeIdInCategory; using AnyImplAsId = NodeIdInCategory; using AnyMemberAccessId = NodeIdInCategory; using AnyModifierId = NodeIdInCategory; using AnyPatternId = NodeIdInCategory; using AnyStatementId = NodeIdInCategory; using AnyRequirementId = NodeIdInCategory; using AnyNonExprIdentifierNameId = NodeIdInCategory; // NodeId with kind that matches one of the `T::Kind`s. template struct NodeIdOneOf : public NodeId { static_assert(sizeof...(T) >= 2, "Expected at least two types."); constexpr explicit NodeIdOneOf(NodeId node_id) : NodeId(node_id) {} template // NOLINTNEXTLINE(google-explicit-constructor) NodeIdOneOf(NodeIdForKind node_id) : NodeId(node_id) { static_assert(((T::Kind == Kind) || ...)); } // NOLINTNEXTLINE(google-explicit-constructor) constexpr NodeIdOneOf(NoneNodeId /*none*/) : NodeId(NoneIndex) {} }; using AnyClassDeclId = NodeIdOneOf; using AnyFunctionDeclId = NodeIdOneOf; using AnyImplDeclId = NodeIdOneOf; using AnyInterfaceDeclId = NodeIdOneOf; using AnyNamespaceId = NodeIdOneOf; using AnyPointerDeferenceExprId = NodeIdOneOf; // NodeId with kind that is anything but T::Kind. template struct NodeIdNot : public NodeId { constexpr explicit NodeIdNot(NodeId node_id) : NodeId(node_id) {} // NOLINTNEXTLINE(google-explicit-constructor) constexpr NodeIdNot(NoneNodeId /*none*/) : NodeId(NoneIndex) {} }; // Note that the support for extracting these types using the `Tree::Extract*` // functions is defined in `extract.cpp`. } // namespace Carbon::Parse #endif // CARBON_TOOLCHAIN_PARSE_NODE_IDS_H_