Skip to content

Commit a68a01c

Browse files
authored
[Swift Parser] Add concurrency support (#27)
* Recognize await keyword * Add parsing for async sequences * Add parsing for parallel async declaration * Add parsing for actor types
1 parent fb9d8f1 commit a68a01c

File tree

2 files changed

+93
-6
lines changed

2 files changed

+93
-6
lines changed

src/providers/swift/parsing/parser.ml

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ and keywords = [
164164
"throws";
165165
"true";
166166
"try";
167+
"await";
167168
]
168169

169170
and identifier () = identifier' keywords
@@ -937,6 +938,12 @@ and tryOperator () =
937938
<|> wstring "try"
938939
) >>= mkString
939940

941+
(*| await-operator -> "await" |*)
942+
and awaitOperator () =
943+
(
944+
wstring "await"
945+
) >>= mkString
946+
940947
(*| GRAMMAR OF AN ASSIGNMENT OPERATOR |*)
941948

942949
(*| assignment-operator -> "=" |*)
@@ -1466,11 +1473,13 @@ and binaryExpression ~allowAssignment ~allowTrailingClosure ~allowTypeAnnotation
14661473
mkNode "AssignmentExpression"
14671474
<:> mkProp "Assignee" (return exp)
14681475
<* assignmentOperator ()
1476+
<:> mkOptPropE "Await" awaitOperator
14691477
<:> mkOptPropE "Try" tryOperator
14701478
<:> mkPropE "Value" (prefixExpression ~allowTrailingClosure ~allowTypeAnnotation)
14711479
and conditionalExpression () =
14721480
mkNode "ConditionalExpression"
14731481
<:> conditionalOperator ()
1482+
<:> mkOptPropE "Await" awaitOperator
14741483
<:> mkOptPropE "AlternateTry" tryOperator
14751484
<:> mkPropE "Alternate" (prefixExpression ~allowTrailingClosure ~allowTypeAnnotation)
14761485
and typeCastingExpression () =
@@ -1510,17 +1519,25 @@ and binaryExpressions ~allowAssignment ~allowTrailingClosure ~allowTypeAnnotatio
15101519

15111520
(*| GRAMMAR OF AN EXPRESSION |*)
15121521

1513-
(*| expression -> try-operator ??? prefix-expression binary-expressions ??? |*)
1522+
(*| expression -> await-operator ??? try-operator ??? prefix-expression binary-expressions ??? |*)
15141523
and expression
15151524
?allowAssignment:(allowAssignment:bool = true)
15161525
?allowTrailingClosure:(allowTrailingClosure:bool = true)
15171526
?(allowTypeAnnotation=true)
15181527
_
15191528
=
1520-
mkOptE tryOperator >>= fun tryop ->
1521-
prefixExpression ~allowTrailingClosure ~allowTypeAnnotation () >>= fun pre ->
1522-
option pre (binaryExpressions ~allowAssignment ~allowTrailingClosure ~allowTypeAnnotation pre)
1523-
<:> mkProp "Try" (return tryop)
1529+
mkOptE tryOperator
1530+
>>=
1531+
fun tryop ->
1532+
mkOptE awaitOperator
1533+
>>=
1534+
fun awaitop ->
1535+
prefixExpression ~allowTrailingClosure ~allowTypeAnnotation ()
1536+
>>=
1537+
fun pre ->
1538+
option pre (binaryExpressions ~allowAssignment ~allowTrailingClosure ~allowTypeAnnotation pre)
1539+
<:> mkProp "Try" (return tryop)
1540+
<:> mkProp "Await" (return awaitop)
15241541

15251542
(*| expression-list -> expression | expression "," expression-list |*)
15261543
and expressionList () =
@@ -1630,11 +1647,18 @@ and loopStatement () =
16301647

16311648
(*| GRAMMAR OF A FOR-IN STATEMENT |*)
16321649

