@@ -52,7 +52,7 @@ trait ExprBuilder {
5252 List (nextState)
5353
5454 def mkHandlerCaseForState : CaseDef =
55- mkHandlerCase(state, stats :+ mkStateTree(nextState, symLookup) :+ mkResumeApply(symLookup) )
55+ mkHandlerCase(state, stats :+ mkStateTree(nextState, symLookup))
5656
5757 override val toString : String =
5858 s " AsyncState # $state, next = $nextState"
@@ -72,7 +72,7 @@ trait ExprBuilder {
7272 /** A sequence of statements that concludes with an `await` call. The `onComplete`
7373 * handler will unconditionally transition to `nextState`.
7474 */
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 ,
7676 val awaitable : Awaitable , symLookup : SymLookup )
7777 extends AsyncState {
7878
@@ -82,7 +82,7 @@ trait ExprBuilder {
8282 override def mkHandlerCaseForState : CaseDef = {
8383 val callOnComplete = futureSystemOps.onComplete(Expr (awaitable.expr),
8484 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)) )
8686 }
8787
8888 override def mkOnCompleteHandler [T : WeakTypeTag ]: Option [CaseDef ] = {
@@ -102,15 +102,16 @@ trait ExprBuilder {
102102 */
103103 val ifIsFailureTree =
104104 If (futureSystemOps.tryyIsFailure(Expr [futureSystem.Tryy [T ]](Ident (symLookup.applyTrParam))).tree,
105- futureSystemOps.completeProm[T ](
105+ Block ( futureSystemOps.completeProm[T ](
106106 Expr [futureSystem.Prom [T ]](symLookup.memberRef(name.result)),
107107 Expr [futureSystem.Tryy [T ]](
108108 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))
111112 )
112113
113- Some (mkHandlerCase(state , List (ifIsFailureTree)))
114+ Some (mkHandlerCase(onCompleteState , List (ifIsFailureTree)))
114115 }
115116
116117 override val toString : String =
@@ -146,9 +147,10 @@ trait ExprBuilder {
146147 }
147148
148149 def resultWithAwait (awaitable : Awaitable ,
150+ onCompleteState : Int ,
149151 nextState : Int ): AsyncState = {
150152 val effectiveNextState = nextJumpState.getOrElse(nextState)
151- new AsyncStateWithAwait (stats.toList, state, effectiveNextState, awaitable, symLookup)
153+ new AsyncStateWithAwait (stats.toList, state, onCompleteState, effectiveNextState, awaitable, symLookup)
152154 }
153155
154156 def resultSimple (nextState : Int ): AsyncState = {
@@ -157,7 +159,7 @@ trait ExprBuilder {
157159 }
158160
159161 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)
161163 this += If (condTree, mkBranch(thenState), mkBranch(elseState))
162164 new AsyncStateWithoutAwait (stats.toList, state, List (thenState, elseState))
163165 }
@@ -177,15 +179,15 @@ trait ExprBuilder {
177179 val newCases = for ((cas, num) <- cases.zipWithIndex) yield cas match {
178180 case CaseDef (pat, guard, rhs) =>
179181 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)))
181183 }
182184 // 2. insert changed match tree at the end of the current state
183185 this += Match (scrutTree, newCases)
184186 new AsyncStateWithoutAwait (stats.toList, state, caseStates)
185187 }
186188
187189 def resultWithLabel (startLabelState : Int , symLookup : SymLookup ): AsyncState = {
188- this += Block ( mkStateTree(startLabelState, symLookup) :: Nil , mkResumeApply(symLookup) )
190+ this += mkStateTree(startLabelState, symLookup)
189191 new AsyncStateWithoutAwait (stats.toList, state, List (startLabelState))
190192 }
191193
@@ -226,9 +228,10 @@ trait ExprBuilder {
226228 for (stat <- stats) stat match {
227229 // the val name = await(..) pattern
228230 case vd @ ValDef (mods, name, tpt, Apply (fun, arg :: Nil )) if isAwait(fun) =>
231+ val onCompleteState = nextState()
229232 val afterAwaitState = nextState()
230233 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
232235 currState = afterAwaitState
233236 stateBuilder = new AsyncStateBuilder (currState, symLookup)
234237
@@ -296,8 +299,6 @@ trait ExprBuilder {
296299 def asyncStates : List [AsyncState ]
297300
298301 def onCompleteHandler [T : WeakTypeTag ]: Tree
299-
300- def resumeFunTree [T : WeakTypeTag ]: DefDef
301302 }
302303
303304 case class SymLookup (stateMachineClass : Symbol , applyTrParam : Symbol ) {
@@ -330,7 +331,7 @@ trait ExprBuilder {
330331 val lastStateBody = Expr [T ](lastState.body)
331332 val rhs = futureSystemOps.completeProm(
332333 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)) )
334335 }
335336 asyncStates.toList match {
336337 case s :: Nil =>
@@ -362,18 +363,23 @@ trait ExprBuilder {
362363 * }
363364 * }
364365 */
365- def resumeFunTree [T : WeakTypeTag ]: DefDef =
366- DefDef (Modifiers (), name.resume, Nil , List (Nil ), Ident (definitions.UnitClass ),
366+ private def resumeFunTree [T : WeakTypeTag ]: Tree =
367367 Try (
368- Match (symLookup.memberRef(name.state), mkCombinedHandlerCases[T ]),
368+ Match (symLookup.memberRef(name.state), mkCombinedHandlerCases[T ] ++ initStates.flatMap(_.mkOnCompleteHandler[ T ]) ),
369369 List (
370370 CaseDef (
371371 Bind (name.t, Ident (nme.WILDCARD )),
372372 Apply (Ident (defn.NonFatalClass ), List (Ident (name.t))), {
373373 val t = Expr [Throwable ](Ident (name.t))
374- futureSystemOps.completeProm[T ](
374+ val complete = futureSystemOps.completeProm[T ](
375375 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+ }
377383
378384 /**
379385 * Builds a `match` expression used as an onComplete handler.
@@ -387,8 +393,12 @@ trait ExprBuilder {
387393 * resume()
388394 * }
389395 */
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+ }
392402 }
393403 }
394404
@@ -399,9 +409,6 @@ trait ExprBuilder {
399409
400410 case class Awaitable (expr : Tree , resultName : Symbol , resultType : Type , resultValDef : ValDef )
401411
402- private def mkResumeApply (symLookup : SymLookup ) =
403- Apply (symLookup.memberRef(name.resume), Nil )
404-
405412 private def mkStateTree (nextState : Int , symLookup : SymLookup ): Tree =
406413 Assign (symLookup.memberRef(name.state), Literal (Constant (nextState)))
407414
@@ -411,5 +418,7 @@ trait ExprBuilder {
411418 private def mkHandlerCase (num : Int , rhs : Tree ): CaseDef =
412419 CaseDef (Literal (Constant (num)), EmptyTree , rhs)
413420
414- private def literalUnit = Literal (Constant (()))
421+ def literalUnit = Literal (Constant (()))
422+
423+ def literalNull = Literal (Constant (null ))
415424}
0 commit comments