Skip to content

Commit 1cac584

Browse files
committed
[Variadic Generics] Parse contexutal 'each' in expression context as a
pack element expression.
1 parent 2c1a466 commit 1cac584

File tree

2 files changed

+95
-8
lines changed

2 files changed

+95
-8
lines changed

Sources/SwiftParser/Expressions.swift

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1020,13 +1020,20 @@ extension Parser {
10201020
return RawExprSyntax(RawUnresolvedPatternExprSyntax(pattern: pattern, arena: self.arena))
10211021
}
10221022

1023-
// 'any' followed by another identifier is an existential type.
1024-
if self.atContextualKeyword("any"),
1025-
self.peek().tokenKind == .identifier,
1026-
!self.peek().isAtStartOfLine
1027-
{
1028-
let ty = self.parseType()
1029-
return RawExprSyntax(RawTypeExprSyntax(type: ty, arena: self.arena))
1023+
// We might have a contextual keyword followed by an identifier.
1024+
// 'each <identifier>' is a pack element expr, and 'any <identifier>'
1025+
// is an existential type expr.
1026+
if self.peek().tokenKind == .identifier, !self.peek().isAtStartOfLine {
1027+
if self.atContextualKeyword("any") {
1028+
let ty = self.parseType()
1029+
return RawExprSyntax(RawTypeExprSyntax(type: ty, arena: self.arena))
1030+
}
1031+
1032+
if let each = self.consumeIfContextualKeyword("each") {
1033+
let packRef = self.parseExpression()
1034+
return RawExprSyntax(RawPackElementExprSyntax(
1035+
eachKeyword: each, packRefExpr: packRef, arena: self.arena))
1036+
}
10301037
}
10311038

10321039
return RawExprSyntax(self.parseIdentifierExpression())

Tests/SwiftParserTest/VariadicGenericsTests.swift

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
13+
@_spi(RawSyntax) import SwiftSyntax
1414
import XCTest
1515

1616
final class VariadicGenericsTests: XCTestCase {
@@ -60,4 +60,84 @@ final class VariadicGenericsTests: XCTestCase {
6060
]
6161
)
6262
}
63+
64+
func testPackElementExprSimple() {
65+
AssertParse(
66+
"""
67+
func tuplify<T...>(_ t: (each T)...) -> ((each T)...) {
68+
return ((each t)...)
69+
}
70+
"""
71+
)
72+
73+
AssertParse(
74+
"""
75+
func zip<T..., U...>(_ first: T..., with second: U...) -> ((T, U)...) {
76+
return ((each first, each second)...)
77+
}
78+
"""
79+
)
80+
81+
AssertParse(
82+
"""
83+
func variadicMap<T..., Result...>(_ t: T..., transform: ((T) -> Result)...) -> (Result...) {
84+
return ((each transform)(each t)...)
85+
}
86+
"""
87+
)
88+
}
89+
90+
func testEachExprContextualKeyword() {
91+
let callExpr = FunctionCallExprSyntax(
92+
calledExpression: IdentifierExprSyntax(
93+
identifier: .identifier("each")
94+
),
95+
leftParen: .leftParen,
96+
argumentList: TupleExprElementListSyntax([
97+
.init(expression:
98+
IdentifierExprSyntax(
99+
identifier: .identifier("x")
100+
)
101+
)
102+
]),
103+
rightParen: .rightParen
104+
)
105+
106+
AssertParse(
107+
"""
108+
func test() {
109+
1️⃣each(x)
110+
}
111+
""",
112+
substructure: Syntax(callExpr),
113+
substructureAfterMarker: "1️⃣"
114+
)
115+
116+
AssertParse(
117+
"""
118+
func test() {
119+
1️⃣each (x)
120+
}
121+
""",
122+
substructure: Syntax(callExpr),
123+
substructureAfterMarker: "1️⃣"
124+
)
125+
126+
AssertParse(
127+
"""
128+
func test() {
129+
1️⃣each x
130+
}
131+
""",
132+
substructure: Syntax(
133+
PackElementExprSyntax(
134+
eachKeyword: .contextualKeyword("each"),
135+
packRefExpr: IdentifierExprSyntax(
136+
identifier: .identifier("x")
137+
)
138+
)
139+
),
140+
substructureAfterMarker: "1️⃣"
141+
)
142+
}
63143
}

0 commit comments

Comments
 (0)