@@ -52,7 +52,7 @@ trait ExprBuilder {
52
52
List (nextState)
53
53
54
54
def mkHandlerCaseForState : CaseDef =
55
- mkHandlerCase(state, stats :+ mkStateTree(nextState, symLookup) :+ mkResumeApply(symLookup) )
55
+ mkHandlerCase(state, stats :+ mkStateTree(nextState, symLookup))
56
56
57
57
override val toString : String =
58
58
s " AsyncState # $state, next = $nextState"
@@ -72,7 +72,7 @@ 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
@@ -82,7 +82,7 @@ trait ExprBuilder {
82
82
override def mkHandlerCaseForState : CaseDef = {
83
83
val callOnComplete = futureSystemOps.onComplete(Expr (awaitable.expr),
84
84
Expr (This (tpnme.EMPTY )), Expr (Ident (name.execContext))).tree
85
- mkHandlerCase(state, stats :+ callOnComplete)
85
+ mkHandlerCase(state, stats ++ List (mkStateTree(onCompleteState, symLookup), callOnComplete, Return (literalUnit)) )
86
86
}
87
87
88
88
override def mkOnCompleteHandler [T : WeakTypeTag ]: Option [CaseDef ] = {
@@ -102,15 +102,16 @@ trait ExprBuilder {
102
102
*/
103
103
val ifIsFailureTree =
104
104
If (futureSystemOps.tryyIsFailure(Expr [futureSystem.Tryy [T ]](Ident (symLookup.applyTrParam))).tree,
105
- futureSystemOps.completeProm[T ](
105
+ Block ( futureSystemOps.completeProm[T ](
106
106
Expr [futureSystem.Prom [T ]](symLookup.memberRef(name.result)),
107
107
Expr [futureSystem.Tryy [T ]](
108
108
TypeApply (Select (Ident (symLookup.applyTrParam), newTermName(" asInstanceOf" )),
109
- List (TypeTree (futureSystemOps.tryType[T ]))))).tree,
110
- Block (List (tryGetTree, mkStateTree(nextState, symLookup)), mkResumeApply(symLookup))
109
+ List (TypeTree (futureSystemOps.tryType[T ]))))).tree :: Nil ,
110
+ Return (literalUnit)),
111
+ Block (List (tryGetTree), mkStateTree(nextState, symLookup))
111
112
)
112
113
113
- Some (mkHandlerCase(state , List (ifIsFailureTree)))
114
+ Some (mkHandlerCase(onCompleteState , List (ifIsFailureTree)))
114
115
}
115
116
116
117
override val toString : String =
@@ -146,9 +147,10 @@ trait ExprBuilder {
146
147
}
147
148
148
149
def resultWithAwait (awaitable : Awaitable ,
150
+ onCompleteState : Int ,
149
151
nextState : Int ): AsyncState = {
150
152
val effectiveNextState = nextJumpState.getOrElse(nextState)
151
- new AsyncStateWithAwait (stats.toList, state, effectiveNextState, awaitable, symLookup)
153
+ new AsyncStateWithAwait (stats.toList, state, onCompleteState, effectiveNextState, awaitable, symLookup)
152
154
}
153
155
154
156
def resultSimple (nextState : Int ): AsyncState = {
@@ -157,7 +159,7 @@ trait ExprBuilder {
157
159
}
158
160
159
161
def resultWithIf (condTree : Tree , thenState : Int , elseState : Int ): AsyncState = {
160
- def mkBranch (state : Int ) = Block ( mkStateTree(state, symLookup) :: Nil , mkResumeApply(symLookup) )
162
+ def mkBranch (state : Int ) = mkStateTree(state, symLookup)
161
163
this += If (condTree, mkBranch(thenState), mkBranch(elseState))
162
164
new AsyncStateWithoutAwait (stats.toList, state, List (thenState, elseState))
163
165
}
@@ -177,15 +179,15 @@ trait ExprBuilder {
177
179
val newCases = for ((cas, num) <- cases.zipWithIndex) yield cas match {
178
180
case CaseDef (pat, guard, rhs) =>
179
181
val bindAssigns = rhs.children.takeWhile(isSyntheticBindVal)
180
- CaseDef (pat, guard, Block (bindAssigns :+ mkStateTree(caseStates(num), symLookup), mkResumeApply( symLookup)))
182
+ CaseDef (pat, guard, Block (bindAssigns, mkStateTree(caseStates(num), symLookup)))
181
183
}
182
184
// 2. insert changed match tree at the end of the current state
183
185
this += Match (scrutTree, newCases)
184
186
new AsyncStateWithoutAwait (stats.toList, state, caseStates)
185
187
}
186
188
187
189
def resultWithLabel (startLabelState : Int , symLookup : SymLookup ): AsyncState = {
188
- this += Block ( mkStateTree(startLabelState, symLookup) :: Nil , mkResumeApply(symLookup) )
190
+ this += mkStateTree(startLabelState, symLookup)
189
191
new AsyncStateWithoutAwait (stats.toList, state, List (startLabelState))
190
192
}
191
193
@@ -226,9 +228,10 @@ trait ExprBuilder {
226
228
for (stat <- stats) stat match {
227
229
// the val name = await(..) pattern
228
230
case vd @ ValDef (mods, name, tpt, Apply (fun, arg :: Nil )) if isAwait(fun) =>
231
+ val onCompleteState = nextState()
229
232
val afterAwaitState = nextState()
230
233
val awaitable = Awaitable (arg, stat.symbol, tpt.tpe, vd)
231
- asyncStates += stateBuilder.resultWithAwait(awaitable, afterAwaitState) // complete with await
234
+ asyncStates += stateBuilder.resultWithAwait(awaitable, onCompleteState, afterAwaitState) // complete with await
232
235
currState = afterAwaitState
233
236
stateBuilder = new AsyncStateBuilder (currState, symLookup)
234
237
@@ -296,8 +299,6 @@ trait ExprBuilder {
296
299
def asyncStates : List [AsyncState ]
297
300
298
301
def onCompleteHandler [T : WeakTypeTag ]: Tree
299
-
300
- def resumeFunTree [T : WeakTypeTag ]: DefDef
301
302
}
302
303
303
304
case class SymLookup (stateMachineClass : Symbol , applyTrParam : Symbol ) {
@@ -330,7 +331,7 @@ trait ExprBuilder {
330
331
val lastStateBody = Expr [T ](lastState.body)
331
332
val rhs = futureSystemOps.completeProm(
332
333
Expr [futureSystem.Prom [T ]](symLookup.memberRef(name.result)), futureSystemOps.tryySuccess[T ](lastStateBody))
333
- mkHandlerCase(lastState.state, rhs.tree)
334
+ mkHandlerCase(lastState.state, Block ( rhs.tree, Return (literalUnit)) )
334
335
}
335
336
asyncStates.toList match {
336
337
case s :: Nil =>
@@ -362,18 +363,23 @@ trait ExprBuilder {
362
363
* }
363
364
* }
364
365
*/
365
- def resumeFunTree [T : WeakTypeTag ]: DefDef =
366
- DefDef (Modifiers (), name.resume, Nil , List (Nil ), Ident (definitions.UnitClass ),
366
+ private def resumeFunTree [T : WeakTypeTag ]: Tree =
367
367
Try (
368
- Match (symLookup.memberRef(name.state), mkCombinedHandlerCases[T ]),
368
+ Match (symLookup.memberRef(name.state), mkCombinedHandlerCases[T ] ++ initStates.flatMap(_.mkOnCompleteHandler[ T ]) ),
369
369
List (
370
370
CaseDef (
371
371
Bind (name.t, Ident (nme.WILDCARD )),
372
372
Apply (Ident (defn.NonFatalClass ), List (Ident (name.t))), {
373
373
val t = Expr [Throwable ](Ident (name.t))
374
- futureSystemOps.completeProm[T ](
374
+ val complete = futureSystemOps.completeProm[T ](
375
375
Expr [futureSystem.Prom [T ]](symLookup.memberRef(name.result)), futureSystemOps.tryyFailure[T ](t)).tree
376
- })), EmptyTree ))
376
+ Block (complete :: Nil , Return (literalUnit))
377
+ })), EmptyTree )
378
+
379
+ def forever (t : Tree ): Tree = {
380
+ val labelName = name.fresh(" while$" )
381
+ LabelDef (labelName, Nil , Block (t :: Nil , Apply (Ident (labelName), Nil )))
382
+ }
377
383
378
384
/**
379
385
* Builds a `match` expression used as an onComplete handler.
@@ -387,8 +393,12 @@ trait ExprBuilder {
387
393
* resume()
388
394
* }
389
395
*/
390
- def onCompleteHandler [T : WeakTypeTag ]: Tree =
391
- Match (symLookup.memberRef(name.state), initStates.flatMap(_.mkOnCompleteHandler[T ]).toList)
396
+ def onCompleteHandler [T : WeakTypeTag ]: Tree = {
397
+ val onCompletes = initStates.flatMap(_.mkOnCompleteHandler[T ]).toList
398
+ forever {
399
+ Block (resumeFunTree :: Nil , literalUnit)
400
+ }
401
+ }
392
402
}
393
403
}
394
404
@@ -399,9 +409,6 @@ trait ExprBuilder {
399
409
400
410
case class Awaitable (expr : Tree , resultName : Symbol , resultType : Type , resultValDef : ValDef )
401
411
402
- private def mkResumeApply (symLookup : SymLookup ) =
403
- Apply (symLookup.memberRef(name.resume), Nil )
404
-
405
412
private def mkStateTree (nextState : Int , symLookup : SymLookup ): Tree =
406
413
Assign (symLookup.memberRef(name.state), Literal (Constant (nextState)))
407
414
@@ -411,5 +418,7 @@ trait ExprBuilder {
411
418
private def mkHandlerCase (num : Int , rhs : Tree ): CaseDef =
412
419
CaseDef (Literal (Constant (num)), EmptyTree , rhs)
413
420
414
- private def literalUnit = Literal (Constant (()))
421
+ def literalUnit = Literal (Constant (()))
422
+
423
+ def literalNull = Literal (Constant (null ))
415
424
}
0 commit comments