@@ -27,7 +27,7 @@ trait ExprBuilder {
27
27
28
28
def nextStates : List [Int ]
29
29
30
- def mkHandlerCaseForState : CaseDef
30
+ def mkHandlerCaseForState [ T : WeakTypeTag ] : CaseDef
31
31
32
32
def mkOnCompleteHandler [T : WeakTypeTag ]: Option [CaseDef ] = None
33
33
@@ -51,8 +51,8 @@ trait ExprBuilder {
51
51
def nextStates : List [Int ] =
52
52
List (nextState)
53
53
54
- def mkHandlerCaseForState : CaseDef =
55
- mkHandlerCase(state, stats :+ mkStateTree(nextState, symLookup) :+ mkResumeApply(symLookup) )
54
+ def mkHandlerCaseForState [ T : WeakTypeTag ] : CaseDef =
55
+ mkHandlerCase(state, stats :+ mkStateTree(nextState, symLookup))
56
56
57
57
override val toString : String =
58
58
s " AsyncState # $state, next = $nextState"
@@ -62,7 +62,7 @@ trait ExprBuilder {
62
62
* a branch of an `if` or a `match`.
63
63
*/
64
64
final class AsyncStateWithoutAwait (var stats : List [Tree ], val state : Int , val nextStates : List [Int ]) extends AsyncState {
65
- override def mkHandlerCaseForState : CaseDef =
65
+ override def mkHandlerCaseForState [ T : WeakTypeTag ] : CaseDef =
66
66
mkHandlerCase(state, stats)
67
67
68
68
override val toString : String =
@@ -72,45 +72,54 @@ trait ExprBuilder {
72
72
/** A sequence of statements that concludes with an `await` call. The `onComplete`
73
73
* handler will unconditionally transition to `nextState`.
74
74
*/
75
- final class AsyncStateWithAwait (var stats : List [Tree ], val state : Int , nextState : Int ,
75
+ final class AsyncStateWithAwait (var stats : List [Tree ], val state : Int , onCompleteState : Int , nextState : Int ,
76
76
val awaitable : Awaitable , symLookup : SymLookup )
77
77
extends AsyncState {
78
78
79
79
def nextStates : List [Int ] =
80
80
List (nextState)
81
81
82
- override def mkHandlerCaseForState : CaseDef = {
83
- val callOnComplete = futureSystemOps.onComplete(Expr (awaitable.expr),
84
- Expr (This (tpnme.EMPTY )), Expr (Ident (name.execContext))).tree
85
- mkHandlerCase(state, stats :+ callOnComplete)
82
+ override def mkHandlerCaseForState [T : WeakTypeTag ]: CaseDef = {
83
+ val fun = This (tpnme.EMPTY )
84
+ val callOnComplete = futureSystemOps.onComplete[Any , Unit ](Expr [futureSystem.Fut [Any ]](awaitable.expr),
85
+ Expr [futureSystem.Tryy [Any ] => Unit ](fun), Expr [futureSystem.ExecContext ](Ident (name.execContext))).tree
86
+ val tryGetOrCallOnComplete =
87
+ if (futureSystemOps.continueCompletedFutureOnSameThread)
88
+ If (futureSystemOps.isCompleted(Expr [futureSystem.Fut [_]](awaitable.expr)).tree,
89
+ Block (ifIsFailureTree[T ](futureSystemOps.getCompleted[Any ](Expr [futureSystem.Fut [Any ]](awaitable.expr)).tree) :: Nil , literalUnit),
90
+ Block (callOnComplete :: Nil , Return (literalUnit)))
91
+ else
92
+ Block (callOnComplete :: Nil , Return (literalUnit))
93
+ mkHandlerCase(state, stats ++ List (mkStateTree(onCompleteState, symLookup), tryGetOrCallOnComplete))
86
94
}
87
95
96
+ private def tryGetTree (tryReference : => Tree ) =
97
+ Assign (
98
+ Ident (awaitable.resultName),
99
+ TypeApply (Select (futureSystemOps.tryyGet[Any ](Expr [futureSystem.Tryy [Any ]](tryReference)).tree, newTermName(" asInstanceOf" )), List (TypeTree (awaitable.resultType)))
100
+ )
101
+
102
+ /* if (tr.isFailure)
103
+ * result.complete(tr.asInstanceOf[Try[T]])
104
+ * else {
105
+ * <resultName> = tr.get.asInstanceOf[<resultType>]
106
+ * <nextState>
107
+ * <mkResumeApply>
108
+ * }
109
+ */
110
+ def ifIsFailureTree [T : WeakTypeTag ](tryReference : => Tree ) =
111
+ If (futureSystemOps.tryyIsFailure(Expr [futureSystem.Tryy [T ]](tryReference)).tree,
112
+ Block (futureSystemOps.completeProm[T ](
113
+ Expr [futureSystem.Prom [T ]](symLookup.memberRef(name.result)),
114
+ Expr [futureSystem.Tryy [T ]](
115
+ TypeApply (Select (tryReference, newTermName(" asInstanceOf" )),
116
+ List (TypeTree (futureSystemOps.tryType[T ]))))).tree :: Nil ,
117
+ Return (literalUnit)),
118
+ Block (List (tryGetTree(tryReference)), mkStateTree(nextState, symLookup))
119
+ )
120
+
88
121
override def mkOnCompleteHandler [T : WeakTypeTag ]: Option [CaseDef ] = {
89
- val tryGetTree =
90
- Assign (
91
- Ident (awaitable.resultName),
92
- TypeApply (Select (futureSystemOps.tryyGet[T ](Expr [futureSystem.Tryy [T ]](Ident (symLookup.applyTrParam))).tree, newTermName(" asInstanceOf" )), List (TypeTree (awaitable.resultType)))
93
- )
94
-
95
- /* if (tr.isFailure)
96
- * result.complete(tr.asInstanceOf[Try[T]])
97
- * else {
98
- * <resultName> = tr.get.asInstanceOf[<resultType>]
99
- * <nextState>
100
- * <mkResumeApply>
101
- * }
102
- */
103
- val ifIsFailureTree =
104
- If (futureSystemOps.tryyIsFailure(Expr [futureSystem.Tryy [T ]](Ident (symLookup.applyTrParam))).tree,
105
- futureSystemOps.completeProm[T ](
106
- Expr [futureSystem.Prom [T ]](symLookup.memberRef(name.result)),
107
- Expr [futureSystem.Tryy [T ]](
108
- TypeApply (Select (Ident (symLookup.applyTrParam), newTermName(" asInstanceOf" )),
109
- List (TypeTree (futureSystemOps.tryType[T ]))))).tree,
110
- Block (List (tryGetTree, mkStateTree(nextState, symLookup)), mkResumeApply(symLookup))
111
- )
112
-
113
- Some (mkHandlerCase(state, List (ifIsFailureTree)))
122
+ Some (mkHandlerCase(onCompleteState, List (ifIsFailureTree[T ](Ident (symLookup.applyTrParam)))))
114
123
}
115
124
116
125
override val toString : String =
@@ -146,9 +155,10 @@ trait ExprBuilder {
146
155
}
147
156
148
157
def resultWithAwait (awaitable : Awaitable ,
158
+ onCompleteState : Int ,
149
159
nextState : Int ): AsyncState = {
150
160
val effectiveNextState = nextJumpState.getOrElse(nextState)
151
- new AsyncStateWithAwait (stats.toList, state, effectiveNextState, awaitable, symLookup)
161
+ new AsyncStateWithAwait (stats.toList, state, onCompleteState, effectiveNextState, awaitable, symLookup)
152
162
}
153
163
154
164
def resultSimple (nextState : Int ): AsyncState = {
@@ -157,7 +167,7 @@ trait ExprBuilder {
157
167
}
158
168
159
169
def resultWithIf (condTree : Tree , thenState : Int , elseState : Int ): AsyncState = {
160
- def mkBranch (state : Int ) = Block ( mkStateTree(state, symLookup) :: Nil , mkResumeApply(symLookup) )
170
+ def mkBranch (state : Int ) = mkStateTree(state, symLookup)
161
171
this += If (condTree, mkBranch(thenState), mkBranch(elseState))
162
172
new AsyncStateWithoutAwait (stats.toList, state, List (thenState, elseState))
163
173
}
@@ -177,15 +187,15 @@ trait ExprBuilder {
177
187
val newCases = for ((cas, num) <- cases.zipWithIndex) yield cas match {
178
188
case CaseDef (pat, guard, rhs) =>
179
189
val bindAssigns = rhs.children.takeWhile(isSyntheticBindVal)
180
- CaseDef (pat, guard, Block (bindAssigns :+ mkStateTree(caseStates(num), symLookup), mkResumeApply( symLookup)))
190
+ CaseDef (pat, guard, Block (bindAssigns, mkStateTree(caseStates(num), symLookup)))
181
191
}
182
192
// 2. insert changed match tree at the end of the current state
183
193
this += Match (scrutTree, newCases)
184
194
new AsyncStateWithoutAwait (stats.toList, state, caseStates)
185
195
}
186
196
187
197
def resultWithLabel (startLabelState : Int , symLookup : SymLookup ): AsyncState = {
188
- this += Block ( mkStateTree(startLabelState, symLookup) :: Nil , mkResumeApply(symLookup) )
198
+ this += mkStateTree(startLabelState, symLookup)
189
199
new AsyncStateWithoutAwait (stats.toList, state, List (startLabelState))
190
200
}
191
201
@@ -226,9 +236,10 @@ trait ExprBuilder {
226
236
for (stat <- stats) stat match {
227
237
// the val name = await(..) pattern
228
238
case vd @ ValDef (mods, name, tpt, Apply (fun, arg :: Nil )) if isAwait(fun) =>
239
+ val onCompleteState = nextState()
229
240
val afterAwaitState = nextState()
230
241
val awaitable = Awaitable (arg, stat.symbol, tpt.tpe, vd)
231
- asyncStates += stateBuilder.resultWithAwait(awaitable, afterAwaitState) // complete with await
242
+ asyncStates += stateBuilder.resultWithAwait(awaitable, onCompleteState, afterAwaitState) // complete with await
232
243
currState = afterAwaitState
233
244
stateBuilder = new AsyncStateBuilder (currState, symLookup)
234
245
@@ -296,8 +307,6 @@ trait ExprBuilder {
296
307
def asyncStates : List [AsyncState ]
297
308
298
309
def onCompleteHandler [T : WeakTypeTag ]: Tree
299
-
300
- def resumeFunTree [T : WeakTypeTag ]: DefDef
301
310
}
302
311
303
312
case class SymLookup (stateMachineClass : Symbol , applyTrParam : Symbol ) {
@@ -330,13 +339,13 @@ trait ExprBuilder {
330
339
val lastStateBody = Expr [T ](lastState.body)
331
340
val rhs = futureSystemOps.completeProm(
332
341
Expr [futureSystem.Prom [T ]](symLookup.memberRef(name.result)), futureSystemOps.tryySuccess[T ](lastStateBody))
333
- mkHandlerCase(lastState.state, rhs.tree)
342
+ mkHandlerCase(lastState.state, Block ( rhs.tree, Return (literalUnit)) )
334
343
}
335
344
asyncStates.toList match {
336
345
case s :: Nil =>
337
346
List (caseForLastState)
338
347
case _ =>
339
- val initCases = for (state <- asyncStates.toList.init) yield state.mkHandlerCaseForState
348
+ val initCases = for (state <- asyncStates.toList.init) yield state.mkHandlerCaseForState[ T ]
340
349
initCases :+ caseForLastState
341
350
}
342
351
}
@@ -362,18 +371,23 @@ trait ExprBuilder {
362
371
* }
363
372
* }
364
373
*/
365
- def resumeFunTree [T : WeakTypeTag ]: DefDef =
366
- DefDef (Modifiers (), name.resume, Nil , List (Nil ), Ident (definitions.UnitClass ),
374
+ private def resumeFunTree [T : WeakTypeTag ]: Tree =
367
375
Try (
368
- Match (symLookup.memberRef(name.state), mkCombinedHandlerCases[T ]),
376
+ Match (symLookup.memberRef(name.state), mkCombinedHandlerCases[T ] ++ initStates.flatMap(_.mkOnCompleteHandler[ T ]) ),
369
377
List (
370
378
CaseDef (
371
379
Bind (name.t, Ident (nme.WILDCARD )),
372
380
Apply (Ident (defn.NonFatalClass ), List (Ident (name.t))), {
373
381
val t = Expr [Throwable ](Ident (name.t))
374
- futureSystemOps.completeProm[T ](
382
+ val complete = futureSystemOps.completeProm[T ](
375
383
Expr [futureSystem.Prom [T ]](symLookup.memberRef(name.result)), futureSystemOps.tryyFailure[T ](t)).tree
376
- })), EmptyTree ))
384
+ Block (complete :: Nil , Return (literalUnit))
385
+ })), EmptyTree )
386
+
387
+ def forever (t : Tree ): Tree = {
388
+ val labelName = name.fresh(" while$" )
389
+ LabelDef (labelName, Nil , Block (t :: Nil , Apply (Ident (labelName), Nil )))
390
+ }
377
391
378
392
/**
379
393
* Builds a `match` expression used as an onComplete handler.
@@ -387,8 +401,12 @@ trait ExprBuilder {
387
401
* resume()
388
402
* }
389
403
*/
390
- def onCompleteHandler [T : WeakTypeTag ]: Tree =
391
- Match (symLookup.memberRef(name.state), initStates.flatMap(_.mkOnCompleteHandler[T ]).toList)
404
+ def onCompleteHandler [T : WeakTypeTag ]: Tree = {
405
+ val onCompletes = initStates.flatMap(_.mkOnCompleteHandler[T ]).toList
406
+ forever {
407
+ Block (resumeFunTree :: Nil , literalUnit)
408
+ }
409
+ }
392
410
}
393
411
}
394
412
@@ -399,9 +417,6 @@ trait ExprBuilder {
399
417
400
418
case class Awaitable (expr : Tree , resultName : Symbol , resultType : Type , resultValDef : ValDef )
401
419
402
- private def mkResumeApply (symLookup : SymLookup ) =
403
- Apply (symLookup.memberRef(name.resume), Nil )
404
-
405
420
private def mkStateTree (nextState : Int , symLookup : SymLookup ): Tree =
406
421
Assign (symLookup.memberRef(name.state), Literal (Constant (nextState)))
407
422
@@ -411,5 +426,7 @@ trait ExprBuilder {
411
426
private def mkHandlerCase (num : Int , rhs : Tree ): CaseDef =
412
427
CaseDef (Literal (Constant (num)), EmptyTree , rhs)
413
428
414
- private def literalUnit = Literal (Constant (()))
429
+ def literalUnit = Literal (Constant (()))
430
+
431
+ def literalNull = Literal (Constant (null ))
415
432
}
0 commit comments