Skip to content

Commit 7000969

Browse files
committed
Introduce and use #externalMacro for externally-defined macros.
Align the grammar of macro declarations with SE-0382, so that macro definitions are parsed as an expression. External macro definitions are referenced via a referenced to the macro `#externalMacro`. Define that macro in the standard library, and recognize uses of it as the definition of other macros to use externally-defined macros. For example, this means that the "stringify" macro used in a lot of examples is now defined as something like this: @expression macro stringify<T>(_ value: T) -> (T, String) = #externalMacro(module: "MyMacros", type: "StringifyMacro") We still parse the old "A.B" syntax for two reasons. First, it's helpful to anyone who has existing code using the prior syntax, so they get a warning + Fix-It to rewrite to the new syntax. Second, we use it to define builtin macros like `externalMacro` itself, which looks like this: @expression public macro externalMacro<T>(module: String, type: String) -> T = Builtin.ExternalMacro This uses the same virtual `Builtin` module as other library builtins, and we can expand it to handle other builtin macro implementations (such as #line) over time.
1 parent 49b42b4 commit 7000969

24 files changed

+486
-166
lines changed

include/swift/AST/Decl.h

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ namespace swift {
6060
struct ASTNode;
6161
class ASTPrinter;
6262
class ASTWalker;
63+
enum class BuiltinMacroKind: uint8_t;
6364
class ConstructorDecl;
6465
class DestructorDecl;
6566
class DiagnosticEngine;
@@ -79,6 +80,7 @@ namespace swift {
7980
class GenericSignature;
8081
class GenericTypeParamDecl;
8182
class GenericTypeParamType;
83+
class MacroDefinition;
8284
class ModuleDecl;
8385
class NamedPattern;
8486
class EnumCaseDecl;
@@ -8344,27 +8346,16 @@ class MacroDecl : public GenericContext, public ValueDecl {
83448346
/// The result type.
83458347
TypeLoc resultType;
83468348

8347-
/// The module name for the external macro definition.
8348-
Identifier externalModuleName;
8349-
8350-
/// The location of the module name for the external macro definition.
8351-
SourceLoc externalModuleNameLoc;
8352-
8353-
/// The type name for the external macro definition.
8354-
Identifier externalMacroTypeName;
8355-
8356-
/// The location of the type name for the external macro definition.
8357-
SourceLoc externalMacroTypeNameLoc;
8349+
/// The macro definition, which should always be a
8350+
/// \c MacroExpansionExpr in well-formed code.
8351+
Expr *definition;
83588352

83598353
MacroDecl(SourceLoc macroLoc, DeclName name, SourceLoc nameLoc,
83608354
GenericParamList *genericParams,
83618355
ParameterList *parameterList,
83628356
SourceLoc arrowOrColonLoc,
83638357
TypeRepr *resultType,
8364-
Identifier externalModuleName,
8365-
SourceLoc externalModuleNameLoc,
8366-
Identifier externalMacroTypeName,
8367-
SourceLoc externalMacroTypeNameLoc,
8358+
Expr *definition,
83688359
DeclContext *parent);
83698360

83708361
SourceRange getSourceRange() const;
@@ -8375,6 +8366,13 @@ class MacroDecl : public GenericContext, public ValueDecl {
83758366
/// Determine the contexts in which this macro can be applied.
83768367
MacroContexts getMacroContexts() const;
83778368

8369+
/// Retrieve the definition of this macro.
8370+
MacroDefinition getDefinition() const;
8371+
8372+
/// Retrieve the builtin macro kind for this macro, or \c None if it is a
8373+
/// user-defined macro with no special semantics.
8374+
Optional<BuiltinMacroKind> getBuiltinKind() const;
8375+
83788376
static bool classof(const DeclContext *C) {
83798377
if (auto D = C->getAsDecl())
83808378
return classof(D);

include/swift/AST/DiagnosticsParse.def

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1996,14 +1996,8 @@ ERROR(expected_lparen_macro,PointsToFirstBadToken,
19961996
"expected '(' for macro parameters or ':' for a value-like macro", ())
19971997
ERROR(expected_type_macro_result,PointsToFirstBadToken,
19981998
"expected macro result type", ())
1999-
ERROR(macro_decl_expected_equal,PointsToFirstBadToken,
2000-
"expected '=' to introduce external macro name", ())
2001-
ERROR(macro_decl_expected_macro_module,PointsToFirstBadToken,
2002-
"expected external macro name", ())
2003-
ERROR(macro_decl_expected_period,PointsToFirstBadToken,
2004-
"expected '.' between external macro module and type name", ())
2005-
ERROR(macro_decl_expected_macro_type,PointsToFirstBadToken,
2006-
"expected external macro type name", ())
1999+
ERROR(macro_decl_expected_macro_definition,PointsToFirstBadToken,
2000+
"expected macro definition following '=''", ())
20072001

20082002
ERROR(macro_expansion_expr_expected_macro_identifier,PointsToFirstBadToken,
20092003
"expected a macro identifier for a pound literal expression", ())

include/swift/AST/DiagnosticsSema.def

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6801,6 +6801,18 @@ ERROR(macro_unsupported,none,
68016801
"macros are not supported in this compiler", ())
68026802
ERROR(macro_recursive,none,
68036803
"recursive expansion of macro %0", (DeclName))
6804+
WARNING(macro_definition_old_style,none,
6805+
"external macro definitions are now written using #externalMacro", ())
6806+
WARNING(macro_definition_unknown_builtin,none,
6807+
"ignoring definition of unknown builtin macro %0", (Identifier))
6808+
ERROR(macro_definition_not_expansion,none,
6809+
"macro must itself be defined by a macro expansion such as "
6810+
"'#externalMacro(...)'", ())
6811+
ERROR(macro_definition_unsupported,none,
6812+
"macro definitions other than '#externalMacro(...)' are unsupported", ())
6813+
ERROR(external_macro_arg_not_type_name,none,
6814+
"argument to `#externalMacro` must be a string literal naming "
6815+
"the external macro's %select{module|type}", (unsigned))
68046816

68056817
//------------------------------------------------------------------------------
68066818
// MARK: Move Only Errors

include/swift/AST/MacroDefinition.h

Lines changed: 67 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -22,64 +22,97 @@
2222

2323
namespace swift {
2424

25+
/// A reference to an external macro definition that is understood by ASTGen.
26+
struct ExternalMacroDefinition {
27+
/// ASTGen's notion of an macro definition, which is opaque to the C++ part
28+
/// of the compiler.
29+
void *opaqueHandle = nullptr;
30+
};
31+
32+
/// A reference to an external macro.
33+
struct ExternalMacroReference {
34+
Identifier moduleName;
35+
Identifier macroTypeName;
36+
};
37+
38+
/// Describes the known kinds of builtin macros.
39+
enum class BuiltinMacroKind: uint8_t {
40+
/// #externalMacro, which references an external macro.
41+
ExternalMacro,
42+
};
43+
2544
/// Provides the definition of a macro.
2645
class MacroDefinition {
2746
public:
28-
/// Describes a missing macro definition.
29-
struct MissingDefinition {
30-
Identifier externalModuleName;
31-
Identifier externalMacroTypeName;
32-
};
33-
3447
/// Describes how the macro is implemented.
35-
enum class ImplementationKind: uint8_t {
48+
enum class Kind: uint8_t {
49+
/// The macro has a definition, but it is invalid, so the macro cannot be
50+
/// expanded.
51+
Invalid,
52+
3653
/// The macro has no definition.
3754
Undefined,
3855

39-
/// The macro has a definition, but it could not be found.
40-
Missing,
56+
/// An externally-provided macro definition.
57+
External,
4158

42-
/// The macro is in the same process as the compiler, whether built-in or
43-
/// loaded via a compiler plugin.
44-
InProcess,
59+
/// A builtin macro definition, which has a separate builtin kind.
60+
Builtin,
4561
};
4662

47-
ImplementationKind implKind;
63+
Kind kind;
4864

4965
private:
50-
void *opaqueHandle;
66+
union Data {
67+
ExternalMacroReference external;
68+
BuiltinMacroKind builtin;
5169

52-
MacroDefinition(ImplementationKind implKind, void *opaqueHandle)
53-
: implKind(implKind), opaqueHandle(opaqueHandle) { }
70+
Data() : builtin(BuiltinMacroKind::ExternalMacro) { }
71+
} data;
72+
73+
MacroDefinition(Kind kind) : kind(kind) { }
74+
75+
MacroDefinition(ExternalMacroReference external) : kind(Kind::External) {
76+
data.external = external;
77+
}
78+
79+
MacroDefinition(BuiltinMacroKind builtinKind) : kind(Kind::Builtin) {
80+
data.builtin = builtinKind;
81+
}
5482

5583
public:
84+
static MacroDefinition forInvalid() {
85+
return MacroDefinition(Kind::Invalid);
86+
}
87+
5688
static MacroDefinition forUndefined() {
57-
return MacroDefinition{
58-
ImplementationKind::Undefined, nullptr
59-
};
89+
return MacroDefinition(Kind::Undefined);
6090
}
6191

62-
static MacroDefinition forMissing(
63-
ASTContext &ctx,
64-
Identifier externalModuleName,
65-
Identifier externalMacroTypeName
66-
);
92+
static MacroDefinition forExternal(
93+
Identifier moduleName,
94+
Identifier macroTypeName
95+
) {
96+
return MacroDefinition(ExternalMacroReference{moduleName, macroTypeName});
97+
}
6798

68-
static MacroDefinition forInProcess(void *opaqueHandle) {
69-
return MacroDefinition{ImplementationKind::InProcess, opaqueHandle};
99+
static MacroDefinition forBuiltin(BuiltinMacroKind builtinKind) {
100+
return MacroDefinition(builtinKind);
70101
}
71102

72-
/// Return the opaque handle for an in-process macro definition.
73-
void *getInProcessOpaqueHandle() const {
74-
assert(implKind == ImplementationKind::InProcess);
75-
return opaqueHandle;
103+
/// Retrieve the external macro being referenced.
104+
ExternalMacroReference getExternalMacro() const {
105+
assert(kind == Kind::External);
106+
return data.external;
76107
}
77108

78-
/// Return more information about a missing macro definition.
79-
MissingDefinition *getMissingDefinition() const {
80-
assert(implKind == ImplementationKind::Missing);
81-
return static_cast<MissingDefinition *>(opaqueHandle);
109+
/// Retrieve the builtin kind.
110+
BuiltinMacroKind getBuiltinKind() const {
111+
assert(kind == Kind::Builtin);
112+
return data.builtin;
82113
}
114+
115+
explicit operator bool() const { return kind != Kind::Invalid; }
83116
};
84117

85118
}

include/swift/AST/TypeCheckRequests.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class ContextualPattern;
4545
class ContinueStmt;
4646
class DefaultArgumentExpr;
4747
class DefaultArgumentType;
48+
struct ExternalMacroDefinition;
4849
class ClosureExpr;
4950
class GenericParamList;
5051
class LabeledStmt;
@@ -71,6 +72,8 @@ void simple_display(
7172
llvm::raw_ostream &out,
7273
const llvm::PointerUnion<const TypeDecl *, const ExtensionDecl *> &value);
7374

75+
void simple_display(llvm::raw_ostream &out, ASTContext *ctx);
76+
7477
/// Request the type from the ith entry in the inheritance clause for the
7578
/// given declaration.
7679
class InheritedTypeRequest
@@ -3796,6 +3799,30 @@ class MacroDefinitionRequest
37963799
bool isCached() const { return true; }
37973800
};
37983801

3802+
/// Resolve an external macro given its module and type name.
3803+
class ExternalMacroDefinitionRequest
3804+
: public SimpleRequest<ExternalMacroDefinitionRequest,
3805+
ExternalMacroDefinition(
3806+
ASTContext *, Identifier, Identifier),
3807+
RequestFlags::Cached> {
3808+
public:
3809+
using SimpleRequest::SimpleRequest;
3810+
3811+
private:
3812+
friend SimpleRequest;
3813+
3814+
ExternalMacroDefinition evaluate(
3815+
Evaluator &evaluator, ASTContext *ctx, Identifier moduleName,
3816+
Identifier typeName
3817+
) const;
3818+
3819+
public:
3820+
// Source location
3821+
SourceLoc getNearestLoc() const { return SourceLoc(); }
3822+
3823+
bool isCached() const { return true; }
3824+
};
3825+
37993826
class GetRuntimeDiscoverableAttributes
38003827
: public SimpleRequest<GetRuntimeDiscoverableAttributes,
38013828
ArrayRef<CustomAttr *>(ValueDecl *),

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,9 @@ SWIFT_REQUEST(TypeChecker, UsesTypeWrapperFeature,
449449
SWIFT_REQUEST(TypeChecker, MacroDefinitionRequest,
450450
MacroDefinition(MacroDecl *),
451451
Cached, NoLocationInfo)
452+
SWIFT_REQUEST(TypeChecker, ExternalMacroDefinitionRequest,
453+
ExternalMacroDefinition(ASTContext *, Identifier, Identifier),
454+
Cached, NoLocationInfo)
452455
SWIFT_REQUEST(TypeChecker, SynthesizeRuntimeMetadataAttrGenerator,
453456
Expr *(CustomAttr *, ValueDecl *),
454457
Cached, NoLocationInfo)

lib/AST/ASTPrinter.cpp

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
//
1515
//===----------------------------------------------------------------------===//
1616

17+
#include "InlinableText.h"
1718
#include "swift/AST/ASTPrinter.h"
1819
#include "swift/AST/ASTContext.h"
1920
#include "swift/AST/ASTMangler.h"
@@ -29,6 +30,7 @@
2930
#include "swift/AST/GenericEnvironment.h"
3031
#include "swift/AST/GenericParamList.h"
3132
#include "swift/AST/GenericSignature.h"
33+
#include "swift/AST/MacroDefinition.h"
3234
#include "swift/AST/Module.h"
3335
#include "swift/AST/NameLookup.h"
3436
#include "swift/AST/NameLookupRequests.h"
@@ -4541,8 +4543,36 @@ void PrintAST::visitMacroDecl(MacroDecl *decl) {
45414543
Printer.printStructurePost(PrintStructureKind::FunctionReturnType);
45424544
}
45434545

4544-
Printer << " = ";
4545-
Printer << decl->externalModuleName << "." << decl->externalMacroTypeName;
4546+
if (decl->definition) {
4547+
ASTContext &ctx = decl->getASTContext();
4548+
SmallString<64> scratch;
4549+
Printer << " = "
4550+
<< extractInlinableText(ctx.SourceMgr, decl->definition, scratch);
4551+
} else {
4552+
auto def = decl->getDefinition();
4553+
switch (def.kind) {
4554+
case MacroDefinition::Kind::Invalid:
4555+
case MacroDefinition::Kind::Undefined:
4556+
// Nothing to do.
4557+
break;
4558+
4559+
case MacroDefinition::Kind::External: {
4560+
auto external = def.getExternalMacro();
4561+
Printer << " = #externalMacro(module: \"" << external.moduleName << "\", "
4562+
<< "type: \"" << external.macroTypeName << "\")";
4563+
break;
4564+
}
4565+
4566+
case MacroDefinition::Kind::Builtin:
4567+
Printer << " = Builtin.";
4568+
switch (def.getBuiltinKind()) {
4569+
case BuiltinMacroKind::ExternalMacro:
4570+
Printer << "ExternalMacro";
4571+
break;
4572+
}
4573+
break;
4574+
}
4575+
}
45464576

45474577
printDeclGenericRequirements(decl);
45484578
}
@@ -7130,7 +7160,6 @@ swift::getInheritedForPrinting(
71307160
}
71317161

71327162
// Collect synthesized conformances.
7133-
auto &ctx = decl->getASTContext();
71347163
llvm::SetVector<ProtocolDecl *> protocols;
71357164
llvm::TinyPtrVector<ProtocolDecl *> uncheckedProtocols;
71367165
for (auto attr : decl->getAttrs().getAttributes<SynthesizedProtocolAttr>()) {

0 commit comments

Comments
 (0)