mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 20:00:12 +01:00
Use an x-macro for special NameId values. (#5018)
Doing an in-file X-macro, though maybe we'll want to move it out to a #include if we keep piling on more. I know there's `destroy` to add, and possibly `copy` and `move`, but I don't know what threshold we'll want for a separate file. Note this does set up for an advantage where we can `switch` instead of repeated `if` for special names, shifting to compile errors for new values. I also considered a simpler enum approach (with an implicit conversion to `NameId`) but that runs into issues with things like `Id::Kind::For<...>` as a consequence of calls like `name_id == special_name_id` (just requires another `operator==`) and `context.node_stack().Push(node_id, SemIR::NameId::SelfType);` (a little more complex how we'd want to handle it).
This commit is contained in:
+13
-19
@@ -77,6 +77,9 @@ auto IntKind::Print(llvm::raw_ostream& out) const -> void {
|
||||
}
|
||||
}
|
||||
|
||||
// Double-check the special value mapping and constexpr evaluation.
|
||||
static_assert(NameId::SpecialNameId::Vptr == *NameId::Vptr.AsSpecialNameId());
|
||||
|
||||
auto NameId::ForIdentifier(IdentifierId id) -> NameId {
|
||||
if (id.index >= 0) {
|
||||
return NameId(id.index);
|
||||
@@ -105,25 +108,16 @@ auto NameId::Print(llvm::raw_ostream& out) const -> void {
|
||||
return;
|
||||
}
|
||||
out << Label << "(";
|
||||
if (*this == Base) {
|
||||
out << "Base";
|
||||
} else if (*this == Core) {
|
||||
out << "Core";
|
||||
} else if (*this == PackageNamespace) {
|
||||
out << "PackageNamespace";
|
||||
} else if (*this == PeriodSelf) {
|
||||
out << "PeriodSelf";
|
||||
} else if (*this == ReturnSlot) {
|
||||
out << "ReturnSlot";
|
||||
} else if (*this == SelfType) {
|
||||
out << "SelfType";
|
||||
} else if (*this == SelfValue) {
|
||||
out << "SelfValue";
|
||||
} else if (*this == Vptr) {
|
||||
out << "Vptr";
|
||||
} else {
|
||||
CARBON_FATAL("Unknown index {0}", index);
|
||||
IdBase::Print(out);
|
||||
auto special_name_id = AsSpecialNameId();
|
||||
CARBON_CHECK(special_name_id, "Unknown index {0}", index);
|
||||
|
||||
switch (*special_name_id) {
|
||||
#define CARBON_SPECIAL_NAME_ID_FOR_PRINT(Name) \
|
||||
case SpecialNameId::Name: \
|
||||
out << #Name; \
|
||||
break;
|
||||
CARBON_SPECIAL_NAME_ID(CARBON_SPECIAL_NAME_ID_FOR_PRINT)
|
||||
#undef CARBON_SPECIAL_NAME_ID_FOR_PRINT
|
||||
}
|
||||
out << ")";
|
||||
}
|
||||
|
||||
+59
-30
@@ -481,6 +481,31 @@ struct FloatKind : public IdBase<FloatKind> {
|
||||
auto Print(llvm::raw_ostream& out) const -> void { out << "float"; }
|
||||
};
|
||||
|
||||
// An X-macro for special names. Uses should look like:
|
||||
//
|
||||
// #define CARBON_SPECIAL_NAME_ID_FOR_XYZ(Name) ...
|
||||
// CARBON_SPECIAL_NAME_ID(CARBON_SPECIAL_NAME_ID_FOR_XYZ)
|
||||
// #undef CARBON_SPECIAL_NAME_ID_FOR_XYZ
|
||||
#define CARBON_SPECIAL_NAME_ID(X) \
|
||||
/* The name of `base`. */ \
|
||||
X(Base) \
|
||||
/* The name of the discriminant field (if any) in a choice. */ \
|
||||
X(ChoiceDiscriminant) \
|
||||
/* The name of the package `Core`. */ \
|
||||
X(Core) \
|
||||
/* The name of `package`. */ \
|
||||
X(PackageNamespace) \
|
||||
/* The name of `.Self`. */ \
|
||||
X(PeriodSelf) \
|
||||
/* The name of the return slot in a function. */ \
|
||||
X(ReturnSlot) \
|
||||
/* The name of `Self`. */ \
|
||||
X(SelfType) \
|
||||
/* The name of `self`. */ \
|
||||
X(SelfValue) \
|
||||
/* The name of `vptr`. */ \
|
||||
X(Vptr)
|
||||
|
||||
// The ID of a name. A name is either a string or a special name such as
|
||||
// `self`, `Self`, or `base`.
|
||||
struct NameId : public IdBase<NameId> {
|
||||
@@ -491,24 +516,19 @@ struct NameId : public IdBase<NameId> {
|
||||
|
||||
// An ID with no value.
|
||||
static const NameId None;
|
||||
// The name of `base`.
|
||||
static const NameId Base;
|
||||
// The name of the package `Core`.
|
||||
static const NameId Core;
|
||||
// The name of `package`.
|
||||
static const NameId PackageNamespace;
|
||||
// The name of `.Self`.
|
||||
static const NameId PeriodSelf;
|
||||
// The name of the return slot in a function.
|
||||
static const NameId ReturnSlot;
|
||||
// The name of `Self`.
|
||||
static const NameId SelfType;
|
||||
// The name of `self`.
|
||||
static const NameId SelfValue;
|
||||
// The name of `vptr`.
|
||||
static const NameId Vptr;
|
||||
// The name of the discriminant field (if any) in a choice.
|
||||
static const NameId ChoiceDiscriminant;
|
||||
|
||||
// An enum of special names.
|
||||
enum class SpecialNameId : uint8_t {
|
||||
#define CARBON_SPECIAL_NAME_ID_FOR_ENUM(Name) Name,
|
||||
CARBON_SPECIAL_NAME_ID(CARBON_SPECIAL_NAME_ID_FOR_ENUM)
|
||||
#undef CARBON_SPECIAL_NAME_ID_FOR_ENUM
|
||||
};
|
||||
|
||||
// For each SpecialNameId, provide a matching `NameId` instance for
|
||||
// convenience.
|
||||
#define CARBON_SPECIAL_NAME_ID_FOR_DECL(Name) static const NameId Name;
|
||||
CARBON_SPECIAL_NAME_ID(CARBON_SPECIAL_NAME_ID_FOR_DECL)
|
||||
#undef CARBON_SPECIAL_NAME_ID_FOR_DECL
|
||||
|
||||
// The number of non-index (<0) that exist, and will need storage in name
|
||||
// lookup.
|
||||
@@ -529,22 +549,31 @@ struct NameId : public IdBase<NameId> {
|
||||
return index >= 0 ? IdentifierId(index) : IdentifierId::None;
|
||||
}
|
||||
|
||||
// Expose special names for `switch`.
|
||||
constexpr auto AsSpecialNameId() const -> std::optional<SpecialNameId> {
|
||||
if (index >= NoneIndex) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return static_cast<SpecialNameId>(NoneIndex - 1 - index);
|
||||
}
|
||||
|
||||
auto Print(llvm::raw_ostream& out) const -> void;
|
||||
};
|
||||
|
||||
constexpr NameId NameId::None = NameId(NoneIndex);
|
||||
constexpr NameId NameId::Base = NameId(NoneIndex - 1);
|
||||
constexpr NameId NameId::Core = NameId(NoneIndex - 2);
|
||||
constexpr NameId NameId::PackageNamespace = NameId(NoneIndex - 3);
|
||||
constexpr NameId NameId::PeriodSelf = NameId(NoneIndex - 4);
|
||||
constexpr NameId NameId::ReturnSlot = NameId(NoneIndex - 5);
|
||||
constexpr NameId NameId::SelfType = NameId(NoneIndex - 6);
|
||||
constexpr NameId NameId::SelfValue = NameId(NoneIndex - 7);
|
||||
constexpr NameId NameId::Vptr = NameId(NoneIndex - 8);
|
||||
constexpr NameId NameId::ChoiceDiscriminant = NameId(NoneIndex - 9);
|
||||
constexpr int NameId::NonIndexValueCount = 10;
|
||||
// Enforce the link between SpecialValueCount and the last special value.
|
||||
static_assert(NameId::NonIndexValueCount == -NameId::ChoiceDiscriminant.index);
|
||||
|
||||
// Define the special `static const NameId` values.
|
||||
#define CARBON_SPECIAL_NAME_ID_FOR_DEF(Name) \
|
||||
constexpr NameId NameId::Name = \
|
||||
NameId(NoneIndex - 1 - static_cast<int>(NameId::SpecialNameId::Name));
|
||||
CARBON_SPECIAL_NAME_ID(CARBON_SPECIAL_NAME_ID_FOR_DEF)
|
||||
#undef CARBON_SPECIAL_NAME_ID_FOR_DEF
|
||||
|
||||
// Count non-index values, including `None` and special names.
|
||||
#define CARBON_SPECIAL_NAME_ID_FOR_COUNT(...) +1
|
||||
constexpr int NameId::NonIndexValueCount =
|
||||
1 CARBON_SPECIAL_NAME_ID(CARBON_SPECIAL_NAME_ID_FOR_COUNT);
|
||||
#undef CARBON_SPECIAL_NAME_ID_FOR_COUNT
|
||||
|
||||
// The ID of a name scope.
|
||||
struct NameScopeId : public IdBase<NameScopeId> {
|
||||
|
||||
+23
-21
@@ -10,29 +10,31 @@ namespace Carbon::SemIR {
|
||||
|
||||
// Get the spelling to use for a special name.
|
||||
static auto GetSpecialName(NameId name_id, bool for_ir) -> llvm::StringRef {
|
||||
switch (name_id.index) {
|
||||
case NameId::None.index:
|
||||
return for_ir ? "" : "<none>";
|
||||
case NameId::Base.index:
|
||||
if (name_id == NameId::None) {
|
||||
return for_ir ? "" : "<none>";
|
||||
}
|
||||
|
||||
auto special_name_id = name_id.AsSpecialNameId();
|
||||
CARBON_CHECK(special_name_id, "Not a special name");
|
||||
switch (*special_name_id) {
|
||||
case NameId::SpecialNameId::Base:
|
||||
return "base";
|
||||
case NameId::Core.index:
|
||||
return "Core";
|
||||
case NameId::PeriodSelf.index:
|
||||
return ".Self";
|
||||
case NameId::ReturnSlot.index:
|
||||
return for_ir ? "return" : "<return slot>";
|
||||
case NameId::PackageNamespace.index:
|
||||
return "package";
|
||||
case NameId::SelfType.index:
|
||||
return "Self";
|
||||
case NameId::SelfValue.index:
|
||||
return "self";
|
||||
case NameId::Vptr.index:
|
||||
return for_ir ? "vptr" : "<vptr>";
|
||||
case NameId::ChoiceDiscriminant.index:
|
||||
case NameId::SpecialNameId::ChoiceDiscriminant:
|
||||
return "discriminant";
|
||||
default:
|
||||
CARBON_FATAL("Unknown special name");
|
||||
case NameId::SpecialNameId::Core:
|
||||
return "Core";
|
||||
case NameId::SpecialNameId::PackageNamespace:
|
||||
return "package";
|
||||
case NameId::SpecialNameId::PeriodSelf:
|
||||
return ".Self";
|
||||
case NameId::SpecialNameId::ReturnSlot:
|
||||
return for_ir ? "return" : "<return slot>";
|
||||
case NameId::SpecialNameId::SelfType:
|
||||
return "Self";
|
||||
case NameId::SpecialNameId::SelfValue:
|
||||
return "self";
|
||||
case NameId::SpecialNameId::Vptr:
|
||||
return for_ir ? "vptr" : "<vptr>";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user