Sfoglia il codice sorgente

Refactor NodeCategory for X-macros (#5029)

Taking an approach similar to NameId in #5018
Jon Ross-Perkins 1 anno fa
parent
commit
90b6f5a22c

+ 11 - 0
toolchain/parse/BUILD

@@ -18,6 +18,16 @@ manifest(
     srcs = [":testdata"],
 )
 
+cc_library(
+    name = "node_category",
+    srcs = ["node_category.cpp"],
+    hdrs = ["node_category.h"],
+    deps = [
+        "//common:ostream",
+        "@llvm-project//llvm:Support",
+    ],
+)
+
 cc_library(
     name = "node_kind",
     srcs = ["node_kind.cpp"],
@@ -28,6 +38,7 @@ cc_library(
     ],
     textual_hdrs = ["node_kind.def"],
     deps = [
+        ":node_category",
         "//common:check",
         "//common:enum_base",
         "//common:ostream",

+ 37 - 0
toolchain/parse/node_category.cpp

@@ -0,0 +1,37 @@
+// 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
+
+#include "toolchain/parse/node_category.h"
+
+#include "llvm/ADT/StringExtras.h"
+
+namespace Carbon::Parse {
+
+// Returns a string form of the node category for printing.
+static auto NodeCategoryToString(NodeCategory::RawEnumType category)
+    -> llvm::StringLiteral {
+#define CARBON_NODE_CATEGORY_TO_STRING(Name) \
+  case NodeCategory::Name:                   \
+    return #Name;
+
+  switch (category) {
+    CARBON_NODE_CATEGORY(CARBON_NODE_CATEGORY_TO_STRING)
+    CARBON_NODE_CATEGORY_TO_STRING(None)
+  }
+
+#undef CARBON_NODE_CATEGORY_TO_STRING
+}
+
+auto NodeCategory::Print(llvm::raw_ostream& out) const -> void {
+  llvm::ListSeparator sep("|");
+  auto value = value_;
+  do {
+    // The lowest set bit in the value, or 0 (`None`) if no bits are set.
+    auto lowest_bit = static_cast<RawEnumType>(value & -value);
+    out << sep << NodeCategoryToString(lowest_bit);
+    value &= ~lowest_bit;
+  } while (value);
+}
+
+}  // namespace Carbon::Parse

+ 91 - 0
toolchain/parse/node_category.h

@@ -0,0 +1,91 @@
+// 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_CATEGORY_H_
+#define CARBON_TOOLCHAIN_PARSE_NODE_CATEGORY_H_
+
+#include "common/ostream.h"
+#include "llvm/ADT/BitmaskEnum.h"
+
+namespace Carbon::Parse {
+
+LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
+
+// An X-macro for node categories. Uses should look like:
+//
+//   #define CARBON_NODE_CATEGORY_FOR_XYZ(Name) ...
+//   CARBON_NODE_CATEGORY(CARBON_NODE_CATEGORY_FOR_XYZ)
+//   #undef CARBON_NODE_CATEGORY_FOR_XYZ
+#define CARBON_NODE_CATEGORY(X) \
+  X(Decl)                       \
+  X(Expr)                       \
+  X(ImplAs)                     \
+  X(IntConst)                   \
+  X(MemberExpr)                 \
+  X(MemberName)                 \
+  X(Modifier)                   \
+  X(NonExprIdentifierName)      \
+  X(PackageName)                \
+  X(Pattern)                    \
+  X(Requirement)                \
+  X(Statement)
+
+// Represents a set of keyword modifiers, using a separate bit per modifier.
+class NodeCategory : public Printable<NodeCategory> {
+ private:
+  // Use an enum to get incremental bit shifts.
+  enum class BitShift : uint8_t {
+#define CARBON_NODE_CATEGORY_FOR_BIT_SHIFT(Name) Name,
+    CARBON_NODE_CATEGORY(CARBON_NODE_CATEGORY_FOR_BIT_SHIFT)
+#undef CARBON_NODE_CATEGORY_FOR_BIT_SHIFT
+
+    // For `LLVM_MARK_AS_BITMASK_ENUM`.
+    LargestValueMarker,
+  };
+
+ public:
+  // Provide values as an enum. This doesn't expose these as NodeCategory
+  // instances just due to the duplication of declarations that would cause.
+  //
+  // We expect this to grow, so are using a bigger size than needed.
+  // NOLINTNEXTLINE(performance-enum-size)
+  enum RawEnumType : uint32_t {
+#define CARBON_NODE_CATEGORY_FOR_BIT_MASK(Name) \
+  Name = 1 << static_cast<uint8_t>(BitShift::Name),
+    CARBON_NODE_CATEGORY(CARBON_NODE_CATEGORY_FOR_BIT_MASK)
+#undef CARBON_NODE_CATEGORY_FOR_BIT_MASK
+    // If you add a new category here, also add it to the Print function.
+    None = 0,
+
+    LLVM_MARK_AS_BITMASK_ENUM(
+        /*LargestValue=*/1
+        << (static_cast<uint8_t>(BitShift::LargestValueMarker) - 1))
+  };
+
+  // Support implicit conversion so that the difference with the member enum is
+  // opaque.
+  // NOLINTNEXTLINE(google-explicit-constructor)
+  constexpr NodeCategory(RawEnumType value) : value_(value) {}
+
+  // Returns true if there's a non-empty set intersection.
+  constexpr auto HasAnyOf(NodeCategory other) const -> bool {
+    return value_ & other.value_;
+  }
+
+  // Returns the set inverse.
+  constexpr auto operator~() const -> NodeCategory { return ~value_; }
+
+  friend auto operator==(NodeCategory lhs, NodeCategory rhs) -> bool {
+    return lhs.value_ == rhs.value_;
+  }
+
+  auto Print(llvm::raw_ostream& out) const -> void;
+
+ private:
+  RawEnumType value_;
+};
+
+}  // namespace Carbon::Parse
+
+#endif  // CARBON_TOOLCHAIN_PARSE_NODE_CATEGORY_H_

+ 0 - 31
toolchain/parse/node_kind.cpp

@@ -9,37 +9,6 @@
 
 namespace Carbon::Parse {
 
-auto NodeCategory::Print(llvm::raw_ostream& out) const -> void {
-  llvm::ListSeparator sep("|");
-  auto value = value_;
-  do {
-    // The lowest set bit in the value, or 0 (`None`) if no bits are set.
-    auto lowest_bit = static_cast<RawEnumType>(value & -value);
-    switch (lowest_bit) {
-#define CARBON_NODE_CATEGORY(Name) \
-  case NodeCategory::Name: {       \
-    out << sep << #Name;           \
-    break;                         \
-  }
-      CARBON_NODE_CATEGORY(Decl);
-      CARBON_NODE_CATEGORY(Expr);
-      CARBON_NODE_CATEGORY(ImplAs);
-      CARBON_NODE_CATEGORY(MemberExpr);
-      CARBON_NODE_CATEGORY(MemberName);
-      CARBON_NODE_CATEGORY(Modifier);
-      CARBON_NODE_CATEGORY(Pattern);
-      CARBON_NODE_CATEGORY(Statement);
-      CARBON_NODE_CATEGORY(IntConst);
-      CARBON_NODE_CATEGORY(Requirement);
-      CARBON_NODE_CATEGORY(NonExprIdentifierName);
-      CARBON_NODE_CATEGORY(PackageName);
-      CARBON_NODE_CATEGORY(None);
-#undef CARBON_NODE_CATEGORY
-    }
-    value &= ~lowest_bit;
-  } while (value);
-}
-
 CARBON_DEFINE_ENUM_CLASS_NAMES(NodeKind) = {
 #define CARBON_PARSE_NODE_KIND(Name) CARBON_ENUM_CLASS_NAME_STRING(Name)
 #include "toolchain/parse/node_kind.def"

+ 1 - 53
toolchain/parse/node_kind.h

@@ -9,63 +9,11 @@
 
 #include "common/enum_base.h"
 #include "common/ostream.h"
-#include "llvm/ADT/BitmaskEnum.h"
 #include "toolchain/lex/token_kind.h"
+#include "toolchain/parse/node_category.h"
 
 namespace Carbon::Parse {
 
-LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
-
-// Represents a set of keyword modifiers, using a separate bit per modifier.
-class NodeCategory : public Printable<NodeCategory> {
- public:
-  // Provide values as an enum. This doesn't expose these as NodeCategory
-  // instances just due to the duplication of declarations that would cause.
-  //
-  // We expect this to grow, so are using a bigger size than needed.
-  // NOLINTNEXTLINE(performance-enum-size)
-  enum RawEnumType : uint32_t {
-    Decl = 1 << 0,
-    Expr = 1 << 1,
-    ImplAs = 1 << 2,
-    MemberExpr = 1 << 3,
-    MemberName = 1 << 4,
-    Modifier = 1 << 5,
-    Pattern = 1 << 6,
-    Statement = 1 << 7,
-    IntConst = 1 << 8,
-    Requirement = 1 << 9,
-    NonExprIdentifierName = 1 << 10,
-    PackageName = 1 << 11,
-    // If you add a new category here, also add it to the Print function.
-    None = 0,
-
-    LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/PackageName)
-  };
-
-  // Support implicit conversion so that the difference with the member enum is
-  // opaque.
-  // NOLINTNEXTLINE(google-explicit-constructor)
-  constexpr NodeCategory(RawEnumType value) : value_(value) {}
-
-  // Returns true if there's a non-empty set intersection.
-  constexpr auto HasAnyOf(NodeCategory other) const -> bool {
-    return value_ & other.value_;
-  }
-
-  // Returns the set inverse.
-  constexpr auto operator~() const -> NodeCategory { return ~value_; }
-
-  friend auto operator==(NodeCategory lhs, NodeCategory rhs) -> bool {
-    return lhs.value_ == rhs.value_;
-  }
-
-  auto Print(llvm::raw_ostream& out) const -> void;
-
- private:
-  RawEnumType value_;
-};
-
 CARBON_DEFINE_RAW_ENUM_CLASS(NodeKind, uint8_t) {
 #define CARBON_PARSE_NODE_KIND(Name) CARBON_RAW_ENUM_ENUMERATOR(Name)
 #include "toolchain/parse/node_kind.def"

+ 1 - 1
toolchain/parse/typed_nodes_test.cpp

@@ -262,7 +262,7 @@ Aggregate [^:]*: success
   // Use Regex matching to avoid hard-coding the result of `typeinfo(T).name()`.
   EXPECT_THAT(err2.message(), testing::MatchesRegex(
                                   R"Trace(Aggregate [^:]*: begin
-NodeIdInCategory MemberExpr\|MemberName\|IntConst: kind IdentifierNameNotBeforeParams consumed
+NodeIdInCategory IntConst\|MemberExpr\|MemberName: kind IdentifierNameNotBeforeParams consumed
 NodeIdInCategory Expr: kind PointerMemberAccessExpr consumed
 Aggregate [^:]*: success
 )Trace"));