741 lines
28 KiB
Diff
741 lines
28 KiB
Diff
From dba94bdbd4f4b1e9b3b271409cbc5d1bb49ddaf3
|
|
From: Doug Gregor <dgregor@apple.com>
|
|
Date: Fri, 19 May 2023 15:02:42 -0700
|
|
Subject: [PATCH] [ASTGen] Add experimental feature to use ASTGen in lieu
|
|
of parsing types
|
|
|
|
Introduce a new experimental feature `ASTGenTypes` that uses ASTGen to
|
|
translate the Swift syntax tree (produced by the new Swift parser)
|
|
into C++ `TypeRepr` nodes instead of having the C++ parser create the
|
|
nodes.
|
|
|
|
The approach here is to intercept the C++ parser's `parseType`
|
|
operation to find the Swift syntax node at the given position (where
|
|
the lexer currently is) and have ASTGen translate that into the
|
|
corresponding C++ AST node. Then, we spin the lexer forward to the
|
|
token immediately following the end of the syntax node and continue
|
|
parsing.
|
|
|
|
diff --git a/swift/include/swift/AST/CASTBridging.h b/swift/include/swift/AST/CASTBridging.h
|
|
index 4699a291a1f..dd24e573561 100644
|
|
--- a/swift/include/swift/AST/CASTBridging.h
|
|
+++ b/swift/include/swift/AST/CASTBridging.h
|
|
@@ -112,6 +112,70 @@ typedef enum ENUM_EXTENSIBILITY_ATTR(open) BridgedMacroDefinitionKind : long {
|
|
BridgedBuiltinExternalMacro
|
|
} BridgedMacroDefinitionKind;
|
|
|
|
+/// Bridged parameter specifiers
|
|
+typedef enum ENUM_EXTENSIBILITY_ATTR(open) BridgedAttributedTypeSpecifier : long {
|
|
+ BridgedAttributedTypeSpecifierInOut,
|
|
+ BridgedAttributedTypeSpecifierBorrowing,
|
|
+ BridgedAttributedTypeSpecifierConsuming,
|
|
+ BridgedAttributedTypeSpecifierLegacyShared,
|
|
+ BridgedAttributedTypeSpecifierLegacyOwned,
|
|
+ BridgedAttributedTypeSpecifierConst,
|
|
+ BridgedAttributedTypeSpecifierIsolated,
|
|
+} BridgedAttributedTypeSpecifier;
|
|
+
|
|
+
|
|
+// Bridged type attribute kinds, which mirror TypeAttrKind exactly.
|
|
+typedef enum ENUM_EXTENSIBILITY_ATTR(closed) BridgedTypeAttrKind : long {
|
|
+ BridgedTypeAttrKind_autoclosure,
|
|
+ BridgedTypeAttrKind_convention,
|
|
+ BridgedTypeAttrKind_noescape,
|
|
+ BridgedTypeAttrKind_escaping,
|
|
+ BridgedTypeAttrKind_differentiable,
|
|
+ BridgedTypeAttrKind_noDerivative,
|
|
+ BridgedTypeAttrKind_async,
|
|
+ BridgedTypeAttrKind_Sendable,
|
|
+ BridgedTypeAttrKind_unchecked,
|
|
+ BridgedTypeAttrKind__local,
|
|
+ BridgedTypeAttrKind__noMetadata,
|
|
+ BridgedTypeAttrKind__opaqueReturnTypeOf,
|
|
+ BridgedTypeAttrKind_block_storage,
|
|
+ BridgedTypeAttrKind_box,
|
|
+ BridgedTypeAttrKind_dynamic_self,
|
|
+ BridgedTypeAttrKind_sil_weak,
|
|
+ BridgedTypeAttrKind_sil_unowned,
|
|
+ BridgedTypeAttrKind_sil_unmanaged,
|
|
+ BridgedTypeAttrKind_error,
|
|
+ BridgedTypeAttrKind_out,
|
|
+ BridgedTypeAttrKind_direct,
|
|
+ BridgedTypeAttrKind_in,
|
|
+ BridgedTypeAttrKind_inout,
|
|
+ BridgedTypeAttrKind_inout_aliasable,
|
|
+ BridgedTypeAttrKind_in_guaranteed,
|
|
+ BridgedTypeAttrKind_in_constant,
|
|
+ BridgedTypeAttrKind_pack_owned,
|
|
+ BridgedTypeAttrKind_pack_guaranteed,
|
|
+ BridgedTypeAttrKind_pack_inout,
|
|
+ BridgedTypeAttrKind_pack_out,
|
|
+ BridgedTypeAttrKind_owned,
|
|
+ BridgedTypeAttrKind_unowned_inner_pointer,
|
|
+ BridgedTypeAttrKind_guaranteed,
|
|
+ BridgedTypeAttrKind_autoreleased,
|
|
+ BridgedTypeAttrKind_callee_owned,
|
|
+ BridgedTypeAttrKind_callee_guaranteed,
|
|
+ BridgedTypeAttrKind_objc_metatype,
|
|
+ BridgedTypeAttrKind_opened,
|
|
+ BridgedTypeAttrKind_pack_element,
|
|
+ BridgedTypeAttrKind_pseudogeneric,
|
|
+ BridgedTypeAttrKind_yields,
|
|
+ BridgedTypeAttrKind_yield_once,
|
|
+ BridgedTypeAttrKind_yield_many,
|
|
+ BridgedTypeAttrKind_captures_generics,
|
|
+ BridgedTypeAttrKind_moveOnly,
|
|
+ BridgedTypeAttrKind_thin,
|
|
+ BridgedTypeAttrKind_thick,
|
|
+ BridgedTypeAttrKind_Count
|
|
+} BridgedTypeAttrKind;
|
|
+
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
|
|
@@ -261,6 +325,19 @@ void *ImplicitlyUnwrappedOptionalTypeRepr_create(void *ctx, void *base,
|
|
void *exclamationLoc);
|
|
void *MetatypeTypeRepr_create(void *ctx, void *baseType, void *typeLoc);
|
|
void *ProtocolTypeRepr_create(void *ctx, void *baseType, void *protoLoc);
|
|
+
|
|
+BridgedTypeAttrKind getBridgedTypeAttrKindFromString(
|
|
+ const unsigned char * _Nullable str, long len);
|
|
+
|
|
+typedef void *BridgedTypeAttributes;
|
|
+BridgedTypeAttributes BridgedTypeAttributes_create(void);
|
|
+void BridgedTypeAttributes_addSimpleAttr(
|
|
+ BridgedTypeAttributes typeAttributes, BridgedTypeAttrKind kind, void *atLoc, void *attrLoc);
|
|
+void *AttributedTypeRepr_create(void *ctx, void *base, BridgedTypeAttributes typeAttributes);
|
|
+
|
|
+void *AttributedTypeSpecifierRepr_create(
|
|
+ void *ctx, void *base, BridgedAttributedTypeSpecifier specifier, void *specifierLoc);
|
|
+void *VarargTypeRepr_create(void *ctx, void *base, void *ellipsisLocPtr);
|
|
void *PackExpansionTypeRepr_create(void *ctx, void *base, void *repeatLoc);
|
|
void *TupleTypeRepr_create(void *ctx, BridgedArrayRef elements, void *lParenLoc,
|
|
void *rParenLoc);
|
|
@@ -269,8 +346,9 @@ void *MemberTypeRepr_create(void *ctx, void *baseComponent,
|
|
void *GenericIdentTypeRepr_create(void *ctx, BridgedIdentifier name,
|
|
void *nameLoc, BridgedArrayRef genericArgs,
|
|
void *lAngle, void *rAngle);
|
|
+void *EmptyCompositionTypeRepr_create(void *ctx, void *anyLoc);
|
|
void *CompositionTypeRepr_create(void *ctx, BridgedArrayRef types,
|
|
- void *firstTypeLoc);
|
|
+ void *firstTypeLoc, void *firstAmpLoc);
|
|
void *FunctionTypeRepr_create(void *ctx, void *argsTy, void *_Nullable asyncLoc,
|
|
void *_Nullable throwsLoc, void *arrowLoc,
|
|
void *returnType);
|
|
diff --git a/swift/include/swift/Basic/Features.def b/swift/include/swift/Basic/Features.def
|
|
index d3b6ed2519f..d0884deafe4 100644
|
|
--- a/swift/include/swift/Basic/Features.def
|
|
+++ b/swift/include/swift/Basic/Features.def
|
|
@@ -184,6 +184,10 @@ EXPERIMENTAL_FEATURE(ImplicitSome, false)
|
|
/// corresponding syntax tree.
|
|
EXPERIMENTAL_FEATURE(ParserASTGen, false)
|
|
|
|
+/// Use the syntax tree produced by the Swift (swift-syntax) parser for type
|
|
+/// parsing, using ASTGen to translate them into AST nodes.
|
|
+EXPERIMENTAL_FEATURE(ASTGenTypes, false)
|
|
+
|
|
/// Parse using the Swift (swift-syntax) parser and use ASTGen to generate the
|
|
/// corresponding syntax tree.
|
|
EXPERIMENTAL_FEATURE(BuiltinMacros, false)
|
|
diff --git a/swift/include/swift/Parse/Parser.h b/swift/include/swift/Parse/Parser.h
|
|
index a1ac3666776..2ba8c645833 100644
|
|
--- a/swift/include/swift/Parse/Parser.h
|
|
+++ b/swift/include/swift/Parse/Parser.h
|
|
@@ -24,6 +24,7 @@
|
|
#include "swift/AST/LayoutConstraint.h"
|
|
#include "swift/AST/ParseRequests.h"
|
|
#include "swift/AST/Pattern.h"
|
|
+#include "swift/AST/SourceFile.h"
|
|
#include "swift/AST/Stmt.h"
|
|
#include "swift/Basic/OptionSet.h"
|
|
#include "swift/Config.h"
|
|
@@ -1343,6 +1344,50 @@ public:
|
|
/// Get the location for a type error.
|
|
SourceLoc getTypeErrorLoc() const;
|
|
|
|
+ /// Callback function used for creating a C++ AST from the syntax node at the given source location.
|
|
+ ///
|
|
+ /// The arguments to this callback are the source file to pass into ASTGen (the exported source file)
|
|
+ /// and the source location pointer to pass into ASTGen (to find the syntax node).
|
|
+ ///
|
|
+ /// The callback returns the new AST node and the ending location of the syntax node. If the AST node
|
|
+ /// is NULL, something went wrong.
|
|
+ template<typename T>
|
|
+ using ASTFromSyntaxTreeCallback = std::pair<T*, const void *>(
|
|
+ void *sourceFile, const void *sourceLoc
|
|
+ );
|
|
+
|
|
+ /// Parse by constructing a C++ AST node from the Swift syntax tree via ASTGen.
|
|
+ template<typename T>
|
|
+ ParserResult<T> parseASTFromSyntaxTree(
|
|
+ llvm::function_ref<ASTFromSyntaxTreeCallback<T>> body
|
|
+ ) {
|
|
+ if (!Context.LangOpts.hasFeature(Feature::ASTGenTypes))
|
|
+ return nullptr;
|
|
+
|
|
+ auto exportedSourceFile = SF.getExportedSourceFile();
|
|
+ if (!exportedSourceFile)
|
|
+ return nullptr;
|
|
+
|
|
+ // Perform the translation.
|
|
+ auto sourceLoc = Tok.getLoc().getOpaquePointerValue();
|
|
+ T* astNode;
|
|
+ const void *endLocPtr;
|
|
+ std::tie(astNode, endLocPtr) = body(exportedSourceFile, sourceLoc);
|
|
+
|
|
+ if (!astNode) {
|
|
+ assert(false && "Could not build AST node from syntax tree");
|
|
+ return nullptr;
|
|
+ }
|
|
+
|
|
+ // Reset the lexer to the ending location.
|
|
+ StringRef contents =
|
|
+ SourceMgr.extractText(SourceMgr.getRangeForBuffer(L->getBufferID()));
|
|
+ L->resetToOffset((const char *)endLocPtr - contents.data());
|
|
+ L->lex(Tok);
|
|
+
|
|
+ return makeParserResult(astNode);
|
|
+ }
|
|
+
|
|
//===--------------------------------------------------------------------===//
|
|
// Type Parsing
|
|
|
|
diff --git a/swift/lib/AST/ASTPrinter.cpp b/swift/lib/AST/ASTPrinter.cpp
|
|
index 7f24711916c..474e62aa8dc 100644
|
|
--- a/swift/lib/AST/ASTPrinter.cpp
|
|
+++ b/swift/lib/AST/ASTPrinter.cpp
|
|
@@ -3364,6 +3364,10 @@ static bool usesFeatureParserASTGen(Decl *decl) {
|
|
return false;
|
|
}
|
|
|
|
+static bool usesFeatureASTGenTypes(Decl *decl) {
|
|
+ return false;
|
|
+}
|
|
+
|
|
static bool usesFeatureBuiltinMacros(Decl *decl) {
|
|
return false;
|
|
}
|
|
diff --git a/swift/lib/AST/CASTBridging.cpp b/swift/lib/AST/CASTBridging.cpp
|
|
index 5b935d4cebb..2f7c14fd1a2 100644
|
|
--- a/swift/lib/AST/CASTBridging.cpp
|
|
+++ b/swift/lib/AST/CASTBridging.cpp
|
|
@@ -119,6 +119,15 @@ void SwiftDiagnostic_finish(BridgedDiagnostic diagPtr) {
|
|
BridgedIdentifier
|
|
SwiftASTContext_getIdentifier(void *ctx, const unsigned char *_Nullable str,
|
|
long len) {
|
|
+ if (len == 1 && str[0] == '_')
|
|
+ return BridgedIdentifier();
|
|
+
|
|
+ // If this was a back-ticked identifier, drop the back-ticks.
|
|
+ if (len >= 2 && str[0] == '`' && str[len-1] == '`') {
|
|
+ ++str;
|
|
+ len -= 2;
|
|
+ }
|
|
+
|
|
return const_cast<void *>(
|
|
static_cast<ASTContext *>(ctx)
|
|
->getIdentifier(
|
|
@@ -484,6 +493,87 @@ void *PackExpansionTypeRepr_create(void *ctx, void *base, void *repeatLoc) {
|
|
getSourceLocFromPointer(repeatLoc), (TypeRepr *)base);
|
|
}
|
|
|
|
+static BridgedTypeAttrKind bridgeTypeAttrKind(TypeAttrKind kind) {
|
|
+ switch (kind) {
|
|
+#define TYPE_ATTR(X) case TAK_##X: return BridgedTypeAttrKind_##X;
|
|
+#include "swift/AST/Attr.def"
|
|
+ case TAK_Count: return BridgedTypeAttrKind_Count;
|
|
+ }
|
|
+}
|
|
+
|
|
+static TypeAttrKind bridgeTypeAttrKind(BridgedTypeAttrKind kind) {
|
|
+ switch (kind) {
|
|
+#define TYPE_ATTR(X) case BridgedTypeAttrKind_##X: return TAK_##X;
|
|
+#include "swift/AST/Attr.def"
|
|
+ case BridgedTypeAttrKind_Count: return TAK_Count;
|
|
+ }
|
|
+}
|
|
+
|
|
+BridgedTypeAttrKind getBridgedTypeAttrKindFromString(
|
|
+ const unsigned char *str, intptr_t len) {
|
|
+ return bridgeTypeAttrKind(
|
|
+ TypeAttributes::getAttrKindFromString(StringRef((const char *)str, len)));
|
|
+}
|
|
+
|
|
+BridgedTypeAttributes BridgedTypeAttributes_create() {
|
|
+ return new TypeAttributes();
|
|
+}
|
|
+
|
|
+void BridgedTypeAttributes_addSimpleAttr(
|
|
+ BridgedTypeAttributes typeAttributesPtr, BridgedTypeAttrKind kind,
|
|
+ void *atLoc, void *attrLoc
|
|
+) {
|
|
+ TypeAttributes *typeAttributes = (TypeAttributes *)typeAttributesPtr;
|
|
+ typeAttributes->setAttr(
|
|
+ bridgeTypeAttrKind(kind), getSourceLocFromPointer(attrLoc));
|
|
+ if (typeAttributes->AtLoc.isInvalid())
|
|
+ typeAttributes->AtLoc = getSourceLocFromPointer(atLoc);
|
|
+}
|
|
+
|
|
+void *AttributedTypeRepr_create(
|
|
+ void *ctx, void *base, BridgedTypeAttributes typeAttributesPtr) {
|
|
+ TypeAttributes *typeAttributes = (TypeAttributes *)typeAttributesPtr;
|
|
+ if (typeAttributes->empty())
|
|
+ return base;
|
|
+
|
|
+ ASTContext &Context = *static_cast<ASTContext *>(ctx);
|
|
+ auto attributedType =
|
|
+ new (Context) AttributedTypeRepr(*typeAttributes, (TypeRepr *)base);
|
|
+ delete typeAttributes;
|
|
+ return attributedType;
|
|
+}
|
|
+
|
|
+void *AttributedTypeSpecifierRepr_create(
|
|
+ void *ctx, void *base, BridgedAttributedTypeSpecifier specifier, void *specifierLoc
|
|
+) {
|
|
+ ASTContext &Context = *static_cast<ASTContext *>(ctx);
|
|
+ SourceLoc loc = getSourceLocFromPointer(specifierLoc);
|
|
+ TypeRepr *baseType = (TypeRepr *)base;
|
|
+ switch (specifier) {
|
|
+ case BridgedAttributedTypeSpecifierInOut:
|
|
+ return new (Context) OwnershipTypeRepr(baseType, ParamSpecifier::InOut, loc);
|
|
+ case BridgedAttributedTypeSpecifierBorrowing:
|
|
+ return new (Context) OwnershipTypeRepr(baseType, ParamSpecifier::Borrowing, loc);
|
|
+ case BridgedAttributedTypeSpecifierConsuming:
|
|
+ return new (Context) OwnershipTypeRepr(baseType, ParamSpecifier::Consuming, loc);
|
|
+ case BridgedAttributedTypeSpecifierLegacyShared:
|
|
+ return new (Context) OwnershipTypeRepr(baseType, ParamSpecifier::LegacyShared, loc);
|
|
+ case BridgedAttributedTypeSpecifierLegacyOwned:
|
|
+ return new (Context) OwnershipTypeRepr(baseType, ParamSpecifier::LegacyOwned, loc);
|
|
+ case BridgedAttributedTypeSpecifierConst:
|
|
+ return new (Context) CompileTimeConstTypeRepr(baseType, loc);
|
|
+ case BridgedAttributedTypeSpecifierIsolated:
|
|
+ return new (Context) IsolatedTypeRepr(baseType, loc);
|
|
+ }
|
|
+}
|
|
+
|
|
+void *VarargTypeRepr_create(void *ctx, void *base, void *ellipsisLocPtr) {
|
|
+ ASTContext &Context = *static_cast<ASTContext *>(ctx);
|
|
+ SourceLoc ellipsisLoc = getSourceLocFromPointer(ellipsisLocPtr);
|
|
+ TypeRepr *baseType = (TypeRepr *)base;
|
|
+ return new (Context) VarargTypeRepr(baseType, ellipsisLoc);
|
|
+}
|
|
+
|
|
void *TupleTypeRepr_create(void *ctx, BridgedArrayRef elements, void *lParenLoc,
|
|
void *rParenLoc) {
|
|
ASTContext &Context = *static_cast<ASTContext *>(ctx);
|
|
@@ -518,12 +608,21 @@ void *MemberTypeRepr_create(void *ctx, void *baseComponent,
|
|
memberComponents);
|
|
}
|
|
|
|
-void *CompositionTypeRepr_create(void *ctx, BridgedArrayRef types,
|
|
- void *firstTypeLoc) {
|
|
+void *EmptyCompositionTypeRepr_create(void *ctx, void *anyLocPtr) {
|
|
+ ASTContext &Context = *static_cast<ASTContext *>(ctx);
|
|
+ SourceLoc anyLoc = getSourceLocFromPointer(anyLocPtr);
|
|
+ return CompositionTypeRepr::createEmptyComposition(Context, anyLoc);
|
|
+}
|
|
+
|
|
+void *CompositionTypeRepr_create(void *ctx, BridgedArrayRef typesPtr,
|
|
+ void *firstTypeLoc, void *firstAmpLocPtr) {
|
|
ASTContext &Context = *static_cast<ASTContext *>(ctx);
|
|
SourceLoc firstType = getSourceLocFromPointer(firstTypeLoc);
|
|
- return CompositionTypeRepr::create(Context, getArrayRef<TypeRepr *>(types),
|
|
- firstType, SourceRange{});
|
|
+ SourceLoc firstAmpLoc = getSourceLocFromPointer(firstAmpLocPtr);
|
|
+ auto types = getArrayRef<TypeRepr *>(typesPtr);
|
|
+ return CompositionTypeRepr::create(
|
|
+ Context, types, firstType,
|
|
+ SourceRange{firstAmpLoc, types.back()->getEndLoc()});
|
|
}
|
|
|
|
void *FunctionTypeRepr_create(void *ctx, void *argsTy, void *_Nullable asyncLoc,
|
|
diff --git a/swift/lib/ASTGen/Sources/ASTGen/Macros.swift b/swift/lib/ASTGen/Sources/ASTGen/Macros.swift
|
|
index 4ee025884bd..81e355f475d 100644
|
|
--- a/swift/lib/ASTGen/Sources/ASTGen/Macros.swift
|
|
+++ b/swift/lib/ASTGen/Sources/ASTGen/Macros.swift
|
|
@@ -627,10 +627,11 @@ func expandFreestandingMacroInProcess(
|
|
}
|
|
|
|
/// Retrieve a syntax node in the given source file, with the given type.
|
|
-private func findSyntaxNodeInSourceFile<Node: SyntaxProtocol>(
|
|
+func findSyntaxNodeInSourceFile<Node: SyntaxProtocol>(
|
|
sourceFilePtr: UnsafeRawPointer,
|
|
sourceLocationPtr: UnsafePointer<UInt8>?,
|
|
- type: Node.Type
|
|
+ type: Node.Type,
|
|
+ wantOutermost: Bool = false
|
|
) -> Node? {
|
|
guard let sourceLocationPtr = sourceLocationPtr else {
|
|
return nil
|
|
@@ -656,16 +657,45 @@ private func findSyntaxNodeInSourceFile<Node: SyntaxProtocol>(
|
|
}
|
|
|
|
var currentSyntax = Syntax(token)
|
|
+ var resultSyntax: Node? = nil
|
|
while let parentSyntax = currentSyntax.parent {
|
|
if let typedParent = parentSyntax.as(type) {
|
|
- return typedParent
|
|
+ resultSyntax = typedParent
|
|
+ break
|
|
}
|
|
|
|
currentSyntax = parentSyntax
|
|
}
|
|
|
|
- print("unable to find node: \(token.debugDescription)")
|
|
- return nil
|
|
+ // If we didn't find anything, complain and fail.
|
|
+ guard var resultSyntax else {
|
|
+ print("unable to find node: \(token.debugDescription)")
|
|
+ return nil
|
|
+ }
|
|
+
|
|
+ // If we want the outermost node, keep looking.
|
|
+ // FIXME: This is VERY SPECIFIC to handling of types. We must be able to
|
|
+ // do better.
|
|
+ if wantOutermost {
|
|
+ while let parentSyntax = resultSyntax.parent {
|
|
+ // Look through type compositions.
|
|
+ if let compositionElement = parentSyntax.as(CompositionTypeElementSyntax.self),
|
|
+ let compositionList = compositionElement.parent?.as(CompositionTypeElementListSyntax.self),
|
|
+ let typedParent = compositionList.parent?.as(type) {
|
|
+ resultSyntax = typedParent
|
|
+ continue
|
|
+ }
|
|
+
|
|
+ guard let typedParent = parentSyntax.as(type),
|
|
+ typedParent.position == resultSyntax.position else {
|
|
+ break
|
|
+ }
|
|
+
|
|
+ resultSyntax = typedParent
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return resultSyntax
|
|
}
|
|
|
|
@_cdecl("swift_ASTGen_expandAttachedMacro")
|
|
diff --git a/swift/lib/ASTGen/Sources/ASTGen/Types.swift b/swift/lib/ASTGen/Sources/ASTGen/Types.swift
|
|
index eb2be48a8a8..82bbca53bf4 100644
|
|
--- a/swift/lib/ASTGen/Sources/ASTGen/Types.swift
|
|
+++ b/swift/lib/ASTGen/Sources/ASTGen/Types.swift
|
|
@@ -6,6 +6,11 @@ extension ASTGenVisitor {
|
|
public func visit(_ node: SimpleTypeIdentifierSyntax) -> ASTNode {
|
|
let loc = self.base.advanced(by: node.position.utf8Offset).raw
|
|
|
|
+ // If this is the bare 'Any' keyword, produce an empty composition type.
|
|
+ if node.name.tokenKind == .keyword(.Any) && node.genericArgumentClause == nil {
|
|
+ return .type(EmptyCompositionTypeRepr_create(self.ctx, loc))
|
|
+ }
|
|
+
|
|
var text = node.name.text
|
|
let id = text.withUTF8 { buf in
|
|
return SwiftASTContext_getIdentifier(ctx, buf.baseAddress, buf.count)
|
|
@@ -19,7 +24,7 @@ extension ASTGenVisitor {
|
|
let rAngle = self.base.advanced(by: generics.rightAngleBracket.position.utf8Offset).raw
|
|
return .type(
|
|
generics.arguments.map({
|
|
- self.visit($0.argumentType)
|
|
+ self.visit($0.argumentType).rawValue
|
|
}).withBridgedArrayRef {
|
|
genericArgs in
|
|
GenericIdentTypeRepr_create(
|
|
@@ -46,7 +51,7 @@ extension ASTGenVisitor {
|
|
let lAngle = self.base.advanced(by: generics.leftAngleBracket.position.utf8Offset).raw
|
|
let rAngle = self.base.advanced(by: generics.rightAngleBracket.position.utf8Offset).raw
|
|
reverseMemberComponents.append(
|
|
- generics.arguments.map({ self.visit($0.argumentType) }).withBridgedArrayRef {
|
|
+ generics.arguments.map({ self.visit($0.argumentType).rawValue }).withBridgedArrayRef {
|
|
genericArgs in
|
|
GenericIdentTypeRepr_create(self.ctx, name, nameLoc, genericArgs, lAngle, rAngle)
|
|
})
|
|
@@ -123,9 +128,11 @@ extension ASTGenVisitor {
|
|
assert(node.elements.count > 1)
|
|
let types = node.elements.map { visit($0.type) }.map { $0.rawValue }
|
|
let firstTypeLoc = self.base.advanced(by: node.elements.first!.type.position.utf8Offset).raw
|
|
+ let firstAmpOffset = node.elements.first?.ampersand.map { $0.position.utf8Offset } ?? 0
|
|
+ let firstAmpLoc = self.base.advanced(by: firstAmpOffset).raw
|
|
return .type(
|
|
types.withBridgedArrayRef { types in
|
|
- return CompositionTypeRepr_create(self.ctx, types, firstTypeLoc)
|
|
+ return CompositionTypeRepr_create(self.ctx, types, firstTypeLoc, firstAmpLoc)
|
|
})
|
|
}
|
|
|
|
@@ -161,8 +168,77 @@ extension ASTGenVisitor {
|
|
}
|
|
|
|
public func visit(_ node: AttributedTypeSyntax) -> ASTNode {
|
|
- // FIXME: Respect the attributes
|
|
- return visit(node.baseType)
|
|
+ var type = visit(node.baseType)
|
|
+
|
|
+ // Handle specifiers.
|
|
+ if let specifier = node.specifier {
|
|
+ let specifierLoc = self.base.advanced(by: specifier.position.utf8Offset).raw
|
|
+
|
|
+ let kind: BridgedAttributedTypeSpecifier
|
|
+ switch specifier.tokenKind {
|
|
+ case .keyword(.inout): kind = .inOut
|
|
+ case .keyword(.borrowing): kind = .borrowing
|
|
+ case .keyword(.consuming): kind = .consuming
|
|
+ case .keyword(.__shared): kind = .legacyShared
|
|
+ case .keyword(.__owned): kind = .legacyOwned
|
|
+ case .keyword(._const): kind = .const
|
|
+ case .keyword(.isolated): kind = .isolated
|
|
+ default: fatalError("unhandled specifier \(specifier.debugDescription)")
|
|
+ }
|
|
+
|
|
+ type = .type(AttributedTypeSpecifierRepr_create(self.ctx, type.rawValue, kind, specifierLoc))
|
|
+ }
|
|
+
|
|
+ // Handle type attributes.
|
|
+ if let attributes = node.attributes {
|
|
+ let typeAttributes = BridgedTypeAttributes_create()
|
|
+ for attributeElt in attributes {
|
|
+ // FIXME: Ignoring #ifs entirely. We want to provide a filtered view,
|
|
+ // but we don't have that ability right now.
|
|
+ guard case let .attribute(attribute) = attributeElt else {
|
|
+ continue
|
|
+ }
|
|
+
|
|
+ // Only handle simple attribute names right now.
|
|
+ guard let identType = attribute.attributeName.as(SimpleTypeIdentifierSyntax.self) else {
|
|
+ continue
|
|
+ }
|
|
+
|
|
+ let nameSyntax = identType.name
|
|
+ var name = nameSyntax.text
|
|
+ let typeAttrKind = name.withUTF8 { buf in
|
|
+ getBridgedTypeAttrKindFromString(buf.baseAddress, buf.count)
|
|
+ }
|
|
+ let atLoc = self.base.advanced(by: attribute.atSignToken.position.utf8Offset).raw
|
|
+ let attrLoc = self.base.advanced(by: nameSyntax.position.utf8Offset).raw
|
|
+ switch typeAttrKind {
|
|
+ // SIL attributes
|
|
+ // FIXME: Diagnose if not in SIL mode? Or should that move to the
|
|
+ // type checker?
|
|
+ case .out, .in, .owned, .unowned_inner_pointer, .guaranteed,
|
|
+ .autoreleased, .callee_owned, .callee_guaranteed, .objc_metatype,
|
|
+ .sil_weak, .sil_unowned, .inout, .block_storage, .box,
|
|
+ .dynamic_self, .sil_unmanaged, .error, .direct, .inout_aliasable,
|
|
+ .in_guaranteed, .in_constant, .captures_generics, .moveOnly:
|
|
+ fallthrough
|
|
+
|
|
+ case .autoclosure, .escaping, .noescape, .noDerivative, .async,
|
|
+ .sendable, .unchecked, ._local, ._noMetadata, .pack_owned,
|
|
+ .pack_guaranteed, .pack_inout, .pack_out, .pseudogeneric,
|
|
+ .yields, .yield_once, .yield_many, .thin, .thick, .count:
|
|
+ BridgedTypeAttributes_addSimpleAttr(typeAttributes, typeAttrKind, atLoc, attrLoc)
|
|
+
|
|
+ case .opened, .pack_element, .differentiable, .convention,
|
|
+ ._opaqueReturnTypeOf:
|
|
+ // FIXME: These require more complicated checks
|
|
+ break
|
|
+ }
|
|
+ }
|
|
+
|
|
+ type = .type(AttributedTypeRepr_create(self.ctx, type.rawValue, typeAttributes))
|
|
+ }
|
|
+
|
|
+ return type
|
|
}
|
|
}
|
|
|
|
@@ -186,7 +262,13 @@ extension ASTGenVisitor {
|
|
self.base.advanced(by: $0.position.utf8Offset).raw
|
|
}
|
|
let colonLoc = element.colon.map { self.base.advanced(by: $0.position.utf8Offset).raw }
|
|
- let type = visit(element.type).rawValue
|
|
+
|
|
+ var type = visit(element.type).rawValue
|
|
+ if let ellipsis = element.ellipsis {
|
|
+ let ellipsisLoc = self.base.advanced(by: ellipsis.positionAfterSkippingLeadingTrivia.utf8Offset).raw
|
|
+ type = VarargTypeRepr_create(self.ctx, type, ellipsisLoc)
|
|
+ }
|
|
+
|
|
let trailingCommaLoc = element.trailingComma.map {
|
|
self.base.advanced(by: $0.position.utf8Offset).raw
|
|
}
|
|
@@ -207,3 +289,37 @@ extension ASTGenVisitor {
|
|
}
|
|
}
|
|
}
|
|
+
|
|
+@_cdecl("swift_ASTGen_buildTypeRepr")
|
|
+@usableFromInline
|
|
+func buildTypeRepr(
|
|
+ sourceFilePtr: UnsafeRawPointer,
|
|
+ typeLocPtr: UnsafePointer<UInt8>,
|
|
+ dc: UnsafeMutableRawPointer,
|
|
+ ctx: UnsafeMutableRawPointer,
|
|
+ endTypeLocPtr: UnsafeMutablePointer<UnsafePointer<UInt8>?>
|
|
+) -> UnsafeMutableRawPointer? {
|
|
+ let sourceFile = sourceFilePtr.bindMemory(
|
|
+ to: ExportedSourceFile.self, capacity: 1
|
|
+ )
|
|
+
|
|
+ // Find the type syntax node.
|
|
+ guard let typeSyntax = findSyntaxNodeInSourceFile(
|
|
+ sourceFilePtr: sourceFilePtr,
|
|
+ sourceLocationPtr: typeLocPtr,
|
|
+ type: TypeSyntax.self,
|
|
+ wantOutermost: true
|
|
+ ) else {
|
|
+ // FIXME: Produce an error
|
|
+ return nil
|
|
+ }
|
|
+
|
|
+ // Fill in the end location.
|
|
+ endTypeLocPtr.pointee = sourceFile.pointee.buffer.baseAddress!.advanced(by: typeSyntax.endPosition.utf8Offset)
|
|
+
|
|
+ // Convert the type syntax node.
|
|
+ let typeReprNode = ASTGenVisitor(ctx: ctx, base: sourceFile.pointee.buffer.baseAddress!, declContext: dc)
|
|
+ .visit(typeSyntax)
|
|
+
|
|
+ return typeReprNode.rawValue
|
|
+}
|
|
diff --git a/swift/lib/Parse/ParseType.cpp b/swift/lib/Parse/ParseType.cpp
|
|
index 98a1cb0a4fc..97c88da9bbd 100644
|
|
--- a/swift/lib/Parse/ParseType.cpp
|
|
+++ b/swift/lib/Parse/ParseType.cpp
|
|
@@ -582,6 +582,14 @@ ParserResult<TypeRepr> Parser::parseTypeScalar(
|
|
constLoc));
|
|
}
|
|
|
|
+/// Build a TypeRepr for AST node for the type at the given source location in the specified file.
|
|
+///
|
|
+/// \param sourceLoc The source location at which to start processing a type.
|
|
+/// \param endSourceLoc Will receive the source location immediately following the type.
|
|
+extern "C" TypeRepr *swift_ASTGen_buildTypeRepr(
|
|
+ void *sourceFile, const void *_Nullable sourceLoc,
|
|
+ void *declContext, void *astContext, const void *_Nullable *endSourceLoc);
|
|
+
|
|
/// parseType
|
|
/// type:
|
|
/// type-scalar
|
|
@@ -592,6 +600,32 @@ ParserResult<TypeRepr> Parser::parseTypeScalar(
|
|
///
|
|
ParserResult<TypeRepr> Parser::parseType(
|
|
Diag<> MessageID, ParseTypeReason reason) {
|
|
+ #if SWIFT_SWIFT_PARSER
|
|
+ auto astGenResult = parseASTFromSyntaxTree<TypeRepr>(
|
|
+ [&](void *exportedSourceFile, const void *sourceLoc) {
|
|
+ const void *endLocPtr = nullptr;
|
|
+ TypeRepr *typeRepr = swift_ASTGen_buildTypeRepr(
|
|
+ exportedSourceFile, Tok.getLoc().getOpaquePointerValue(),
|
|
+ CurDeclContext, &Context, &endLocPtr);
|
|
+ return std::make_pair(typeRepr, endLocPtr);
|
|
+ });
|
|
+ if (astGenResult.isNonNull()) {
|
|
+ // Note: there is a representational difference between the swift-syntax
|
|
+ // tree and the C++ parser tree regarding variadic parameters. In the
|
|
+ // swift-syntax tree, the ellipsis is part of the parameter declaration.
|
|
+ // In the C++ parser tree, the ellipsis is part of the type. Account for
|
|
+ // this difference by consuming the ellipsis here.
|
|
+ if (Tok.isEllipsis()) {
|
|
+ Tok.setKind(tok::ellipsis);
|
|
+ SourceLoc ellipsisLoc = consumeToken();
|
|
+ return makeParserResult(astGenResult,
|
|
+ new (Context) VarargTypeRepr(astGenResult.get(), ellipsisLoc));
|
|
+ }
|
|
+
|
|
+ return astGenResult;
|
|
+ }
|
|
+ #endif
|
|
+
|
|
// Parse pack expansion 'repeat T'
|
|
if (Tok.is(tok::kw_repeat)) {
|
|
SourceLoc repeatLoc = consumeToken(tok::kw_repeat);
|
|
diff --git a/swift/test/ASTGen/types.swift b/swift/test/ASTGen/types.swift
|
|
new file mode 100644
|
|
index 00000000000..f6eddfe1ed6
|
|
--- /dev/null
|
|
+++ b/swift/test/ASTGen/types.swift
|
|
@@ -0,0 +1,41 @@
|
|
+// RUN: %target-typecheck-verify-swift -enable-experimental-feature ASTGenTypes
|
|
+
|
|
+// -enable-experimental-feature requires an asserts build
|
|
+// REQUIRES: asserts
|
|
+
|
|
+protocol P { }
|
|
+protocol Q { }
|
|
+typealias PQ = P & Q
|
|
+
|
|
+func test7(_ b: inout Bool) {
|
|
+ b = true
|
|
+}
|
|
+
|
|
+struct X { struct `Protocol` { } }
|
|
+
|
|
+func test10(_: X.`Protocol`) { }
|
|
+
|
|
+func test11(_: Int...) { }
|
|
+func test11a() {
|
|
+ test11(1, 2, 3, 4, 5)
|
|
+}
|
|
+
|
|
+typealias VAFunc = (Int, Int...) -> Int
|
|
+func testVAFunc(a: Int, f: VAFunc) {
|
|
+ _ = f(a, a, a, a, a)
|
|
+}
|
|
+
|
|
+func test12(_ producer: @escaping @autoclosure () -> Int) {
|
|
+ _ = producer()
|
|
+}
|
|
+func test12a(i: Int) {
|
|
+ test12(i)
|
|
+}
|
|
+
|
|
+func test13(body: (_ value: Int) -> Void, i: Int) {
|
|
+ body(i)
|
|
+}
|
|
+
|
|
+func test14() {
|
|
+ _ = Array<Array<Array<Int>>>().count
|
|
+}
|
|
diff --git a/swift/test/ASTGen/verify-parse.swift b/swift/test/ASTGen/verify-parse.swift
|
|
index ec5004eb129..9bdc36cb4f0 100644
|
|
--- a/swift/test/ASTGen/verify-parse.swift
|
|
+++ b/swift/test/ASTGen/verify-parse.swift
|
|
@@ -1,8 +1,9 @@
|
|
// RUN: %target-run-simple-swift(-enable-experimental-feature SwiftParser -enable-experimental-feature ParserASTGen)
|
|
+// RUN: %target-run-simple-swift(-enable-experimental-feature ASTGenTypes)
|
|
|
|
// REQUIRES: executable_test
|
|
|
|
-// -enable-experimental-feature requires and asserts build
|
|
+// -enable-experimental-feature requires an asserts build
|
|
// REQUIRES: asserts
|
|
|
|
func test1(x: Int, fn: (Int) -> Int) -> Int {
|
|
@@ -25,11 +26,11 @@ func test3(y: Int) -> Int {
|
|
return x
|
|
}
|
|
|
|
-func test4(_ b: Bool) -> Int {
|
|
- if b { 0 } else { 1 }
|
|
+func test4(_ b: [Bool]) -> Int {
|
|
+ if b.isEmpty { 0 } else { 1 }
|
|
}
|
|
|
|
-func test5(_ b: Bool) -> Int {
|
|
+func test5(_ b: Swift.Bool) -> Int {
|
|
return if b { 0 } else { 1 }
|
|
}
|
|
|
|
@@ -37,3 +38,12 @@ func test6(_ b: Bool) -> Int {
|
|
let x = if b { 0 } else { 1 }
|
|
return x
|
|
}
|
|
+
|
|
+func test7(_ b: inout Bool) {
|
|
+ // b = true
|
|
+}
|
|
+
|
|
+func test8(_ i: _const Int) {
|
|
+}
|
|
+
|
|
+func test9(_ value: Any) { }
|