Skip to content

Commit 1105309

Browse files
authored
Merge pull request #71631 from rintaro/astgen-trailingclosure
[ASTGen] Generate trailing closures
2 parents de50b0a + c8be142 commit 1105309

File tree

5 files changed

+222
-80
lines changed

5 files changed

+222
-80
lines changed

include/swift/AST/ASTBridging.h

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "swift/Basic/BasicBridging.h"
2323

2424
#ifdef USED_IN_CPP_SOURCE
25+
#include "swift/AST/ArgumentList.h"
2526
#include "swift/AST/Attr.h"
2627
#include "swift/AST/DiagnosticConsumer.h"
2728
#include "swift/AST/DiagnosticEngine.h"
@@ -1037,6 +1038,26 @@ BridgedVarDecl_asAbstractStorageDecl(BridgedVarDecl decl);
10371038
// MARK: Exprs
10381039
//===----------------------------------------------------------------------===//
10391040

1041+
struct BridgedCallArgument {
1042+
BridgedSourceLoc labelLoc;
1043+
BridgedIdentifier label;
1044+
BridgedExpr argExpr;
1045+
1046+
#ifdef USED_IN_CPP_SOURCE
1047+
swift::Argument unbridged() const {
1048+
return swift::Argument(labelLoc.unbridged(), label.unbridged(),
1049+
argExpr.unbridged());
1050+
}
1051+
#endif
1052+
};
1053+
1054+
SWIFT_NAME("BridgedArgumentList.createParsed(_:lParenLoc:args:rParenLoc:"
1055+
"firstTrailingClosureIndex:)")
1056+
BridgedArgumentList BridgedArgumentList_createParsed(
1057+
BridgedASTContext cContext, BridgedSourceLoc cLParenLoc,
1058+
BridgedArrayRef cArgs, BridgedSourceLoc cRParenLoc,
1059+
size_t cFirstTrailingClosureIndex);
1060+
10401061
SWIFT_NAME("BridgedArrayExpr.createParsed(_:lSquareLoc:elements:commaLocs:"
10411062
"rSquareLoc:)")
10421063
BridgedArrayExpr BridgedArrayExpr_createParsed(BridgedASTContext cContext,
@@ -1075,13 +1096,12 @@ BridgedBorrowExpr BridgedBorrowExpr_createParsed(BridgedASTContext cContext,
10751096
SWIFT_NAME("BridgedCallExpr.createParsed(_:fn:args:)")
10761097
BridgedCallExpr BridgedCallExpr_createParsed(BridgedASTContext cContext,
10771098
BridgedExpr fn,
1078-
BridgedTupleExpr args);
1099+
BridgedArgumentList args);
10791100

1080-
SWIFT_NAME("BridgedClosureExpr.createParsed(_:declContext:body:)")
1081-
BridgedClosureExpr
1082-
BridgedClosureExpr_createParsed(BridgedASTContext cContext,
1083-
BridgedDeclContext cDeclContext,
1084-
BridgedBraceStmt body);
1101+
SWIFT_NAME("BridgedClosureExpr.createParsed(_:declContext:parameterList:body:)")
1102+
BridgedClosureExpr BridgedClosureExpr_createParsed(
1103+
BridgedASTContext cContext, BridgedDeclContext cDeclContext,
1104+
BridgedParameterList cParamList, BridgedBraceStmt body);
10851105

10861106
SWIFT_NAME("BridgedCoerceExpr.createParsed(_:asLoc:type:)")
10871107
BridgedCoerceExpr BridgedCoerceExpr_createParsed(BridgedASTContext cContext,

lib/AST/ASTBridging.cpp

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1355,6 +1355,25 @@ bool BridgedNominalTypeDecl_isStructWithUnreferenceableStorage(
13551355
// MARK: Exprs
13561356
//===----------------------------------------------------------------------===//
13571357

1358+
BridgedArgumentList BridgedArgumentList_createParsed(
1359+
BridgedASTContext cContext, BridgedSourceLoc cLParenLoc,
1360+
BridgedArrayRef cArgs, BridgedSourceLoc cRParenLoc,
1361+
size_t cFirstTrailingClosureIndex) {
1362+
SmallVector<Argument> arguments;
1363+
arguments.reserve(cArgs.unbridged<BridgedCallArgument>().size());
1364+
for (auto &arg : cArgs.unbridged<BridgedCallArgument>()) {
1365+
arguments.push_back(arg.unbridged());
1366+
}
1367+
1368+
std::optional<unsigned int> firstTrailingClosureIndex;
1369+
if (cFirstTrailingClosureIndex < arguments.size())
1370+
firstTrailingClosureIndex = cFirstTrailingClosureIndex;
1371+
1372+
return ArgumentList::createParsed(
1373+
cContext.unbridged(), cLParenLoc.unbridged(), arguments,
1374+
cRParenLoc.unbridged(), firstTrailingClosureIndex);
1375+
}
1376+
13581377
BridgedArrayExpr BridgedArrayExpr_createParsed(BridgedASTContext cContext,
13591378
BridgedSourceLoc cLLoc,
13601379
BridgedArrayRef elements,
@@ -1404,25 +1423,15 @@ BridgedBorrowExpr BridgedBorrowExpr_createParsed(BridgedASTContext cContext,
14041423

14051424
BridgedCallExpr BridgedCallExpr_createParsed(BridgedASTContext cContext,
14061425
BridgedExpr fn,
1407-
BridgedTupleExpr args) {
1408-
ASTContext &context = cContext.unbridged();
1409-
TupleExpr *TE = args.unbridged();
1410-
SmallVector<Argument, 8> arguments;
1411-
for (unsigned i = 0; i < TE->getNumElements(); ++i) {
1412-
arguments.emplace_back(TE->getElementNameLoc(i), TE->getElementName(i),
1413-
TE->getElement(i));
1414-
}
1415-
auto *argList = ArgumentList::create(context, TE->getLParenLoc(), arguments,
1416-
TE->getRParenLoc(), llvm::None,
1417-
/*isImplicit*/ false);
1418-
return CallExpr::create(context, fn.unbridged(), argList,
1426+
BridgedArgumentList cArguments) {
1427+
return CallExpr::create(cContext.unbridged(), fn.unbridged(),
1428+
cArguments.unbridged(),
14191429
/*implicit*/ false);
14201430
}
14211431

1422-
BridgedClosureExpr
1423-
BridgedClosureExpr_createParsed(BridgedASTContext cContext,
1424-
BridgedDeclContext cDeclContext,
1425-
BridgedBraceStmt body) {
1432+
BridgedClosureExpr BridgedClosureExpr_createParsed(
1433+
BridgedASTContext cContext, BridgedDeclContext cDeclContext,
1434+
BridgedParameterList cParamList, BridgedBraceStmt body) {
14261435
DeclAttributes attributes;
14271436
SourceRange bracketRange;
14281437
SourceLoc asyncLoc;
@@ -1433,13 +1442,11 @@ BridgedClosureExpr_createParsed(BridgedASTContext cContext,
14331442
ASTContext &context = cContext.unbridged();
14341443
DeclContext *declContext = cDeclContext.unbridged();
14351444

1436-
auto params = ParameterList::create(context, inLoc, {}, inLoc);
1437-
14381445
auto *out = new (context) ClosureExpr(
1439-
attributes, bracketRange, nullptr, nullptr, asyncLoc, throwsLoc,
1446+
attributes, bracketRange, nullptr, cParamList.unbridged(), asyncLoc,
1447+
throwsLoc,
14401448
/*FIXME:thrownType=*/nullptr, arrowLoc, inLoc, nullptr, declContext);
14411449
out->setBody(body.unbridged());
1442-
out->setParameterList(params);
14431450
return out;
14441451
}
14451452

lib/ASTGen/Sources/ASTGen/Bridge.swift

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,3 +236,45 @@ extension BridgedSourceRange {
236236
self = astgen.generateSourceRange(start: startToken, end: endToken)
237237
}
238238
}
239+
240+
/// Helper collection type that lazily concatenates two collections.
241+
struct ConcatCollection<C1: Collection, C2: Collection> where C1.Element == C2.Element {
242+
let c1: C1
243+
let c2: C2
244+
245+
init(_ c1: C1, _ c2: C2) {
246+
self.c1 = c1
247+
self.c2 = c2
248+
}
249+
}
250+
251+
extension ConcatCollection: LazyCollectionProtocol {
252+
typealias Element = C1.Element
253+
enum Index: Comparable {
254+
case c1(C1.Index)
255+
case c2(C2.Index)
256+
}
257+
258+
var count: Int { c1.count + c2.count }
259+
260+
private func _normalizedIndex(_ i: C1.Index) -> Index {
261+
return i != c1.endIndex ? .c1(i) : .c2(c2.startIndex)
262+
}
263+
264+
var startIndex: Index { _normalizedIndex(c1.startIndex) }
265+
var endIndex: Index { .c2(c2.endIndex) }
266+
267+
func index(after i: Index) -> Index {
268+
switch i {
269+
case .c1(let i): return _normalizedIndex(c1.index(after: i))
270+
case .c2(let i): return .c2(c2.index(after: i))
271+
}
272+
}
273+
274+
subscript(i: Index) -> Element {
275+
switch i {
276+
case .c1(let i): return c1[i]
277+
case .c2(let i): return c2[i]
278+
}
279+
}
280+
}

lib/ASTGen/Sources/ASTGen/Exprs.swift

Lines changed: 115 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -262,15 +262,34 @@ extension ASTGenVisitor {
262262
}
263263

264264
func generate(closureExpr node: ClosureExprSyntax) -> BridgedClosureExpr {
265+
let params: BridgedParameterList
266+
267+
if let signature = node.signature {
268+
// FIXME: Translate the signature, capture list, 'in' location, etc.
269+
fatalError("unimplmented")
270+
} else {
271+
let lBraceLoc = self.generateSourceLoc(node.leftBrace)
272+
params = BridgedParameterList.createParsed(
273+
self.ctx,
274+
leftParenLoc: lBraceLoc,
275+
parameters: .init(),
276+
rightParenLoc: lBraceLoc
277+
)
278+
}
279+
265280
let body = BridgedBraceStmt.createParsed(
266281
self.ctx,
267282
lBraceLoc: self.generateSourceLoc(node.leftBrace),
268283
elements: self.generate(codeBlockItemList: node.statements),
269284
rBraceLoc: self.generateSourceLoc(node.rightBrace)
270285
)
271286

272-
// FIXME: Translate the signature, capture list, 'in' location, etc.
273-
return .createParsed(self.ctx, declContext: self.declContext, body: body)
287+
return .createParsed(
288+
self.ctx,
289+
declContext: self.declContext,
290+
parameterList: params,
291+
body: body
292+
)
274293
}
275294

276295
func generate(consumeExpr node: ConsumeExprSyntax) -> BridgedConsumeExpr {
@@ -289,6 +308,71 @@ extension ASTGenVisitor {
289308
)
290309
}
291310

311+
func generateArgumentList(
312+
leftParen: TokenSyntax?,
313+
labeledExprList: LabeledExprListSyntax,
314+
rightParen: TokenSyntax?,
315+
trailingClosure: ClosureExprSyntax?,
316+
additionalTrailingClosures: MultipleTrailingClosureElementListSyntax?
317+
) -> BridgedArgumentList {
318+
319+
var bridgedArgs: BridgedArrayRef = {
320+
// Arguments before ')'
321+
let normalArgs = labeledExprList.lazy.map({ elem in
322+
let labelInfo = elem.label.map(self.generateIdentifierAndSourceLoc(_:))
323+
return BridgedCallArgument(
324+
labelLoc: labelInfo?.sourceLoc ?? BridgedSourceLoc(),
325+
label: labelInfo?.identifier ?? BridgedIdentifier(),
326+
argExpr: self.generate(expr: elem.expression)
327+
)
328+
})
329+
guard let trailingClosure else {
330+
// FIXME: Diagnose, instead of precondition.
331+
precondition(
332+
additionalTrailingClosures == nil || additionalTrailingClosures!.isEmpty,
333+
"multiple trailing closures without the first trailing closure"
334+
)
335+
return normalArgs.bridgedArray(in: self)
336+
}
337+
338+
// The first trailing closure.
339+
let bridgedTrailingClosureArg = BridgedCallArgument(
340+
labelLoc: nil,
341+
label: nil,
342+
argExpr: self.generate(closureExpr: trailingClosure).asExpr
343+
)
344+
let normalArgsAndClosure = ConcatCollection(normalArgs, CollectionOfOne(bridgedTrailingClosureArg))
345+
guard let additionalTrailingClosures else {
346+
return normalArgsAndClosure.bridgedArray(in: self)
347+
}
348+
349+
// Remaining trailing closures.
350+
let additions = additionalTrailingClosures.lazy.map { argNode in
351+
return BridgedCallArgument(
352+
labelLoc: self.generateSourceLoc(argNode.label),
353+
label: self.generateIdentifier(argNode.label),
354+
argExpr: self.generate(closureExpr: argNode.closure).asExpr
355+
)
356+
}
357+
let allArgs = ConcatCollection(normalArgsAndClosure, additions)
358+
return allArgs.bridgedArray(in: self)
359+
}()
360+
361+
// This should be "nil" value if there's no trailing closure. Passing the number
362+
// of the normal arguments because we don't have a convenient way to pass
363+
// Optional to ASTBridging, ASTBridging can know it's "nil" if
364+
// bridgedArgs.count == firstTrailingClosureIndex
365+
var firstTrailingClosureIndex = labeledExprList.count
366+
367+
return BridgedArgumentList.createParsed(
368+
self.ctx,
369+
lParenLoc: self.generateSourceLoc(leftParen),
370+
args: bridgedArgs,
371+
rParenLoc: self.generateSourceLoc(rightParen),
372+
firstTrailingClosureIndex: firstTrailingClosureIndex
373+
)
374+
}
375+
292376
func generate(functionCallExpr node: FunctionCallExprSyntax) -> BridgedCallExpr {
293377
if !node.arguments.isEmpty || node.trailingClosure == nil {
294378
if node.leftParen == nil {
@@ -303,29 +387,16 @@ extension ASTGenVisitor {
303387
}
304388
}
305389

306-
var node = node
307-
308-
// Transform the trailing closure into an argument.
309-
if let trailingClosure = node.trailingClosure {
310-
let tupleElement = LabeledExprSyntax(
311-
label: nil,
312-
colon: nil,
313-
expression: ExprSyntax(trailingClosure),
314-
trailingComma: nil
315-
)
316-
317-
node.arguments.append(tupleElement)
318-
node.trailingClosure = nil
319-
}
320-
321-
let argumentTuple = self.generate(
322-
labeledExprList: node.arguments,
390+
let callee = generate(expr: node.calledExpression)
391+
let arguments = generateArgumentList(
323392
leftParen: node.leftParen,
324-
rightParen: node.rightParen
393+
labeledExprList: node.arguments,
394+
rightParen: node.rightParen,
395+
trailingClosure: node.trailingClosure,
396+
additionalTrailingClosures: node.additionalTrailingClosures
325397
)
326-
let callee = generate(expr: node.calledExpression)
327398

328-
return .createParsed(self.ctx, fn: callee, args: argumentTuple)
399+
return .createParsed(self.ctx, fn: callee, args: arguments)
329400
}
330401

331402
func generateDeclNameRef(declReferenceExpr node: DeclReferenceExprSyntax) -> (
@@ -565,7 +636,28 @@ extension ASTGenVisitor {
565636
}
566637

567638
func generate(tupleExpr node: TupleExprSyntax) -> BridgedTupleExpr {
568-
return self.generate(labeledExprList: node.elements, leftParen: node.leftParen, rightParen: node.rightParen)
639+
let expressions = node.elements.lazy.map {
640+
self.generate(expr: $0.expression)
641+
}
642+
let labels = node.elements.lazy.map {
643+
self.generateIdentifier($0.label)
644+
}
645+
let labelLocations = node.elements.lazy.map {
646+
if let label = $0.label {
647+
return self.generateSourceLoc(label)
648+
}
649+
650+
return self.generateSourceLoc($0)
651+
}
652+
653+
return BridgedTupleExpr.createParsed(
654+
self.ctx,
655+
leftParenLoc: self.generateSourceLoc(node.leftParen),
656+
exprs: expressions.bridgedArray(in: self),
657+
labels: labels.bridgedArray(in: self),
658+
labelLocs: labelLocations.bridgedArray(in: self),
659+
rightParenLoc: self.generateSourceLoc(node.rightParen)
660+
)
569661
}
570662

571663
func generate(typeExpr node: TypeExprSyntax) -> BridgedTypeExpr {
@@ -639,35 +731,4 @@ extension ASTGenVisitor {
639731
loc: .createParsed(nameLoc)
640732
);
641733
}
642-
643-
/// Generate a tuple expression from a ``LabeledExprListSyntax`` and parentheses.
644-
func generate(
645-
labeledExprList node: LabeledExprListSyntax,
646-
leftParen: TokenSyntax?,
647-
rightParen: TokenSyntax?
648-
) -> BridgedTupleExpr {
649-
// FIXME: This should return bridged 'ArgumentList' instead of `TupleExpr`
650-
let expressions = node.lazy.map {
651-
self.generate(expr: $0.expression)
652-
}
653-
let labels = node.lazy.map {
654-
self.generateIdentifier($0.label)
655-
}
656-
let labelLocations = node.lazy.map {
657-
if let label = $0.label {
658-
return self.generateSourceLoc(label)
659-
}
660-
661-
return self.generateSourceLoc($0)
662-
}
663-
664-
return BridgedTupleExpr.createParsed(
665-
self.ctx,
666-
leftParenLoc: self.generateSourceLoc(leftParen),
667-
exprs: expressions.bridgedArray(in: self),
668-
labels: labels.bridgedArray(in: self),
669-
labelLocs: labelLocations.bridgedArray(in: self),
670-
rightParenLoc: self.generateSourceLoc(rightParen)
671-
)
672-
}
673734
}

0 commit comments

Comments
 (0)