Skip to content

Commit 33b49d4

Browse files
authored
Merge pull request #64765 from rxwei/code-item-macro
[Macros] Code item macros
2 parents 9d5df0b + 01e6fe2 commit 33b49d4

24 files changed

+226
-25
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2049,8 +2049,8 @@ ERROR(macro_role_attr_expected_kind,PointsToFirstBadToken,
20492049
"expected %select{a freestanding|an attached}0 macro role such as "
20502050
"%select{'expression'|'accessor'}0", (bool))
20512051
ERROR(macro_role_syntax_mismatch,PointsToFirstBadToken,
2052-
"expected %select{a freestanding|an attached}0 macro cannot have "
2053-
"the %1 role", (bool, Identifier))
2052+
"%select{a freestanding|an attached}0 macro cannot have the %1 role",
2053+
(bool, Identifier))
20542054
ERROR(macro_attribute_unknown_label,PointsToFirstBadToken,
20552055
"@%select{freestanding|attached}0 has no argument with label %1",
20562056
(bool, Identifier))

include/swift/AST/DiagnosticsSema.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7032,6 +7032,11 @@ ERROR(invalid_macro_introduced_name,none,
70327032
ERROR(global_freestanding_macro_script,none,
70337033
"global freestanding macros not yet supported in script mode",
70347034
())
7035+
ERROR(invalid_macro_role_for_macro_syntax,none,
7036+
"invalid macro role for %{a freestanding|an attached}0 macro",
7037+
(unsigned))
7038+
ERROR(macro_cannot_introduce_names,none,
7039+
"'%0' macros are not allowed to introduce names", (StringRef))
70357040

70367041
//------------------------------------------------------------------------------
70377042
// MARK: Move Only Errors

include/swift/AST/MacroDeclaration.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ enum class MacroRole: uint32_t {
5555
/// An attached macro that adds conformances to the declaration the
5656
/// macro is attached to.
5757
Conformance = 0x40,
58+
/// A freestanding macro that expands to expressions, statements and
59+
/// declarations in a code block.
60+
CodeItem = 0x80,
5861
};
5962

6063
/// The contexts in which a particular macro declaration can be used.

include/swift/Basic/Features.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ EXPERIMENTAL_FEATURE(VariadicGenerics, false)
112112
EXPERIMENTAL_FEATURE(NamedOpaqueTypes, false)
113113
EXPERIMENTAL_FEATURE(FlowSensitiveConcurrencyCaptures, false)
114114
EXPERIMENTAL_FEATURE(FreestandingMacros, true)
115+
EXPERIMENTAL_FEATURE(CodeItemMacros, true)
115116

116117
// FIXME: MoveOnlyClasses is not intended to be in production,
117118
// but our tests currently rely on it, and we want to run those

lib/AST/ASTMangler.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3965,6 +3965,7 @@ void ASTMangler::appendMacroExpansionOperator(
39653965
switch (role) {
39663966
case MacroRole::Expression:
39673967
case MacroRole::Declaration:
3968+
case MacroRole::CodeItem:
39683969
appendOperator("fMf", Index(discriminator));
39693970
break;
39703971

lib/AST/ASTPrinter.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2838,6 +2838,14 @@ static bool usesFeatureFreestandingMacros(Decl *decl) {
28382838
return macro->getMacroRoles().contains(MacroRole::Declaration);
28392839
}
28402840

2841+
static bool usesFeatureCodeItemMacros(Decl *decl) {
2842+
auto macro = dyn_cast<MacroDecl>(decl);
2843+
if (!macro)
2844+
return false;
2845+
2846+
return macro->getMacroRoles().contains(MacroRole::CodeItem);
2847+
}
2848+
28412849
static bool usesFeatureAttachedMacros(Decl *decl) {
28422850
auto macro = dyn_cast<MacroDecl>(decl);
28432851
if (!macro)

lib/AST/ASTScopeCreation.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ ASTSourceFileScope::ASTSourceFileScope(SourceFile *SF,
261261
switch (*macroRole) {
262262
case MacroRole::Expression:
263263
case MacroRole::Declaration:
264+
case MacroRole::CodeItem:
264265
case MacroRole::Accessor:
265266
case MacroRole::MemberAttribute:
266267
case MacroRole::Conformance:

lib/AST/ASTWalker.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,9 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
442442
}
443443

444444
bool visitMacroExpansionDecl(MacroExpansionDecl *MED) {
445+
#ifndef NDEBUG
446+
PrettyStackTraceDecl debugStack("walking into", MED);
447+
#endif
445448
bool shouldWalkArguments, shouldWalkExpansion;
446449
std::tie(shouldWalkArguments, shouldWalkExpansion) =
447450
Walker.shouldWalkMacroArgumentsAndExpansion();
@@ -1341,6 +1344,14 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
13411344
std::tie(shouldWalkArguments, shouldWalkExpansion) =
13421345
Walker.shouldWalkMacroArgumentsAndExpansion();
13431346

1347+
if (auto *substituteDecl = E->getSubstituteDecl()) {
1348+
if (doIt(substituteDecl))
1349+
return nullptr;
1350+
// Visiting the substitute macro expansion decl will visit the same
1351+
// argument list. Skip visiting it again.
1352+
shouldWalkArguments = false;
1353+
}
1354+
13441355
if (shouldWalkArguments && E->getArgs()) {
13451356
ArgumentList *args = doIt(E->getArgs());
13461357
if (!args) return nullptr;

lib/AST/Decl.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10069,6 +10069,9 @@ StringRef swift::getMacroRoleString(MacroRole role) {
1006910069

1007010070
case MacroRole::Conformance:
1007110071
return "conformance";
10072+
10073+
case MacroRole::CodeItem:
10074+
return "codeItem";
1007210075
}
1007310076
}
1007410077

@@ -10110,7 +10113,8 @@ StringRef swift::getMacroIntroducedDeclNameString(
1011010113
static MacroRoles freestandingMacroRoles =
1011110114
(MacroRoles() |
1011210115
MacroRole::Expression |
10113-
MacroRole::Declaration);
10116+
MacroRole::Declaration |
10117+
MacroRole::CodeItem);
1011410118
static MacroRoles attachedMacroRoles = (MacroRoles() |
1011510119
MacroRole::Accessor |
1011610120
MacroRole::MemberAttribute |
@@ -10316,6 +10320,7 @@ void MacroDecl::getIntroducedNames(MacroRole role, ValueDecl *attachedTo,
1031610320
case MacroRole::Declaration:
1031710321
case MacroRole::Member:
1031810322
case MacroRole::Peer:
10323+
case MacroRole::CodeItem:
1031910324
names.push_back(MacroDecl::getUniqueNamePlaceholder(getASTContext()));
1032010325
break;
1032110326

lib/ASTGen/Sources/ASTGen/Macros.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,21 @@ func expandFreestandingMacroInProcess(
606606
evaluatedSyntax = Syntax(CodeBlockItemListSyntax(
607607
decls.map { CodeBlockItemSyntax(item: .decl($0)) }))
608608

609+
case let codeItemMacro as CodeItemMacro.Type:
610+
func expandCodeItemMacro<Node: FreestandingMacroExpansionSyntax>(
611+
_ node: Node
612+
) throws -> [CodeBlockItemSyntax] {
613+
return try codeItemMacro.expansion(
614+
of: sourceManager.detach(
615+
node,
616+
foldingWith: OperatorTable.standardOperators
617+
),
618+
in: context
619+
)
620+
}
621+
let items = try _openExistential(parentExpansion, do: expandCodeItemMacro)
622+
evaluatedSyntax = Syntax(CodeBlockItemListSyntax(items))
623+
609624
default:
610625
print("not an expression macro or a declaration macro")
611626
return nil

0 commit comments

Comments
 (0)