@@ -28,7 +28,7 @@ trait ExprBuilder {
2828
2929 def nextStates : List [Int ]
3030
31- def mkHandlerCaseForState : CaseDef
31+ def mkHandlerCaseForState [ T : WeakTypeTag ] : CaseDef
3232
3333 def mkOnCompleteHandler [T : WeakTypeTag ]: Option [CaseDef ] = None
3434
@@ -52,8 +52,8 @@ trait ExprBuilder {
5252 def nextStates : List [Int ] =
5353 List (nextState)
5454
55- def mkHandlerCaseForState : CaseDef =
56- mkHandlerCase(state, stats :+ mkStateTree(nextState, symLookup) :+ mkResumeApply(symLookup) )
55+ def mkHandlerCaseForState [ T : WeakTypeTag ] : CaseDef =
56+ mkHandlerCase(state, stats :+ mkStateTree(nextState, symLookup))
5757
5858 override val toString : String =
5959 s " AsyncState # $state, next = $nextState"
@@ -63,7 +63,7 @@ trait ExprBuilder {
6363 * a branch of an `if` or a `match`.
6464 */
6565 final class AsyncStateWithoutAwait (var stats : List [Tree ], val state : Int , val nextStates : List [Int ]) extends AsyncState {
66- override def mkHandlerCaseForState : CaseDef =
66+ override def mkHandlerCaseForState [ T : WeakTypeTag ] : CaseDef =
6767 mkHandlerCase(state, stats)
6868
6969 override val toString : String =
@@ -73,45 +73,54 @@ trait ExprBuilder {
7373 /** A sequence of statements that concludes with an `await` call. The `onComplete`
7474 * handler will unconditionally transition to `nextState`.
7575 */
76- final class AsyncStateWithAwait (var stats : List [Tree ], val state : Int , nextState : Int ,
76+ final class AsyncStateWithAwait (var stats : List [Tree ], val state : Int , onCompleteState : Int , nextState : Int ,
7777 val awaitable : Awaitable , symLookup : SymLookup )
7878 extends AsyncState {
7979
8080 def nextStates : List [Int ] =
8181 List (nextState)
8282
83- override def mkHandlerCaseForState : CaseDef = {
84- val callOnComplete = futureSystemOps.onComplete(c.Expr (awaitable.expr),
85- c.Expr (This (tpnme.EMPTY )), c.Expr (Ident (name.execContext))).tree
86- mkHandlerCase(state, stats :+ callOnComplete)
83+ override def mkHandlerCaseForState [T : WeakTypeTag ]: CaseDef = {
84+ val fun = This (tpnme.EMPTY )
85+ val callOnComplete = futureSystemOps.onComplete[Any , Unit ](c.Expr [futureSystem.Fut [Any ]](awaitable.expr),
86+ c.Expr [futureSystem.Tryy [Any ] => Unit ](fun), c.Expr [futureSystem.ExecContext ](Ident (name.execContext))).tree
87+ val tryGetOrCallOnComplete =
88+ if (futureSystemOps.continueCompletedFutureOnSameThread)
89+ If (futureSystemOps.isCompleted(c.Expr [futureSystem.Fut [_]](awaitable.expr)).tree,
90+ Block (ifIsFailureTree[T ](futureSystemOps.getCompleted[Any ](c.Expr [futureSystem.Fut [Any ]](awaitable.expr)).tree) :: Nil , literalUnit),
91+ Block (callOnComplete :: Nil , Return (literalUnit)))
92+ else
93+ Block (callOnComplete :: Nil , Return (literalUnit))
94+ mkHandlerCase(state, stats ++ List (mkStateTree(onCompleteState, symLookup), tryGetOrCallOnComplete))
8795 }
8896
97+ private def tryGetTree (tryReference : => Tree ) =
98+ Assign (
99+ Ident (awaitable.resultName),
100+ TypeApply (Select (futureSystemOps.tryyGet[Any ](c.Expr [futureSystem.Tryy [Any ]](tryReference)).tree, newTermName(" asInstanceOf" )), List (TypeTree (awaitable.resultType)))
101+ )
102+
103+ /* if (tr.isFailure)
104+ * result.complete(tr.asInstanceOf[Try[T]])
105+ * else {
106+ * <resultName> = tr.get.asInstanceOf[<resultType>]
107+ * <nextState>
108+ * <mkResumeApply>
109+ * }
110+ */
111+ def ifIsFailureTree [T : WeakTypeTag ](tryReference : => Tree ) =
112+ If (futureSystemOps.tryyIsFailure(c.Expr [futureSystem.Tryy [T ]](tryReference)).tree,
113+ Block (futureSystemOps.completeProm[T ](
114+ c.Expr [futureSystem.Prom [T ]](symLookup.memberRef(name.result)),
115+ c.Expr [futureSystem.Tryy [T ]](
116+ TypeApply (Select (tryReference, newTermName(" asInstanceOf" )),
117+ List (TypeTree (futureSystemOps.tryType[T ]))))).tree :: Nil ,
118+ Return (literalUnit)),
119+ Block (List (tryGetTree(tryReference)), mkStateTree(nextState, symLookup))
120+ )
121+
89122 override def mkOnCompleteHandler [T : WeakTypeTag ]: Option [CaseDef ] = {
90- val tryGetTree =
91- Assign (
92- Ident (awaitable.resultName),
93- TypeApply (Select (futureSystemOps.tryyGet[T ](c.Expr [futureSystem.Tryy [T ]](Ident (symLookup.applyTrParam))).tree, newTermName(" asInstanceOf" )), List (TypeTree (awaitable.resultType)))
94- )
95-
96- /* if (tr.isFailure)
97- * result.complete(tr.asInstanceOf[Try[T]])
98- * else {
99- * <resultName> = tr.get.asInstanceOf[<resultType>]
100- * <nextState>
101- * <mkResumeApply>
102- * }
103- */
104- val ifIsFailureTree =
105- If (futureSystemOps.tryyIsFailure(c.Expr [futureSystem.Tryy [T ]](Ident (symLookup.applyTrParam))).tree,
106- futureSystemOps.completeProm[T ](
107- c.Expr [futureSystem.Prom [T ]](symLookup.memberRef(name.result)),
108- c.Expr [futureSystem.Tryy [T ]](
109- TypeApply (Select (Ident (symLookup.applyTrParam), newTermName(" asInstanceOf" )),
110- List (TypeTree (futureSystemOps.tryType[T ]))))).tree,
111- Block (List (tryGetTree, mkStateTree(nextState, symLookup)), mkResumeApply(symLookup))
112- )
113-
114- Some (mkHandlerCase(state, List (ifIsFailureTree)))
123+ Some (mkHandlerCase(onCompleteState, List (ifIsFailureTree[T ](Ident (symLookup.applyTrParam)))))
115124 }
116125
117126 override val toString : String =
@@ -147,9 +156,10 @@ trait ExprBuilder {
147156 }
148157
149158 def resultWithAwait (awaitable : Awaitable ,
159+ onCompleteState : Int ,
150160 nextState : Int ): AsyncState = {
151161 val effectiveNextState = nextJumpState.getOrElse(nextState)
152- new AsyncStateWithAwait (stats.toList, state, effectiveNextState, awaitable, symLookup)
162+ new AsyncStateWithAwait (stats.toList, state, onCompleteState, effectiveNextState, awaitable, symLookup)
153163 }
154164
155165 def resultSimple (nextState : Int ): AsyncState = {
@@ -158,7 +168,7 @@ trait ExprBuilder {
158168 }
159169
160170 def resultWithIf (condTree : Tree , thenState : Int , elseState : Int ): AsyncState = {
161- def mkBranch (state : Int ) = Block ( mkStateTree(state, symLookup) :: Nil , mkResumeApply(symLookup) )
171+ def mkBranch (state : Int ) = mkStateTree(state, symLookup)
162172 this += If (condTree, mkBranch(thenState), mkBranch(elseState))
163173 new AsyncStateWithoutAwait (stats.toList, state, List (thenState, elseState))
164174 }
@@ -178,15 +188,15 @@ trait ExprBuilder {
178188 val newCases = for ((cas, num) <- cases.zipWithIndex) yield cas match {
179189 case CaseDef (pat, guard, rhs) =>
180190 val bindAssigns = rhs.children.takeWhile(isSyntheticBindVal)
181- CaseDef (pat, guard, Block (bindAssigns :+ mkStateTree(caseStates(num), symLookup), mkResumeApply( symLookup)))
191+ CaseDef (pat, guard, Block (bindAssigns, mkStateTree(caseStates(num), symLookup)))
182192 }
183193 // 2. insert changed match tree at the end of the current state
184194 this += Match (scrutTree, newCases)
185195 new AsyncStateWithoutAwait (stats.toList, state, caseStates)
186196 }
187197
188198 def resultWithLabel (startLabelState : Int , symLookup : SymLookup ): AsyncState = {
189- this += Block ( mkStateTree(startLabelState, symLookup) :: Nil , mkResumeApply(symLookup) )
199+ this += mkStateTree(startLabelState, symLookup)
190200 new AsyncStateWithoutAwait (stats.toList, state, List (startLabelState))
191201 }
192202
@@ -227,9 +237,10 @@ trait ExprBuilder {
227237 for (stat <- stats) stat match {
228238 // the val name = await(..) pattern
229239 case vd @ ValDef (mods, name, tpt, Apply (fun, arg :: Nil )) if isAwait(fun) =>
240+ val onCompleteState = nextState()
230241 val afterAwaitState = nextState()
231242 val awaitable = Awaitable (arg, stat.symbol, tpt.tpe, vd)
232- asyncStates += stateBuilder.resultWithAwait(awaitable, afterAwaitState) // complete with await
243+ asyncStates += stateBuilder.resultWithAwait(awaitable, onCompleteState, afterAwaitState) // complete with await
233244 currState = afterAwaitState
234245 stateBuilder = new AsyncStateBuilder (currState, symLookup)
235246
@@ -297,8 +308,6 @@ trait ExprBuilder {
297308 def asyncStates : List [AsyncState ]
298309
299310 def onCompleteHandler [T : WeakTypeTag ]: Tree
300-
301- def resumeFunTree [T : WeakTypeTag ]: DefDef
302311 }
303312
304313 case class SymLookup (stateMachineClass : Symbol , applyTrParam : Symbol ) {
@@ -331,13 +340,13 @@ trait ExprBuilder {
331340 val lastStateBody = c.Expr [T ](lastState.body)
332341 val rhs = futureSystemOps.completeProm(
333342 c.Expr [futureSystem.Prom [T ]](symLookup.memberRef(name.result)), futureSystemOps.tryySuccess[T ](lastStateBody))
334- mkHandlerCase(lastState.state, rhs.tree)
343+ mkHandlerCase(lastState.state, Block ( rhs.tree, Return (literalUnit)) )
335344 }
336345 asyncStates.toList match {
337346 case s :: Nil =>
338347 List (caseForLastState)
339348 case _ =>
340- val initCases = for (state <- asyncStates.toList.init) yield state.mkHandlerCaseForState
349+ val initCases = for (state <- asyncStates.toList.init) yield state.mkHandlerCaseForState[ T ]
341350 initCases :+ caseForLastState
342351 }
343352 }
@@ -363,18 +372,23 @@ trait ExprBuilder {
363372 * }
364373 * }
365374 */
366- def resumeFunTree [T : WeakTypeTag ]: DefDef =
367- DefDef (Modifiers (), name.resume, Nil , List (Nil ), Ident (definitions.UnitClass ),
375+ private def resumeFunTree [T : WeakTypeTag ]: Tree =
368376 Try (
369- Match (symLookup.memberRef(name.state), mkCombinedHandlerCases[T ]),
377+ Match (symLookup.memberRef(name.state), mkCombinedHandlerCases[T ] ++ initStates.flatMap(_.mkOnCompleteHandler[ T ]) ),
370378 List (
371379 CaseDef (
372380 Bind (name.t, Ident (nme.WILDCARD )),
373381 Apply (Ident (defn.NonFatalClass ), List (Ident (name.t))), {
374382 val t = c.Expr [Throwable ](Ident (name.t))
375- futureSystemOps.completeProm[T ](
383+ val complete = futureSystemOps.completeProm[T ](
376384 c.Expr [futureSystem.Prom [T ]](symLookup.memberRef(name.result)), futureSystemOps.tryyFailure[T ](t)).tree
377- })), EmptyTree ))
385+ Block (complete :: Nil , Return (literalUnit))
386+ })), EmptyTree )
387+
388+ def forever (t : Tree ): Tree = {
389+ val labelName = name.fresh(" while$" )
390+ LabelDef (labelName, Nil , Block (t :: Nil , Apply (Ident (labelName), Nil )))
391+ }
378392
379393 /**
380394 * Builds a `match` expression used as an onComplete handler.
@@ -388,8 +402,12 @@ trait ExprBuilder {
388402 * resume()
389403 * }
390404 */
391- def onCompleteHandler [T : WeakTypeTag ]: Tree =
392- Match (symLookup.memberRef(name.state), initStates.flatMap(_.mkOnCompleteHandler[T ]).toList)
405+ def onCompleteHandler [T : WeakTypeTag ]: Tree = {
406+ val onCompletes = initStates.flatMap(_.mkOnCompleteHandler[T ]).toList
407+ forever {
408+ Block (resumeFunTree :: Nil , literalUnit)
409+ }
410+ }
393411 }
394412 }
395413
@@ -400,9 +418,6 @@ trait ExprBuilder {
400418
401419 case class Awaitable (expr : Tree , resultName : Symbol , resultType : Type , resultValDef : ValDef )
402420
403- private def mkResumeApply (symLookup : SymLookup ) =
404- Apply (symLookup.memberRef(name.resume), Nil )
405-
406421 private def mkStateTree (nextState : Int , symLookup : SymLookup ): Tree =
407422 Assign (symLookup.memberRef(name.state), Literal (Constant (nextState)))
408423
@@ -412,5 +427,7 @@ trait ExprBuilder {
412427 private def mkHandlerCase (num : Int , rhs : Tree ): CaseDef =
413428 CaseDef (Literal (Constant (num)), EmptyTree , rhs)
414429
415- private def literalUnit = Literal (Constant (()))
430+ def literalUnit = Literal (Constant (()))
431+
432+ def literalNull = Literal (Constant (null ))
416433}
0 commit comments