Skip to content

Commit 9ddd60d

Browse files
authored
libSyntax: create syntax nodes for closure signature. (#13415)
This patch also refactors the structure of function signature node so that closure signature can re-use parts of function signature. For instance, we group arrow and return type to be "ReturnClause". And we group parenthesized parameter list to be "ParamClause". This structure of closure signature also calls for a good way to represent either-or node in libSyntax APIs, since we've two ways to specify parameters in closure: one is as regular function parameter and the other is dot-separated simple names.
1 parent 079796e commit 9ddd60d

File tree

7 files changed

+126
-68
lines changed

7 files changed

+126
-68
lines changed

lib/Parse/ParseExpr.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2375,7 +2375,7 @@ parseClosureSignatureIfPresent(SmallVectorImpl<CaptureListEntry> &captureList,
23752375
// No closure signature.
23762376
return false;
23772377
}
2378-
2378+
SyntaxParsingContext ClosureSigCtx(SyntaxContext, SyntaxKind::ClosureSignature);
23792379
if (Tok.is(tok::l_square) && peekToken().is(tok::r_square)) {
23802380
SyntaxParsingContext CaptureCtx(SyntaxContext,
23812381
SyntaxKind::ClosureCaptureSignature);
@@ -2509,9 +2509,13 @@ parseClosureSignatureIfPresent(SmallVectorImpl<CaptureListEntry> &captureList,
25092509
else
25102510
invalid = true;
25112511
} else {
2512+
SyntaxParsingContext ClParamListCtx(SyntaxContext,
2513+
SyntaxKind::ClosureParamList);
25122514
// Parse identifier (',' identifier)*
25132515
SmallVector<ParamDecl*, 4> elements;
2516+
bool HasNext;
25142517
do {
2518+
SyntaxParsingContext ClParamCtx(SyntaxContext, SyntaxKind::ClosureParam);
25152519
if (Tok.isNot(tok::identifier, tok::kw__)) {
25162520
diagnose(Tok, diag::expected_closure_parameter_name);
25172521
invalid = true;
@@ -2525,9 +2529,10 @@ parseClosureSignatureIfPresent(SmallVectorImpl<CaptureListEntry> &captureList,
25252529
Tok.getLoc(), name, Type(), nullptr);
25262530
elements.push_back(var);
25272531
consumeToken();
2528-
2532+
25292533
// Consume a comma to continue.
2530-
} while (consumeIf(tok::comma));
2534+
HasNext = consumeIf(tok::comma);
2535+
} while (HasNext);
25312536

25322537
params = ParameterList::create(Context, elements);
25332538
}
@@ -2542,6 +2547,7 @@ parseClosureSignatureIfPresent(SmallVectorImpl<CaptureListEntry> &captureList,
25422547

25432548
// Parse the optional explicit return type.
25442549
if (Tok.is(tok::arrow)) {
2550+
SyntaxParsingContext ReturnCtx(SyntaxContext, SyntaxKind::ReturnClause);
25452551
// Consume the '->'.
25462552
arrowLoc = consumeToken();
25472553

lib/Parse/ParsePattern.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ Parser::parseParameterClause(SourceLoc &leftParenLoc,
152152
ParameterContextKind paramContext) {
153153
assert(params.empty() && leftParenLoc.isInvalid() &&
154154
rightParenLoc.isInvalid() && "Must start with empty state");
155+
SyntaxParsingContext ParamClauseCtx(SyntaxContext, SyntaxKind::ParameterClause);
155156

156157
// Consume the starting '(';
157158
leftParenLoc = consumeToken(tok::l_paren);
@@ -719,6 +720,7 @@ Parser::parseFunctionSignature(Identifier SimpleName,
719720

720721
// If there's a trailing arrow, parse the rest as the result type.
721722
if (Tok.isAny(tok::arrow, tok::colon)) {
723+
SyntaxParsingContext ReturnCtx(SyntaxContext, SyntaxKind::ReturnClause);
722724
if (!consumeIf(tok::arrow, arrowLoc)) {
723725
// FixIt ':' to '->'.
724726
diagnose(Tok, diag::func_decl_expected_arrow)

test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds

Lines changed: 41 additions & 27 deletions
Large diffs are not rendered by default.

test/Syntax/round_trip_parse_gen.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,4 +135,18 @@ func closure() {
135135
unowned(unsafe) c = foo().bar] in
136136
}
137137
{[] in }
138+
139+
{ [] a, b, _ -> Int in
140+
return 2
141+
}
142+
{ [] (a: Int, b: Int, _: Int) -> Int in
143+
return 2
144+
}
145+
{ [] a, b, _ throws -> Int in
146+
return 2
147+
}
148+
{ [] (a: Int, _ b: Int) throws -> Int in
149+
return 2
150+
}
151+
{ a, b in }
138152
}

unittests/Syntax/DeclSyntaxTests.cpp

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -358,13 +358,13 @@ FunctionSignatureSyntax getCannedFunctionSignature() {
358358
.appending(Param)
359359
.castTo<FunctionParameterListSyntax>();
360360
auto RParen = SyntaxFactory::makeRightParenToken({}, Trivia::spaces(1));
361+
auto Parameter = SyntaxFactory::makeParameterClause(LParen, List, RParen);
361362
auto Throws = SyntaxFactory::makeThrowsKeyword({}, Trivia::spaces(1));
362363
auto Arrow = SyntaxFactory::makeArrowToken({}, Trivia::spaces(1));
363-
auto NoAttributes = SyntaxFactory::makeBlankAttributeList();
364364
auto Int = SyntaxFactory::makeTypeIdentifier("Int", {}, Trivia::spaces(1));
365+
auto Return = SyntaxFactory::makeReturnClause(Arrow, Int);
365366

366-
return SyntaxFactory::makeFunctionSignature(LParen, List, RParen, Throws,
367-
Arrow, NoAttributes, Int);
367+
return SyntaxFactory::makeFunctionSignature(Parameter, Throws, Return);
368368
}
369369

370370
TEST(DeclSyntaxTests, FunctionSignatureMakeAPIs) {
@@ -396,19 +396,21 @@ TEST(DeclSyntaxTests, FunctionSignatureGetAPIs) {
396396
auto RParen = SyntaxFactory::makeRightParenToken({}, Trivia::spaces(1));
397397
auto Throws = SyntaxFactory::makeThrowsKeyword({}, Trivia::spaces(1));
398398
auto Arrow = SyntaxFactory::makeArrowToken({}, Trivia::spaces(1));
399-
auto NoAttributes = SyntaxFactory::makeBlankAttributeList();
399+
400400
auto Int = SyntaxFactory::makeTypeIdentifier("Int", {}, {});
401401

402-
auto Sig = SyntaxFactory::makeFunctionSignature(LParen, List, RParen, Throws,
403-
Arrow, NoAttributes, Int);
402+
auto Sig = SyntaxFactory::makeFunctionSignature(
403+
SyntaxFactory::makeParameterClause(LParen, List, RParen),
404+
Throws,
405+
SyntaxFactory::makeReturnClause(Arrow, Int));
404406

405-
ASSERT_EQ(LParen.getRaw(), Sig.getLeftParen().getRaw());
407+
ASSERT_EQ(LParen.getRaw(), Sig.getInput().getLeftParen().getRaw());
406408

407409
{
408410
SmallString<48> Scratch;
409411
llvm::raw_svector_ostream OS(Scratch);
410-
auto GottenList1 = Sig.getParameterList();
411-
auto GottenList2 = Sig.getParameterList();
412+
auto GottenList1 = Sig.getInput().getParameterList();
413+
auto GottenList2 = Sig.getInput().getParameterList();
412414
ASSERT_TRUE(GottenList1.hasSameIdentityAs(GottenList2));
413415
GottenList1.print(OS);
414416
ASSERT_EQ(OS.str().str(),
@@ -417,25 +419,16 @@ TEST(DeclSyntaxTests, FunctionSignatureGetAPIs) {
417419
"with radius: Int = -1, ");
418420
}
419421

420-
ASSERT_EQ(RParen.getRaw(), Sig.getRightParen().getRaw());
422+
ASSERT_EQ(RParen.getRaw(), Sig.getInput().getRightParen().getRaw());
421423
ASSERT_EQ(Throws.getRaw(), Sig.getThrowsOrRethrowsKeyword()->getRaw());
422424
ASSERT_EQ(Sig.getThrowsOrRethrowsKeyword()->getTokenKind(), tok::kw_throws);
423-
ASSERT_EQ(Arrow.getRaw(), Sig.getArrow()->getRaw());
424-
425-
{
426-
SmallString<48> Scratch;
427-
llvm::raw_svector_ostream OS(Scratch);
428-
auto GottenAttrs1 = Sig.getReturnTypeAttributes().getValue();
429-
auto GottenAttrs2 = Sig.getReturnTypeAttributes().getValue();
430-
ASSERT_TRUE(GottenAttrs1.hasSameIdentityAs(GottenAttrs2));
431-
ASSERT_EQ(OS.str().str(), "");
432-
}
425+
ASSERT_EQ(Arrow.getRaw(), Sig.getOutput()->getArrow().getRaw());
433426

434427
{
435428
SmallString<3> Scratch;
436429
llvm::raw_svector_ostream OS(Scratch);
437-
auto GottenReturnType1 = Sig.getReturnType().getValue();
438-
auto GottenReturnType2 = Sig.getReturnType().getValue();
430+
auto GottenReturnType1 = Sig.getOutput()->getReturnType();
431+
auto GottenReturnType2 = Sig.getOutput()->getReturnType();
439432
ASSERT_TRUE(GottenReturnType1.hasSameIdentityAs(GottenReturnType2));
440433
GottenReturnType1.print(OS);
441434
ASSERT_EQ(OS.str().str(), "Int");
@@ -453,19 +446,16 @@ TEST(DeclSyntaxTests, FunctionSignatureWithAPIs) {
453446
auto RParen = SyntaxFactory::makeRightParenToken({}, Trivia::spaces(1));
454447
auto Throws = SyntaxFactory::makeThrowsKeyword({}, Trivia::spaces(1));
455448
auto Arrow = SyntaxFactory::makeArrowToken({}, Trivia::spaces(1));
456-
auto NoAttributes = SyntaxFactory::makeBlankAttributeList();
457449
auto Int = SyntaxFactory::makeTypeIdentifier("Int", {}, {});
458450

451+
auto Parameter = SyntaxFactory::makeParameterClause(LParen, List, RParen);
452+
auto Return = SyntaxFactory::makeReturnClause(Arrow, Int);
459453
SmallString<48> Scratch;
460454
llvm::raw_svector_ostream OS(Scratch);
461455
SyntaxFactory::makeBlankFunctionSignature()
462-
.withLeftParen(LParen)
463-
.withParameterList(List)
464-
.withRightParen(RParen)
456+
.withInput(Parameter)
465457
.withThrowsOrRethrowsKeyword(Throws)
466-
.withReturnTypeAttributes(NoAttributes)
467-
.withArrow(Arrow)
468-
.withReturnType(Int)
458+
.withOutput(Return)
469459
.print(OS);
470460
ASSERT_EQ(OS.str().str(),
471461
"(with radius: Int = -1, "

utils/gyb_syntax_support/DeclNodes.py

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,25 +26,32 @@
2626
Node('FunctionParameterList', kind='SyntaxCollection',
2727
element='FunctionParameter'),
2828

29-
# function-signature ->
30-
# '(' parameter-list? ')' (throws | rethrows)? '->'? attributes? type?
31-
Node('FunctionSignature', kind='Syntax',
29+
Node('ParameterClause', kind='Syntax',
3230
children=[
3331
Child('LeftParen', kind='LeftParenToken'),
3432
Child('ParameterList', kind='FunctionParameterList'),
3533
Child('RightParen', kind='RightParenToken'),
34+
]),
35+
36+
# -> Type
37+
Node('ReturnClause', kind='Syntax',
38+
children=[
39+
Child('Arrow', kind='ArrowToken'),
40+
Child('ReturnType', kind='Type'),
41+
]),
42+
43+
# function-signature ->
44+
# '(' parameter-list? ')' (throws | rethrows)? '->'? type?
45+
Node('FunctionSignature', kind='Syntax',
46+
children=[
47+
Child('Input', kind='ParameterClause'),
3648
Child('ThrowsOrRethrowsKeyword', kind='Token',
3749
is_optional=True,
3850
token_choices=[
3951
'ThrowsToken',
4052
'RethrowsToken',
4153
]),
42-
Child('Arrow', kind='ArrowToken',
43-
is_optional=True),
44-
Child('ReturnTypeAttributes', kind='AttributeList',
45-
is_optional=True),
46-
Child('ReturnType', kind='Type',
47-
is_optional=True),
54+
Child('Output', kind='ReturnClause', is_optional=True),
4855
]),
4956

5057
# else-if-directive-clause -> '#elseif' expr stmt-list

utils/gyb_syntax_support/ExprNodes.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,4 +282,29 @@
282282
Child('Items', kind='ClosureCaptureItemList', is_optional=True),
283283
Child('RightSquare', kind='RightSquareToken'),
284284
]),
285+
286+
Node('ClosureParam', kind='Syntax',
287+
children=[
288+
Child('Name', kind='Token',
289+
token_choices=[
290+
'IdentifierToken',
291+
'WildcardToken',
292+
]),
293+
Child('TrailingComma', kind='CommaToken', is_optional=True),
294+
]),
295+
296+
# a, b, c
297+
Node('ClosureParamList', kind='SyntaxCollection', element='ClosureParam'),
298+
299+
Node('ClosureSignature', kind='Syntax',
300+
children=[
301+
Child('Capture', kind='ClosureCaptureSignature',
302+
is_optional=True),
303+
# FIXME: one and only one of these two children is required
304+
Child('SimpleInput', kind='ClosureParamList', is_optional=True),
305+
Child('Input', kind='ParameterClause', is_optional=True),
306+
Child('ThrowsTok', kind='ThrowsToken', is_optional=True),
307+
Child('Output', kind='ReturnClause', is_optional=True),
308+
Child('InTok', kind='InToken'),
309+
]),
285310
]

0 commit comments

Comments
 (0)