Skip to content

Commit baa1d49

Browse files
authored
Merge pull request #62071 from DougGregor/macro-ast
2 parents 98fa584 + 4b87cb7 commit baa1d49

File tree

13 files changed

+537
-109
lines changed

13 files changed

+537
-109
lines changed

include/swift/AST/CompilerPlugin.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ class CompilerPlugin {
5252
GenericSignature = 4,
5353
// static func _typeSignature(...) -> (UnsafePointer<UInt8>, count: Int)
5454
TypeSignature = 5,
55+
// static func _owningModule(...) -> (UnsafePointer<UInt8>, count: Int)
56+
OwningModule = 6,
57+
// static func _supplementalSignatureModules(...)
58+
// -> (UnsafePointer<UInt8>, count: Int)
59+
SupplementalSignatureModules = 7,
5560
};
5661

5762
/// The plugin type metadata.
@@ -100,6 +105,14 @@ class CompilerPlugin {
100105
/// result string buffer.
101106
StringRef invokeTypeSignature() const;
102107

108+
/// Invoke the `_owningModule` method. The caller assumes ownership of the
109+
/// result string buffer.
110+
StringRef invokeOwningModule() const;
111+
112+
/// Invoke the `_supplementalSignatureModules` method. The caller assumes
113+
/// ownership of the result string buffer.
114+
StringRef invokeSupplementalSignatureModules() const;
115+
103116
StringRef getName() const {
104117
return name;
105118
}

include/swift/AST/Macro.h

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
//===--- Macro.h - Swift Macro Definition -----------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file defines the `Macro` type that describes a macro definition.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#ifndef SWIFT_AST_MACRO_H
18+
#define SWIFT_AST_MACRO_H
19+
20+
#include "swift/AST/ASTAllocated.h"
21+
#include "swift/AST/GenericSignature.h"
22+
#include "swift/AST/Identifier.h"
23+
#include "swift/AST/Type.h"
24+
25+
namespace swift {
26+
class ModuleDecl;
27+
28+
class Macro : public ASTAllocated<Macro> {
29+
public:
30+
/// The kind of macro, which determines how it can be used in source code.
31+
enum Kind: uint8_t {
32+
/// An expression macro.
33+
Expression,
34+
};
35+
36+
/// Describes how the macro is implemented.
37+
enum class ImplementationKind: uint8_t {
38+
/// The macro is built-in to the compiler, linked against the same
39+
/// underlying syntax tree libraries.
40+
Builtin,
41+
42+
/// The macro was defined in a compiler plugin.
43+
Plugin,
44+
};
45+
46+
/// The kind of macro.
47+
const Kind kind;
48+
49+
/// How the macro is implemented.
50+
const ImplementationKind implementationKind;
51+
52+
/// The name of the macro in the source, e.g., "stringify".
53+
const Identifier name;
54+
55+
/// The generic signature, used to describe the signature of macros that
56+
/// involve generic parameters.
57+
const GenericSignature genericSignature;
58+
59+
/// The type signature of the macro.
60+
const Type signature;
61+
62+
/// The module with which this macro is associated.
63+
ModuleDecl * const owningModule;
64+
65+
/// Supplemental modules that should be imported when
66+
const ArrayRef<ModuleDecl *> supplementalSignatureModules;
67+
68+
/// An opaque handle to the representation of the macro.
69+
void * const opaqueHandle;
70+
71+
public:
72+
Macro(
73+
Kind kind, ImplementationKind implementationKind, Identifier name,
74+
GenericSignature genericSignature, Type signature,
75+
ModuleDecl *owningModule,
76+
ArrayRef<ModuleDecl *> supplementalSignatureModules,
77+
void *opaqueHandle
78+
) : kind(kind), implementationKind(implementationKind), name(name),
79+
genericSignature(genericSignature), signature(signature),
80+
owningModule(owningModule),
81+
supplementalSignatureModules(supplementalSignatureModules),
82+
opaqueHandle(opaqueHandle) { }
83+
};
84+
}
85+
86+
#endif // SWIFT_AST_MACRO_H

include/swift/AST/TypeCheckRequests.h

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class DefaultArgumentExpr;
4545
class DefaultArgumentType;
4646
class ClosureExpr;
4747
class GenericParamList;
48+
class Macro;
4849
class PrecedenceGroupDecl;
4950
class PropertyWrapperInitializerInfo;
5051
struct PropertyWrapperLValueness;
@@ -3733,35 +3734,20 @@ class SynthesizeHasSymbolQueryRequest
37333734
bool isCached() const { return true; }
37343735
};
37353736

