Skip to content

Commit 16f81fb

Browse files
committed
Introduce a Macro AST type and use it to describe the macros we find
1 parent b841523 commit 16f81fb

File tree

8 files changed

+292
-104
lines changed

8 files changed

+292
-104
lines changed

include/swift/AST/Macro.h

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
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+
/// Documentation for the macro.
63+
const StringRef documentation;
64+
65+
/// The module with which this macro is associated.
66+
ModuleDecl * const owningModule;
67+
68+
/// Supplemental modules that should be imported when
69+
const ArrayRef<ModuleDecl *> supplementalSignatureModules;
70+
71+
/// An opaque handle to the representation of the macro.
72+
void * const opaqueHandle;
73+
74+
public:
75+
Macro(
76+
Kind kind, ImplementationKind implementationKind, Identifier name,
77+
GenericSignature genericSignature, Type signature,
78+
StringRef documentation, ModuleDecl *owningModule,
79+
ArrayRef<ModuleDecl *> supplementalSignatureModules,
80+
void *opaqueHandle
81+
) : kind(kind), implementationKind(implementationKind), name(name),
82+
genericSignature(genericSignature), signature(signature),
83+
documentation(documentation), owningModule(owningModule),
84+
supplementalSignatureModules(supplementalSignatureModules),
85+
opaqueHandle(opaqueHandle) { }
86+
87+
/// Whether this is a "function-like" macro, meaning that it's expected
88+
/// to have function call arguments.
89+
bool isFunctionLike() const;
90+
};
91+
}
92+
93+
#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/ASTGen/Sources/ASTGen/Macros.swift

Lines changed: 24 additions & 8 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

@@ -104,20 +105,35 @@ extension ExportedMacro {
104105
}
105106
}
106107

107-
/// Query the macro evaluation context of the given macro.
108+
/// Query the macro evaluation context given the evaluation
109+
/// context sources.
108110
@_cdecl("swift_ASTGen_getMacroEvaluationContext")
109111
public func getMacroEvaluationContext(
110112
sourceFilePtr: UnsafePointer<UInt8>,
111113
declContext: UnsafeMutableRawPointer,
112114
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
115+
evaluatedSourceBuffer: UnsafePointer<UInt8>,
116+
evaluatedSourceBufferLength: Int
117+
) -> UnsafeMutableRawPointer? {
118+
let evaluatedSource = UnsafeBufferPointer(
119+
start: evaluatedSourceBuffer,
120+
count: evaluatedSourceBufferLength
121+
)
122+
let sourceFile = Parser.parse(source: evaluatedSource)
123+
124+
// Dig out the top-level struct declaration. That's all we'll
125+
// parse.
126+
guard let structDecl = sourceFile.statements.first(
127+
where: { item in item.item.is(StructDeclSyntax.self)
128+
})?.item.as(StructDeclSyntax.self) else {
129+
return nil
120130
}
131+
132+
// Parse and ASTGen that top-level declaration.
133+
// FIXME: we need to emit diagnostics from this.
134+
return ASTGenVisitor(
135+
ctx: context, base: sourceFilePtr, declContext: declContext
136+
).visit(structDecl).rawValue
121137
}
122138

123139
@_cdecl("swift_ASTGen_evaluateMacro")

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)

lib/Sema/ConstraintSystem.cpp

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "TypeChecker.h"
2525
#include "swift/AST/GenericEnvironment.h"
2626
#include "swift/AST/Initializer.h"
27+
#include "swift/AST/Macro.h"
2728
#include "swift/AST/ParameterList.h"
2829
#include "swift/AST/ProtocolConformance.h"
2930
#include "swift/AST/TypeCheckRequests.h"
@@ -2472,25 +2473,22 @@ ConstraintSystem::getTypeOfMemberReference(
24722473
}
24732474

24742475
#if SWIFT_SWIFT_PARSER
2475-
Type ConstraintSystem::getTypeOfMacroReference(StringRef macroName,
2476+
Type ConstraintSystem::getTypeOfMacroReference(Identifier macroName,
24762477
Expr *anchor) {
2477-
auto req = MacroContextRequest{macroName.str(), DC->getParentModule()};
2478-
auto *macroCtx = evaluateOrDefault(getASTContext().evaluator, req, nullptr);
2479-
if (!macroCtx)
2478+
auto req = MacroLookupRequest{macroName, DC->getParentModule()};
2479+
auto macros = evaluateOrDefault(getASTContext().evaluator, req, { });
2480+
if (macros.empty())
24802481
return Type();
24812482

2482-
auto *locator = getConstraintLocator(anchor);
2483-
// Dig through to __MacroEvaluationContext.SignatureType
2484-
auto sig = getASTContext().getIdentifier("SignatureType");
2485-
auto *signature = cast<TypeAliasDecl>(macroCtx->lookupDirect(sig).front());
2486-
auto type = signature->getUnderlyingType();
2483+
// FIXME: Handle macro overloading.
2484+
auto macro = macros.front();
24872485

24882486
// Open any the generic types.
24892487
OpenedTypeMap replacements;
2490-
openGeneric(signature->getParent(), signature->getGenericSignature(),
2491-
locator, replacements);
2488+
openGeneric(macro->owningModule, macro->genericSignature,
2489+
getConstraintLocator(anchor), replacements);
24922490

2493-
return openType(type, replacements);
2491+
return openType(macro->signature, replacements);
24942492
}
24952493
#endif
24962494

0 commit comments

Comments
 (0)