Skip to content

Commit c5ccf11

Browse files
authored
Merge pull request #66033 from DougGregor/parse-types-via-astgen
[ASTGen] Add experimental feature to use ASTGen in lieu of parsing types
2 parents 90fd254 + 7224b81 commit c5ccf11

File tree

10 files changed

+481
-20
lines changed

10 files changed

+481
-20
lines changed

include/swift/AST/CASTBridging.h

+79-1
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,70 @@ typedef enum ENUM_EXTENSIBILITY_ATTR(open) BridgedMacroDefinitionKind : long {
112112
BridgedBuiltinExternalMacro
113113
} BridgedMacroDefinitionKind;
114114

115+
/// Bridged parameter specifiers
116+
typedef enum ENUM_EXTENSIBILITY_ATTR(open) BridgedAttributedTypeSpecifier : long {
117+
BridgedAttributedTypeSpecifierInOut,
118+
BridgedAttributedTypeSpecifierBorrowing,
119+
BridgedAttributedTypeSpecifierConsuming,
120+
BridgedAttributedTypeSpecifierLegacyShared,
121+
BridgedAttributedTypeSpecifierLegacyOwned,
122+
BridgedAttributedTypeSpecifierConst,
123+
BridgedAttributedTypeSpecifierIsolated,
124+
} BridgedAttributedTypeSpecifier;
125+
126+
127+
// Bridged type attribute kinds, which mirror TypeAttrKind exactly.
128+
typedef enum ENUM_EXTENSIBILITY_ATTR(closed) BridgedTypeAttrKind : long {
129+
BridgedTypeAttrKind_autoclosure,
130+
BridgedTypeAttrKind_convention,
131+
BridgedTypeAttrKind_noescape,
132+
BridgedTypeAttrKind_escaping,
133+
BridgedTypeAttrKind_differentiable,
134+
BridgedTypeAttrKind_noDerivative,
135+
BridgedTypeAttrKind_async,
136+
BridgedTypeAttrKind_Sendable,
137+
BridgedTypeAttrKind_unchecked,
138+
BridgedTypeAttrKind__local,
139+
BridgedTypeAttrKind__noMetadata,
140+
BridgedTypeAttrKind__opaqueReturnTypeOf,
141+
BridgedTypeAttrKind_block_storage,
142+
BridgedTypeAttrKind_box,
143+
BridgedTypeAttrKind_dynamic_self,
144+
BridgedTypeAttrKind_sil_weak,
145+
BridgedTypeAttrKind_sil_unowned,
146+
BridgedTypeAttrKind_sil_unmanaged,
147+
BridgedTypeAttrKind_error,
148+
BridgedTypeAttrKind_out,
149+
BridgedTypeAttrKind_direct,
150+
BridgedTypeAttrKind_in,
151+
BridgedTypeAttrKind_inout,
152+
BridgedTypeAttrKind_inout_aliasable,
153+
BridgedTypeAttrKind_in_guaranteed,
154+
BridgedTypeAttrKind_in_constant,
155+
BridgedTypeAttrKind_pack_owned,
156+
BridgedTypeAttrKind_pack_guaranteed,
157+
BridgedTypeAttrKind_pack_inout,
158+
BridgedTypeAttrKind_pack_out,
159+
BridgedTypeAttrKind_owned,
160+
BridgedTypeAttrKind_unowned_inner_pointer,
161+
BridgedTypeAttrKind_guaranteed,
162+
BridgedTypeAttrKind_autoreleased,
163+
BridgedTypeAttrKind_callee_owned,
164+
BridgedTypeAttrKind_callee_guaranteed,
165+
BridgedTypeAttrKind_objc_metatype,
166+
BridgedTypeAttrKind_opened,
167+
BridgedTypeAttrKind_pack_element,
168+
BridgedTypeAttrKind_pseudogeneric,
169+
BridgedTypeAttrKind_yields,
170+
BridgedTypeAttrKind_yield_once,
171+
BridgedTypeAttrKind_yield_many,
172+
BridgedTypeAttrKind_captures_generics,
173+
BridgedTypeAttrKind_moveOnly,
174+
BridgedTypeAttrKind_thin,
175+
BridgedTypeAttrKind_thick,
176+
BridgedTypeAttrKind_Count
177+
} BridgedTypeAttrKind;
178+
115179
#ifdef __cplusplus
116180
extern "C" {
117181

@@ -261,6 +325,19 @@ void *ImplicitlyUnwrappedOptionalTypeRepr_create(void *ctx, void *base,
261325
void *exclamationLoc);
262326
void *MetatypeTypeRepr_create(void *ctx, void *baseType, void *typeLoc);
263327
void *ProtocolTypeRepr_create(void *ctx, void *baseType, void *protoLoc);
328+
329+
BridgedTypeAttrKind getBridgedTypeAttrKindFromString(
330+
const unsigned char * _Nullable str, long len);
331+
332+
typedef void *BridgedTypeAttributes;
333+
BridgedTypeAttributes BridgedTypeAttributes_create(void);
334+
void BridgedTypeAttributes_addSimpleAttr(
335+
BridgedTypeAttributes typeAttributes, BridgedTypeAttrKind kind, void *atLoc, void *attrLoc);
336+
void *AttributedTypeRepr_create(void *ctx, void *base, BridgedTypeAttributes typeAttributes);
337+
338+
void *AttributedTypeSpecifierRepr_create(
339+
void *ctx, void *base, BridgedAttributedTypeSpecifier specifier, void *specifierLoc);
340+
void *VarargTypeRepr_create(void *ctx, void *base, void *ellipsisLocPtr);
264341
void *PackExpansionTypeRepr_create(void *ctx, void *base, void *repeatLoc);
265342
void *TupleTypeRepr_create(void *ctx, BridgedArrayRef elements, void *lParenLoc,
266343
void *rParenLoc);
@@ -269,8 +346,9 @@ void *MemberTypeRepr_create(void *ctx, void *baseComponent,
269346
void *GenericIdentTypeRepr_create(void *ctx, BridgedIdentifier name,
270347
void *nameLoc, BridgedArrayRef genericArgs,
271348
void *lAngle, void *rAngle);
349+
void *EmptyCompositionTypeRepr_create(void *ctx, void *anyLoc);
272350
void *CompositionTypeRepr_create(void *ctx, BridgedArrayRef types,
273-
void *firstTypeLoc);
351+
void *firstTypeLoc, void *firstAmpLoc);
274352
void *FunctionTypeRepr_create(void *ctx, void *argsTy, void *_Nullable asyncLoc,
275353
void *_Nullable throwsLoc, void *arrowLoc,
276354
void *returnType);

include/swift/Basic/Features.def

+4
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,10 @@ EXPERIMENTAL_FEATURE(ImplicitSome, false)
179179
/// corresponding syntax tree.
180180
EXPERIMENTAL_FEATURE(ParserASTGen, false)
181181

182+
/// Use the syntax tree produced by the Swift (swift-syntax) parser for type
183+
/// parsing, using ASTGen to translate them into AST nodes.
184+
EXPERIMENTAL_FEATURE(ASTGenTypes, false)
185+
182186
/// Parse using the Swift (swift-syntax) parser and use ASTGen to generate the
183187
/// corresponding syntax tree.
184188
EXPERIMENTAL_FEATURE(BuiltinMacros, false)

include/swift/Parse/Parser.h

+45
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "swift/AST/LayoutConstraint.h"
2525
#include "swift/AST/ParseRequests.h"
2626
#include "swift/AST/Pattern.h"
27+
#include "swift/AST/SourceFile.h"
2728
#include "swift/AST/Stmt.h"
2829
#include "swift/Basic/OptionSet.h"
2930
#include "swift/Config.h"
@@ -1330,6 +1331,50 @@ class Parser {
13301331
/// Get the location for a type error.
13311332
SourceLoc getTypeErrorLoc() const;
13321333

1334+
/// Callback function used for creating a C++ AST from the syntax node at the given source location.
1335+
///
1336+
/// The arguments to this callback are the source file to pass into ASTGen (the exported source file)
1337+
/// and the source location pointer to pass into ASTGen (to find the syntax node).
1338+
///
1339+
/// The callback returns the new AST node and the ending location of the syntax node. If the AST node
1340+
/// is NULL, something went wrong.
1341+
template<typename T>
1342+
using ASTFromSyntaxTreeCallback = std::pair<T*, const void *>(
1343+
void *sourceFile, const void *sourceLoc
1344+
);
1345+
1346+
/// Parse by constructing a C++ AST node from the Swift syntax tree via ASTGen.
1347+
template<typename T>
1348+
ParserResult<T> parseASTFromSyntaxTree(
1349+
llvm::function_ref<ASTFromSyntaxTreeCallback<T>> body
1350+
) {
1351+
if (!Context.LangOpts.hasFeature(Feature::ASTGenTypes))
1352+
return nullptr;
1353+
1354+
auto exportedSourceFile = SF.getExportedSourceFile();
1355+
if (!exportedSourceFile)
1356+
return nullptr;
1357+
1358+
// Perform the translation.
1359+
auto sourceLoc = Tok.getLoc().getOpaquePointerValue();
1360+
T* astNode;
1361+
const void *endLocPtr;
1362+
std::tie(astNode, endLocPtr) = body(exportedSourceFile, sourceLoc);
1363+
1364+
if (!astNode) {
1365+
assert(false && "Could not build AST node from syntax tree");
1366+
return nullptr;
1367+
}
1368+
1369+
// Reset the lexer to the ending location.
1370+
StringRef contents =
1371+
SourceMgr.extractText(SourceMgr.getRangeForBuffer(L->getBufferID()));
1372+
L->resetToOffset((const char *)endLocPtr - contents.data());
1373+
L->lex(Tok);
1374+
1375+
return makeParserResult(astNode);
1376+
}
1377+
13331378
//===--------------------------------------------------------------------===//
13341379
// Type Parsing
13351380

lib/AST/ASTPrinter.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -3321,6 +3321,10 @@ static bool usesFeatureParserASTGen(Decl *decl) {
33213321
return false;
33223322
}
33233323

3324+
static bool usesFeatureASTGenTypes(Decl *decl) {
3325+
return false;
3326+
}
3327+
33243328
static bool usesFeatureBuiltinMacros(Decl *decl) {
33253329
return false;
33263330
}

lib/AST/CASTBridging.cpp

+103-4
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,15 @@ void SwiftDiagnostic_finish(BridgedDiagnostic diagPtr) {
119119
BridgedIdentifier
120120
SwiftASTContext_getIdentifier(void *ctx, const unsigned char *_Nullable str,
121121
long len) {
122+
if (len == 1 && str[0] == '_')
123+
return BridgedIdentifier();
124+
125+
// If this was a back-ticked identifier, drop the back-ticks.
126+
if (len >= 2 && str[0] == '`' && str[len-1] == '`') {
127+
++str;
128+
len -= 2;
129+
}
130+
122131
return const_cast<void *>(
123132
static_cast<ASTContext *>(ctx)
124133
->getIdentifier(
@@ -484,6 +493,87 @@ void *PackExpansionTypeRepr_create(void *ctx, void *base, void *repeatLoc) {
484493
getSourceLocFromPointer(repeatLoc), (TypeRepr *)base);
485494
}
486495

496+
static BridgedTypeAttrKind bridgeTypeAttrKind(TypeAttrKind kind) {
497+
switch (kind) {
498+
#define TYPE_ATTR(X) case TAK_##X: return BridgedTypeAttrKind_##X;
499+
#include "swift/AST/Attr.def"
500+
case TAK_Count: return BridgedTypeAttrKind_Count;
501+
}
502+
}
503+
504+
static TypeAttrKind bridgeTypeAttrKind(BridgedTypeAttrKind kind) {
505+
switch (kind) {
506+
#define TYPE_ATTR(X) case BridgedTypeAttrKind_##X: return TAK_##X;
507+
#include "swift/AST/Attr.def"
508+
case BridgedTypeAttrKind_Count: return TAK_Count;
509+
}
510+
}
511+
512+
BridgedTypeAttrKind getBridgedTypeAttrKindFromString(
513+
const unsigned char *str, intptr_t len) {
514+
return bridgeTypeAttrKind(
515+
TypeAttributes::getAttrKindFromString(StringRef((const char *)str, len)));
516+
}
517+
518+
BridgedTypeAttributes BridgedTypeAttributes_create() {
519+
return new TypeAttributes();
520+
}
521+
522+
void BridgedTypeAttributes_addSimpleAttr(
523+
BridgedTypeAttributes typeAttributesPtr, BridgedTypeAttrKind kind,
524+
void *atLoc, void *attrLoc
525+
) {
526+
TypeAttributes *typeAttributes = (TypeAttributes *)typeAttributesPtr;
527+
typeAttributes->setAttr(
528+
bridgeTypeAttrKind(kind), getSourceLocFromPointer(attrLoc));
529+
if (typeAttributes->AtLoc.isInvalid())
530+
typeAttributes->AtLoc = getSourceLocFromPointer(atLoc);
531+
}
532+
533+
void *AttributedTypeRepr_create(
534+
void *ctx, void *base, BridgedTypeAttributes typeAttributesPtr) {
535+
TypeAttributes *typeAttributes = (TypeAttributes *)typeAttributesPtr;
536+
if (typeAttributes->empty())
537+
return base;
538+
539+
ASTContext &Context = *static_cast<ASTContext *>(ctx);
540+
auto attributedType =
541+
new (Context) AttributedTypeRepr(*typeAttributes, (TypeRepr *)base);
542+
delete typeAttributes;
543+
return attributedType;
544+
}
545+
546+
void *AttributedTypeSpecifierRepr_create(
547+
void *ctx, void *base, BridgedAttributedTypeSpecifier specifier, void *specifierLoc
548+
) {
549+
ASTContext &Context = *static_cast<ASTContext *>(ctx);
550+
SourceLoc loc = getSourceLocFromPointer(specifierLoc);
551+
TypeRepr *baseType = (TypeRepr *)base;
552+
switch (specifier) {
553+
case BridgedAttributedTypeSpecifierInOut:
554+
return new (Context) OwnershipTypeRepr(baseType, ParamSpecifier::InOut, loc);
555+
case BridgedAttributedTypeSpecifierBorrowing:
556+
return new (Context) OwnershipTypeRepr(baseType, ParamSpecifier::Borrowing, loc);
557+
case BridgedAttributedTypeSpecifierConsuming:
558+
return new (Context) OwnershipTypeRepr(baseType, ParamSpecifier::Consuming, loc);
559+
case BridgedAttributedTypeSpecifierLegacyShared:
560+
return new (Context) OwnershipTypeRepr(baseType, ParamSpecifier::LegacyShared, loc);
561+
case BridgedAttributedTypeSpecifierLegacyOwned:
562+
return new (Context) OwnershipTypeRepr(baseType, ParamSpecifier::LegacyOwned, loc);
563+
case BridgedAttributedTypeSpecifierConst:
564+
return new (Context) CompileTimeConstTypeRepr(baseType, loc);
565+
case BridgedAttributedTypeSpecifierIsolated:
566+
return new (Context) IsolatedTypeRepr(baseType, loc);
567+
}
568+
}
569+
570+
void *VarargTypeRepr_create(void *ctx, void *base, void *ellipsisLocPtr) {
571+
ASTContext &Context = *static_cast<ASTContext *>(ctx);
572+
SourceLoc ellipsisLoc = getSourceLocFromPointer(ellipsisLocPtr);
573+
TypeRepr *baseType = (TypeRepr *)base;
574+
return new (Context) VarargTypeRepr(baseType, ellipsisLoc);
575+
}
576+
487577
void *TupleTypeRepr_create(void *ctx, BridgedArrayRef elements, void *lParenLoc,
488578
void *rParenLoc) {
489579
ASTContext &Context = *static_cast<ASTContext *>(ctx);
@@ -518,12 +608,21 @@ void *MemberTypeRepr_create(void *ctx, void *baseComponent,
518608
memberComponents);
519609
}
520610

521-
void *CompositionTypeRepr_create(void *ctx, BridgedArrayRef types,
522-
void *firstTypeLoc) {
611+
void *EmptyCompositionTypeRepr_create(void *ctx, void *anyLocPtr) {
612+
ASTContext &Context = *static_cast<ASTContext *>(ctx);
613+
SourceLoc anyLoc = getSourceLocFromPointer(anyLocPtr);
614+
return CompositionTypeRepr::createEmptyComposition(Context, anyLoc);
615+
}
616+
617+
void *CompositionTypeRepr_create(void *ctx, BridgedArrayRef typesPtr,
618+
void *firstTypeLoc, void *firstAmpLocPtr) {
523619
ASTContext &Context = *static_cast<ASTContext *>(ctx);
524620
SourceLoc firstType = getSourceLocFromPointer(firstTypeLoc);
525-
return CompositionTypeRepr::create(Context, getArrayRef<TypeRepr *>(types),
526-
firstType, SourceRange{});
621+
SourceLoc firstAmpLoc = getSourceLocFromPointer(firstAmpLocPtr);
622+
auto types = getArrayRef<TypeRepr *>(typesPtr);
623+
return CompositionTypeRepr::create(
624+
Context, types, firstType,
625+
SourceRange{firstAmpLoc, types.back()->getEndLoc()});
527626
}
528627

529628
void *FunctionTypeRepr_create(void *ctx, void *argsTy, void *_Nullable asyncLoc,

lib/ASTGen/Sources/ASTGen/Macros.swift

+35-5
Original file line numberDiff line numberDiff line change
@@ -586,10 +586,11 @@ func expandFreestandingMacroInProcess(
586586
}
587587

588588
/// Retrieve a syntax node in the given source file, with the given type.
589-
private func findSyntaxNodeInSourceFile<Node: SyntaxProtocol>(
589+
func findSyntaxNodeInSourceFile<Node: SyntaxProtocol>(
590590
sourceFilePtr: UnsafeRawPointer,
591591
sourceLocationPtr: UnsafePointer<UInt8>?,
592-
type: Node.Type
592+
type: Node.Type,
593+
wantOutermost: Bool = false
593594
) -> Node? {
594595
guard let sourceLocationPtr = sourceLocationPtr else {
595596
return nil
@@ -615,16 +616,45 @@ private func findSyntaxNodeInSourceFile<Node: SyntaxProtocol>(
615616
}
616617

617618
var currentSyntax = Syntax(token)
619+
var resultSyntax: Node? = nil
618620
while let parentSyntax = currentSyntax.parent {
619621
if let typedParent = parentSyntax.as(type) {
620-
return typedParent
622+
resultSyntax = typedParent
623+
break
621624
}
622625

623626
currentSyntax = parentSyntax
624627
}
625628

626-
print("unable to find node: \(token.debugDescription)")
627-
return nil
629+
// If we didn't find anything, complain and fail.
630+
guard var resultSyntax else {
631+
print("unable to find node: \(token.debugDescription)")
632+
return nil
633+
}
634+
635+
// If we want the outermost node, keep looking.
636+
// FIXME: This is VERY SPECIFIC to handling of types. We must be able to
637+
// do better.
638+
if wantOutermost {
639+
while let parentSyntax = resultSyntax.parent {
640+
// Look through type compositions.
641+
if let compositionElement = parentSyntax.as(CompositionTypeElementSyntax.self),
642+
let compositionList = compositionElement.parent?.as(CompositionTypeElementListSyntax.self),
643+
let typedParent = compositionList.parent?.as(type) {
644+
resultSyntax = typedParent
645+
continue
646+
}
647+
648+
guard let typedParent = parentSyntax.as(type),
649+
typedParent.position == resultSyntax.position else {
650+
break
651+
}
652+
653+
resultSyntax = typedParent
654+
}
655+
}
656+
657+
return resultSyntax
628658
}
629659

630660
@_cdecl("swift_ASTGen_expandAttachedMacro")

0 commit comments

Comments
 (0)