3736-
3737-
/// Retrieves the evaluation context of a macro with the given name.
3738-
///
3739-
/// The macro evaluation context is a user-defined generic signature and return
3740-
/// type that serves as the "interface type" of references to the macro. The
3741-
/// current implementation takes those pieces of syntax from the macro itself,
3742-
/// then inserts them into a Swift struct that looks like
3743-
///
3744-
/// \code
3745-
/// struct __MacroEvaluationContext\(macro.genericSignature) {
3746-
/// typealias SignatureType = \(macro.signature)
3747-
/// }
3748-
/// \endcode
3749-
///
3750-
/// So that we can use all of Swift's native name lookup and type resolution
3751-
/// facilities to map the parsed signature type back into a semantic \c Type
3752-
/// AST and a set of requiremnets.
3753-
class MacroContextRequest
3754-
: public SimpleRequest<MacroContextRequest,
3755-
StructDecl *(std::string, ModuleDecl *),
3737+
/// Lookup all macros with the given name that are visible from the given
3738+
/// module.
3739+
class MacroLookupRequest
3740+
: public SimpleRequest<MacroLookupRequest,
3741+
ArrayRef<Macro *>(Identifier, ModuleDecl *),
37563742
RequestFlags::Cached> {
37573743
public:
37583744
using SimpleRequest::SimpleRequest;
37593745

37603746
private:
37613747
friend SimpleRequest;
37623748

3763-
StructDecl *evaluate(Evaluator &evaluator,
3764-
std::string macroName, ModuleDecl *mod) const;
3749+
ArrayRef<Macro *> evaluate(Evaluator &evaluator,
3750+
Identifier macroName, ModuleDecl *mod) const;
37653751

37663752
public:
37673753
bool isCached() const { return true; }
@@ -3772,6 +3758,7 @@ void simple_display(llvm::raw_ostream &out, Type value);
37723758
void simple_display(llvm::raw_ostream &out, const TypeRepr *TyR);
37733759
void simple_display(llvm::raw_ostream &out, ImplicitMemberAction action);
37743760
void simple_display(llvm::raw_ostream &out, ResultBuilderBodyPreCheck pck);
3761+
void simple_display(llvm::raw_ostream &out, const Macro *macro);
37753762

37763763
#define SWIFT_TYPEID_ZONE TypeChecker
37773764
#define SWIFT_TYPEID_HEADER "swift/AST/TypeCheckerTypeIDZone.def"

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,6 @@ SWIFT_REQUEST(TypeChecker, GetTypeWrapperInitializer,
440440
SWIFT_REQUEST(TypeChecker, SynthesizeHasSymbolQueryRequest,
441441
FuncDecl *(ValueDecl *),
442442
Cached, NoLocationInfo)
443-
SWIFT_REQUEST(TypeChecker, MacroContextRequest,
444-
StructDecl *(std::string, ModuleDecl *),
443+
SWIFT_REQUEST(TypeChecker, MacroLookupRequest,
444+
ArrayRef<Macro *>(Identifier, ModuleDecl *),
445445
Cached, NoLocationInfo)

include/swift/Sema/ConstraintSystem.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4911,7 +4911,7 @@ class ConstraintSystem {
49114911
///
49124912
/// \returns The opened type of the macro with this name, or the null \c Type
49134913
/// if no such macro exists.
4914-
Type getTypeOfMacroReference(StringRef macro, Expr *anchor);
4914+
Type getTypeOfMacroReference(Identifier macroName, Expr *anchor);
49154915
#endif
49164916

49174917
/// Retrieve a list of generic parameter types solver has "opened" (replaced

lib/AST/CompilerPlugin.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,3 +319,27 @@ StringRef CompilerPlugin::invokeTypeSignature() const {
319319
llvm_unreachable("Incompatible host compiler");
320320
#endif
321321
}
322+
323+
StringRef CompilerPlugin::invokeOwningModule() const {
324+
#if __clang__
325+
using Method = SWIFT_CC CharBuffer(
326+
SWIFT_CONTEXT const void *, const void *, const void *);
327+
auto method = getWitnessMethodUnsafe<Method>(
328+
WitnessTableEntry::OwningModule);
329+
return method(metadata, metadata, witnessTable).str();
330+
#else
331+
llvm_unreachable("Incompatible host compiler");
332+
#endif
333+
}
334+
335+
StringRef CompilerPlugin::invokeSupplementalSignatureModules() const {
336+
#if __clang__
337+
using Method = SWIFT_CC CharBuffer(
338+
SWIFT_CONTEXT const void *, const void *, const void *);
339+
auto method = getWitnessMethodUnsafe<Method>(
340+
WitnessTableEntry::SupplementalSignatureModules);
341+
return method(metadata, metadata, witnessTable).str();
342+
#else
343+
llvm_unreachable("Incompatible host compiler");
344+
#endif
345+
}

lib/ASTGen/Sources/ASTGen/Macros.swift

Lines changed: 84 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import SwiftParser
12
import SwiftSyntax
23
@_spi(Testing) import _SwiftSyntaxMacros
34

@@ -81,43 +82,107 @@ private func allocateUTF8String(
8182
}
8283
}
8384

85+
@_cdecl("swift_ASTGen_getMacroGenericSignature")
86+
public func getMacroGenericSignature(
87+
macroPtr: UnsafeMutablePointer<UInt8>,
88+
genericSignaturePtr: UnsafeMutablePointer<UnsafePointer<UInt8>?>,
89+
genericSignatureLengthPtr: UnsafeMutablePointer<Int>
90+
) {
91+
macroPtr.withMemoryRebound(to: ExportedMacro.self, capacity: 1) { macro in
92+
guard let genericSig = macro.pointee.macro.genericSignature else {
93+
(genericSignaturePtr.pointee, genericSignatureLengthPtr.pointee) = (nil, 0)
94+
return
95+
}
96+
97+
(genericSignaturePtr.pointee, genericSignatureLengthPtr.pointee) =
98+
allocateUTF8String(genericSig.description)
99+
}
100+
}
101+
84102
/// Query the type signature of the given macro.
85103
@_cdecl("swift_ASTGen_getMacroTypeSignature")
86104
public func getMacroTypeSignature(
87105
macroPtr: UnsafeMutablePointer<UInt8>,
88-
evaluationContextPtr: UnsafeMutablePointer<UnsafePointer<UInt8>?>,
89-
evaluationContextLengthPtr: UnsafeMutablePointer<Int>
106+
signaturePtr: UnsafeMutablePointer<UnsafePointer<UInt8>?>,
107+
signatureLengthPtr: UnsafeMutablePointer<Int>
90108
) {
91109
macroPtr.withMemoryRebound(to: ExportedMacro.self, capacity: 1) { macro in
92-
(evaluationContextPtr.pointee, evaluationContextLengthPtr.pointee) =
93-
allocateUTF8String(macro.pointee.evaluationContext, nullTerminated: true)
110+
(signaturePtr.pointee, signatureLengthPtr.pointee) =
111+
allocateUTF8String(macro.pointee.macro.signature.description)
94112
}
95113
}
96114

97-
extension ExportedMacro {
98-
var evaluationContext: String {
99-
"""
100-
struct __MacroEvaluationContext\(self.macro.genericSignature?.description ?? "") {
101-
typealias SignatureType = \(self.macro.signature)
102-
}
103-
"""
115+
/// Query the documentation of the given macro.
116+
@_cdecl("swift_ASTGen_getMacroDocumentation")
117+
public func getMacroDocumentation(
118+
macroPtr: UnsafeMutablePointer<UInt8>,
119+
documentationPtr: UnsafeMutablePointer<UnsafePointer<UInt8>?>,
120+
documentationLengthPtr: UnsafeMutablePointer<Int>
121+
) {
122+
macroPtr.withMemoryRebound(to: ExportedMacro.self, capacity: 1) { macro in
123+
(documentationPtr.pointee, documentationLengthPtr.pointee) =
124+
allocateUTF8String(macro.pointee.macro.documentation)
104125
}
105126
}
106127

107-
/// Query the macro evaluation context of the given macro.
128+
/// Query the owning module of the given macro.
129+
@_cdecl("swift_ASTGen_getMacroOwningModule")
130+
public func getMacroOwningModule(
131+
macroPtr: UnsafeMutablePointer<UInt8>,
132+
owningModulePtr: UnsafeMutablePointer<UnsafePointer<UInt8>?>,
133+
owningModuleLengthPtr: UnsafeMutablePointer<Int>
134+
) {
135+
macroPtr.withMemoryRebound(to: ExportedMacro.self, capacity: 1) { macro in
136+
(owningModulePtr.pointee, owningModuleLengthPtr.pointee) =
137+
allocateUTF8String(macro.pointee.macro.owningModule)
138+
}
139+
}
140+
141+
/// Query the supplemental signature modules of the given macro,
142+
/// as a semicolon-separated string
143+
@_cdecl("swift_ASTGen_getMacroSupplementalSignatureModules")
144+
public func getMacroSupplementableSignatureModules(
145+
macroPtr: UnsafeMutablePointer<UInt8>,
146+
modulesPtr: UnsafeMutablePointer<UnsafePointer<UInt8>?>,
147+
modulesLengthPtr: UnsafeMutablePointer<Int>
148+
) {
149+
macroPtr.withMemoryRebound(to: ExportedMacro.self, capacity: 1) { macro in
150+
let modules = macro.pointee.macro.supplementalSignatureModules
151+
.joined(separator: ";")
152+
(modulesPtr.pointee, modulesLengthPtr.pointee) =
153+
allocateUTF8String(modules)
154+
}
155+
}
156+
157+
/// Query the macro evaluation context given the evaluation
158+
/// context sources.
108159
@_cdecl("swift_ASTGen_getMacroEvaluationContext")
109160
public func getMacroEvaluationContext(
110161
sourceFilePtr: UnsafePointer<UInt8>,
111162
declContext: UnsafeMutableRawPointer,
112163
context: UnsafeMutableRawPointer,
113-
macroPtr: UnsafeMutablePointer<UInt8>,
114-
contextPtr: UnsafeMutablePointer<UnsafeMutableRawPointer?>
115-
) {
116-
contextPtr.pointee = macroPtr.withMemoryRebound(to: ExportedMacro.self, capacity: 1) { macro in
117-
return ASTGenVisitor(ctx: context, base: sourceFilePtr, declContext: declContext)
118-
.visit(StructDeclSyntax(stringLiteral: macro.pointee.evaluationContext))
119-
.rawValue
164+
evaluatedSourceBuffer: UnsafePointer<UInt8>,
165+
evaluatedSourceBufferLength: Int
166+
) -> UnsafeMutableRawPointer? {
167+
let evaluatedSource = UnsafeBufferPointer(
168+
start: evaluatedSourceBuffer,
169+
count: evaluatedSourceBufferLength
170+
)
171+
let sourceFile = Parser.parse(source: evaluatedSource)
172+
173+
// Dig out the top-level typealias declaration. That's all we'll
174+
// parse.
175+
guard let typealiasDecl = sourceFile.statements.first(
176+
where: { item in item.item.is(TypealiasDeclSyntax.self)
177+
})?.item.as(TypealiasDeclSyntax.self) else {
178+
return nil
120179
}
180+
181+
// Parse and ASTGen that top-level declaration.
182+
// FIXME: we need to emit diagnostics from this.
183+
return ASTGenVisitor(
184+
ctx: context, base: sourceFilePtr, declContext: declContext
185+
).visit(typealiasDecl).rawValue
121186
}
122187

123188
@_cdecl("swift_ASTGen_evaluateMacro")

lib/CompilerPluginSupport/CompilerPluginSupport.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,20 @@ public protocol _CompilerPlugin {
6969
/// - Returns: A newly allocated buffer containing the type signature. The
7070
/// caller is responsible for managing the memory.
7171
static func _typeSignature() -> (UnsafePointer<UInt8>, count: Int)
72+
73+
74+
/// Returns the module that owns this macro.
75+
///
76+
/// - Returns: A newly allocated buffer containing the owning module name. The
77+
/// caller is responsible for managing the memory.
78+
static func _owningModule() -> (UnsafePointer<UInt8>, count: Int)
79+
80+
/// Returns the set of modules that are needed (beyond the owning module) to
81+
/// process the module signature.
82+
///
83+
/// - Returns: A newly allocated buffer containing a string with all of the
84+
/// supplemental signature module names, separated by semicolons. The caller
85+
/// is responsible for managing the memory.
86+
static func _supplementalSignatureModules()
87+
-> (UnsafePointer<UInt8>, count: Int)
7288
}

lib/Sema/CSGen.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1200,7 +1200,8 @@ namespace {
12001200
if (!protocol)
12011201
return Type();
12021202

1203-
auto openedType = CS.getTypeOfMacroReference(kind, expr);
1203+
auto openedType = CS.getTypeOfMacroReference(
1204+
ctx.getIdentifier(kind), expr);
12041205
if (!openedType)
12051206
return Type();
12061207

@@ -3633,7 +3634,7 @@ namespace {
36333634
auto &ctx = CS.getASTContext();
36343635
if (ctx.LangOpts.hasFeature(Feature::Macros)) {
36353636
auto macroIdent = expr->getMacroName().getBaseIdentifier();
3636-
auto refType = CS.getTypeOfMacroReference(macroIdent.str(), expr);
3637+
auto refType = CS.getTypeOfMacroReference(macroIdent, expr);
36373638
if (!refType) {
36383639
ctx.Diags.diagnose(expr->getMacroNameLoc(), diag::macro_undefined,
36393640
macroIdent)

0 commit comments

Comments
 (0)