1650+
(*| async-sequence-operator -> "try ??? await" |*)
1651+
and asyncSequenceOperator () =
1652+
(wstring "await") <|> (wstring "try" *> anyspace *> wstring "await")
1653+
1654+
16331655
(*| for-in-statement -> "for" "case ???" pattern "in" expression where-clause ??? code-block |*)
1656+
(*| for-in-statement -> "for" async-sequence-operator ??? pattern "in" expression where-clause ??? code-block |*)
16341657
and forInStatement () =
16351658
mkNode "ForInStatement"
16361659
<* wstring "for"
16371660
<:> mkOptPropEmpty (mkBoolProp "Case" (wstring "case"))
1661+
<:> mkOptPropEmpty (mkBoolProp "AsyncSequence" (asyncSequenceOperator ()))
16381662
<:> mkProp "Pattern" (fix (pattern ~allowExpression:false))
16391663
<* wstring "in"
16401664
<:> mkProp "Condition" (fix (expression ~allowTrailingClosure:false))
@@ -2591,6 +2615,13 @@ and classMembers () =
25912615
and classBody () =
25922616
wchar '{' *> mkOptE classMembers <* wchar '}'
25932617

2618+
(*| reference-type -> class | actor |*)
2619+
and referenceType () =
2620+
(
2621+
mkBoolProp "Actor" (wstring "actor")
2622+
<|> (wstring "class" *> mkPropHolder)
2623+
)
2624+
25942625
(*| class-declaration -> attributes??? access-level-modifier??? "final"??? "class" class-name generic-parameter-clause??? type-inheritance-clause??? generic-where-clause??? class-body |*)
25952626
(*| class-declaration -> attributes??? "final" access-level-modifier??? "class" class-name generic-parameter-clause??? type-inheritance-clause??? generic-where-clause??? class-body |*)
25962627
and classDeclaration () =
@@ -2605,7 +2636,7 @@ and classDeclaration () =
26052636
<:> mkOptPropEmpty (mkBoolProp "Final" (wstring "final"))
26062637
)
26072638
)
2608-
<* wstring "class"
2639+
<:> referenceType ()
26092640
<:> mkPropE "ClassName" className
26102641
<:> mkOptPropE "GenericParameterClause" genericParameterClause
26112642
<:> mkOptPropE "TypeInheritanceClause" typeInheritanceClause
@@ -2951,6 +2982,8 @@ and declarationModifier () =
29512982
<|>
29522983
mkBoolProp "Weak" (wstring "weak")
29532984
<|>
2985+
mkBoolProp "ParallelAsync" (wstring "async")
2986+
<|>
29542987
accessLevelModifier ()
29552988
<|>
29562989
mutationModifier ()
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// RUN: %neal-swift
2+
3+
// Await keyword
4+
let photoNames = try listPhotos(inGallery: "Summer Vacation")
5+
let photoNames = try await listPhotos(inGallery: "Summer Vacation")
6+
let photoNames = await listPhotos(inGallery: "Summer Vacation")
7+
await listPhotos(inGallery: "Summer Vacation")
8+
9+
func listPhotos(inGallery name: String) async throws -> [String] {
10+
try await Task.sleep(nanoseconds: 2 * 1_000_000_000)
11+
return ["IMG001", "IMG99", "IMG0404"]
12+
}
13+
14+
// Asynchronous Sequences
15+
for try await line in handle.bytes.lines {
16+
print(line)
17+
}
18+
19+
for await line in handle.bytes.lines {
20+
print(line)
21+
}
22+
23+
// Parallel execution
24+
async let firstPhoto = downloadPhoto(named: photoNames[0])
25+
async let secondPhoto = downloadPhoto(named: photoNames[1])
26+
async let thirdPhoto = downloadPhoto(named: photoNames[2])
27+
28+
let photos = await [firstPhoto, secondPhoto, thirdPhoto]
29+
30+
// Task Group
31+
await withTaskGroup(of: Data.self) { taskGroup in
32+
let photoNames = await listPhotos(inGallery: "Summer Vacation")
33+
for name in photoNames {
34+
taskGroup.addTask { await downloadPhoto(named: name) }
35+
}
36+
}
37+
38+
let handle = Task {
39+
return await add(newPhoto, toGalleryNamed: "Spring Adventures")
40+
}
41+
let result = await handle.value
42+
43+
// Actor
44+
actor TemperatureLogger {
45+
let label: String
46+
var measurements: [Int]
47+
private(set) var max: Int
48+
49+
init(label: String, measurement: Int) {
50+
self.label = label
51+
self.measurements = [measurement]
52+
self.max = measurement
53+
}
54+
}

0 commit comments

Comments
 (0)