Skip to content

[Macros] Macro-metaprogram macro roles #69840

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 8 additions & 28 deletions include/swift/AST/MacroDeclaration.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,37 +32,17 @@ enum class MacroSyntax: uint8_t {
Attached,
};

enum class MacroRoleBits: uint8_t {
#define MACRO_ROLE(Name, Description) Name,
#include "swift/Basic/MacroRoles.def"
};

/// The context in which a macro can be used, which determines the syntax it
/// uses.
enum class MacroRole: uint32_t {
/// An expression macro, referenced explicitly via "#stringify" or similar
/// in the source code.
Expression = 0x01,
/// A freestanding declaration macro.
Declaration = 0x02,
/// An attached macro that declares accessors for a variable or subscript
/// declaration.
Accessor = 0x04,
/// An attached macro that generates attributes for the
/// members inside the declaration.
MemberAttribute = 0x08,
/// An attached macro that generates synthesized members
/// inside the declaration.
Member = 0x10,
/// An attached macro that generates declarations that are peers
/// of the declaration the macro is attached to.
Peer = 0x20,
/// An attached macro that adds conformances to the declaration the
/// macro is attached to.
Conformance = 0x40,
/// A freestanding macro that expands to expressions, statements and
/// declarations in a code block.
CodeItem = 0x80,
/// An attached macro that adds extensions to the declaration the
/// macro is attached to.
Extension = 0x100,

// NOTE: When adding a new macro role, also add it to `getAllMacroRoles`.
#define MACRO_ROLE(Name, Description) \
Name = 1 << static_cast<uint8_t>(MacroRoleBits::Name),
#include "swift/Basic/MacroRoles.def"
};

/// Returns an enumeratable list of all macro roles.
Expand Down
79 changes: 79 additions & 0 deletions include/swift/Basic/MacroRoles.def
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
//===--- MacroRoles.def - Known macro roles --*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines all of the kinds of macro roles. Clients should define
// either MACRO_ROLE or both ATTACHED_MACRO_ROLE and FREESTANDING_MACRO_ROLE.
//
//===----------------------------------------------------------------------===//

#ifndef ATTACHED_MACRO_ROLE
# define ATTACHED_MACRO_ROLE(Name, Description) MACRO_ROLE(Name, Description)
#endif

#ifndef FREESTANDING_MACRO_ROLE
# define FREESTANDING_MACRO_ROLE(Name, Description) MACRO_ROLE(Name, Description)
#endif

#ifndef EXPERIMENTAL_ATTACHED_MACRO_ROLE
# define EXPERIMENTAL_ATTACHED_MACRO_ROLE(Name, Description, Feature) \
ATTACHED_MACRO_ROLE(Name, Description)
#endif

#ifndef EXPERIMENTAL_FREESTANDING_MACRO_ROLE
# define EXPERIMENTAL_FREESTANDING_MACRO_ROLE(Name, Description, Feature) \
FREESTANDING_MACRO_ROLE(Name, Description)
#endif

/// An expression macro, referenced explicitly via "#stringify" or similar
/// in the source code.
FREESTANDING_MACRO_ROLE(Expression, "expression")

/// A freestanding declaration macro.
FREESTANDING_MACRO_ROLE(Declaration, "declaration")


/// An attached macro that declares accessors for a variable or subscript
/// declaration.
ATTACHED_MACRO_ROLE(Accessor, "accessor")

/// An attached macro that generates attributes for the
/// members inside the declaration.
ATTACHED_MACRO_ROLE(MemberAttribute, "memberAttribute")

/// An attached macro that generates synthesized members
/// inside the declaration.
ATTACHED_MACRO_ROLE(Member, "member")

/// An attached macro that generates declarations that are peers
/// of the declaration the macro is attached to.
ATTACHED_MACRO_ROLE(Peer, "peer")

/// An attached macro that adds conformances to the declaration the
/// macro is attached to.
ATTACHED_MACRO_ROLE(Conformance, "conformance")

/// A freestanding macro that expands to expressions, statements and
/// declarations in a code block.
EXPERIMENTAL_FREESTANDING_MACRO_ROLE(CodeItem, "codeItem", CodeItemMacros)

/// An attached macro that adds extensions to the declaration the
/// macro is attached to.
ATTACHED_MACRO_ROLE(Extension, "extension")

#undef ATTACHED_MACRO_ROLE
#undef FREESTANDING_MACRO_ROLE
#undef EXPERIMENTAL_ATTACHED_MACRO_ROLE
#undef EXPERIMENTAL_FREESTANDING_MACRO_ROLE

