mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 20:20:10 +01:00
Refactor NodeCategory for X-macros (#5029)
Taking an approach similar to NameId in #5018
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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
|
||||
@@ -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_
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"));
|
||||
|
||||
Reference in New Issue
Block a user