#ifdef MACRO_ROLE
# undef MACRO_ROLE
#endif
25 changes: 2 additions & 23 deletions include/swift/Basic/SourceManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,29 +34,8 @@ class GeneratedSourceInfo {
public:
/// The kind of generated source code.
enum Kind {
/// The expansion of a freestanding expression macro.
ExpressionMacroExpansion,

/// The expansion of a freestanding declaration macro.
FreestandingDeclMacroExpansion,

/// The expansion of an accessor attached macro.
AccessorMacroExpansion,

/// The expansion of a member attribute attached macro.
MemberAttributeMacroExpansion,

/// The expansion of an attached member macro.
MemberMacroExpansion,

/// The expansion of an attached peer macro.
PeerMacroExpansion,

/// The expansion of an attached conformance macro.
ConformanceMacroExpansion,

/// The expansion of an attached extension macro.
ExtensionMacroExpansion,
#define MACRO_ROLE(Name, Description) Name##MacroExpansion,
#include "swift/Basic/MacroRoles.def"

/// A new function body that is replacing an existing function body.
ReplacedFunctionBody,
Expand Down
87 changes: 30 additions & 57 deletions lib/AST/ASTMangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3873,80 +3873,54 @@ void ASTMangler::appendMacroExpansionContext(
DeclContext *outerExpansionDC;
DeclBaseName baseName;
unsigned discriminator;

// Determine the macro role.
MacroRole role;
switch (generatedSourceInfo->kind) {
case GeneratedSourceInfo::ExpressionMacroExpansion: {
#define MACRO_ROLE(Name, Description) \
case GeneratedSourceInfo::Name##MacroExpansion: \
role = MacroRole::Name; \
break;
#include "swift/Basic/MacroRoles.def"

case GeneratedSourceInfo::PrettyPrinted:
case GeneratedSourceInfo::ReplacedFunctionBody:
return appendContext(origDC, StringRef());
}

switch (generatedSourceInfo->kind) {
// Freestanding macros
#define FREESTANDING_MACRO_ROLE(Name, Description) \
case GeneratedSourceInfo::Name##MacroExpansion:
#define ATTACHED_MACRO_ROLE(Name, Description)
#include "swift/Basic/MacroRoles.def"
{
auto parent = ASTNode::getFromOpaqueValue(generatedSourceInfo->astNode);
if (auto expr =
cast_or_null<MacroExpansionExpr>(parent.dyn_cast<Expr *>())) {
outerExpansionLoc = expr->getLoc();
baseName = expr->getMacroName().getBaseName();
discriminator = expr->getDiscriminator();
role = MacroRole::Expression;
outerExpansionDC = expr->getDeclContext();
} else {
auto decl = cast<MacroExpansionDecl>(parent.get<Decl *>());
outerExpansionLoc = decl->getLoc();
baseName = decl->getMacroName().getBaseName();
discriminator = decl->getDiscriminator();
role = MacroRole::Declaration;
outerExpansionDC = decl->getDeclContext();
}
break;
}

case GeneratedSourceInfo::FreestandingDeclMacroExpansion: {
auto expansion =
cast<MacroExpansionDecl>(
ASTNode::getFromOpaqueValue(generatedSourceInfo->astNode)
.get<Decl *>());
outerExpansionLoc = expansion->getLoc();
outerExpansionDC = expansion->getDeclContext();
discriminator = expansion->getDiscriminator();
role = MacroRole::Declaration;
baseName = expansion->getMacroName().getBaseName();
break;
}

case GeneratedSourceInfo::AccessorMacroExpansion:
case GeneratedSourceInfo::MemberAttributeMacroExpansion:
case GeneratedSourceInfo::MemberMacroExpansion:
case GeneratedSourceInfo::PeerMacroExpansion:
case GeneratedSourceInfo::ConformanceMacroExpansion:
case GeneratedSourceInfo::ExtensionMacroExpansion: {
// Attached macros
#define FREESTANDING_MACRO_ROLE(Name, Description)
#define ATTACHED_MACRO_ROLE(Name, Description) \
case GeneratedSourceInfo::Name##MacroExpansion:
#include "swift/Basic/MacroRoles.def"
{
auto decl = ASTNode::getFromOpaqueValue(generatedSourceInfo->astNode)
.get<Decl *>();
auto attr = generatedSourceInfo->attachedMacroCustomAttr;

switch (generatedSourceInfo->kind) {
case GeneratedSourceInfo::AccessorMacroExpansion:
role = MacroRole::Accessor;
break;

case GeneratedSourceInfo::MemberAttributeMacroExpansion:
role = MacroRole::MemberAttribute;
break;

case GeneratedSourceInfo::MemberMacroExpansion:
role = MacroRole::Member;
break;

case GeneratedSourceInfo::PeerMacroExpansion:
role = MacroRole::Peer;
break;

case GeneratedSourceInfo::ConformanceMacroExpansion:
role = MacroRole::Conformance;
break;

case GeneratedSourceInfo::ExtensionMacroExpansion:
role = MacroRole::Extension;
break;

default:
llvm_unreachable("Unhandled macro role");
}

outerExpansionLoc = decl->getLoc();
outerExpansionDC = decl->getDeclContext();

Expand All @@ -3956,13 +3930,12 @@ void ASTMangler::appendMacroExpansionContext(
baseName = ctx.getIdentifier("__unknown_macro__");

discriminator = decl->getAttachedMacroDiscriminator(baseName, role, attr);

break;
}

case GeneratedSourceInfo::PrettyPrinted:
case GeneratedSourceInfo::ReplacedFunctionBody:
return appendContext(origDC, StringRef());
llvm_unreachable("Exited above");
}

// If we hit the point where the structure is represented as a DeclContext,
Expand All @@ -3982,9 +3955,9 @@ void ASTMangler::appendMacroExpansionOperator(
appendIdentifier(macroName);

switch (role) {
case MacroRole::Expression:
case MacroRole::Declaration:
case MacroRole::CodeItem:
#define FREESTANDING_MACRO_ROLE(Name, Description) case MacroRole::Name:
#define ATTACHED_MACRO_ROLE(Name, Description)
#include "swift/Basic/MacroRoles.def"
appendOperator("fMf", Index(discriminator));
break;

Expand Down
Loading