@@ -34,8 +34,18 @@ trait ExprBuilder {
3434
3535 var stats : List [Tree ]
3636
37+ def statsAnd (trees : List [Tree ]): List [Tree ] = {
38+ val body = stats match {
39+ case init :+ last if tpeOf(last) =:= definitions.NothingTpe =>
40+ adaptToUnit(init :+ Typed (last, TypeTree (definitions.AnyTpe )))
41+ case _ =>
42+ adaptToUnit(stats)
43+ }
44+ Try (body, Nil , adaptToUnit(trees)) :: Nil
45+ }
46+
3747 final def allStats : List [Tree ] = this match {
38- case a : AsyncStateWithAwait => stats :+ a.awaitable.resultValDef
48+ case a : AsyncStateWithAwait => statsAnd( a.awaitable.resultValDef :: Nil )
3949 case _ => stats
4050 }
4151
@@ -52,8 +62,9 @@ trait ExprBuilder {
5262 def nextStates : List [Int ] =
5363 List (nextState)
5464
55- def mkHandlerCaseForState [T : WeakTypeTag ]: CaseDef =
56- mkHandlerCase(state, stats :+ mkStateTree(nextState, symLookup))
65+ def mkHandlerCaseForState [T : WeakTypeTag ]: CaseDef = {
66+ mkHandlerCase(state, statsAnd(mkStateTree(nextState, symLookup) :: Nil ))
67+ }
5768
5869 override val toString : String =
5970 s " AsyncState # $state, next = $nextState"
@@ -87,10 +98,10 @@ trait ExprBuilder {
8798 val tryGetOrCallOnComplete =
8899 if (futureSystemOps.continueCompletedFutureOnSameThread)
89100 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)))
101+ adaptToUnit (ifIsFailureTree[T ](futureSystemOps.getCompleted[Any ](c.Expr [futureSystem.Fut [Any ]](awaitable.expr)).tree) :: Nil ),
102+ Block (toList( callOnComplete) , Return (literalUnit)))
92103 else
93- Block (callOnComplete :: Nil , Return (literalUnit))
104+ Block (toList( callOnComplete) , Return (literalUnit))
94105 mkHandlerCase(state, stats ++ List (mkStateTree(onCompleteState, symLookup), tryGetOrCallOnComplete))
95106 }
96107
@@ -110,11 +121,11 @@ trait ExprBuilder {
110121 */
111122 def ifIsFailureTree [T : WeakTypeTag ](tryReference : => Tree ) =
112123 If (futureSystemOps.tryyIsFailure(c.Expr [futureSystem.Tryy [T ]](tryReference)).tree,
113- Block (futureSystemOps.completeProm[T ](
124+ Block (toList( futureSystemOps.completeProm[T ](
114125 c.Expr [futureSystem.Prom [T ]](symLookup.memberRef(name.result)),
115126 c.Expr [futureSystem.Tryy [T ]](
116127 TypeApply (Select (tryReference, newTermName(" asInstanceOf" )),
117- List (TypeTree (futureSystemOps.tryType[T ]))))).tree :: Nil ,
128+ List (TypeTree (futureSystemOps.tryType[T ]))))).tree) ,
118129 Return (literalUnit)),
119130 Block (List (tryGetTree(tryReference)), mkStateTree(nextState, symLookup))
120131 )
@@ -382,12 +393,12 @@ trait ExprBuilder {
382393 val t = c.Expr [Throwable ](Ident (name.t))
383394 val complete = futureSystemOps.completeProm[T ](
384395 c.Expr [futureSystem.Prom [T ]](symLookup.memberRef(name.result)), futureSystemOps.tryyFailure[T ](t)).tree
385- Block (complete :: Nil , Return (literalUnit))
396+ Block (toList( complete) , Return (literalUnit))
386397 })), EmptyTree )
387398
388399 def forever (t : Tree ): Tree = {
389400 val labelName = name.fresh(" while$" )
390- LabelDef (labelName, Nil , Block (t :: Nil , Apply (Ident (labelName), Nil )))
401+ LabelDef (labelName, Nil , Block (toList(t) , Apply (Ident (labelName), Nil )))
391402 }
392403
393404 /**
@@ -405,7 +416,7 @@ trait ExprBuilder {
405416 def onCompleteHandler [T : WeakTypeTag ]: Tree = {
406417 val onCompletes = initStates.flatMap(_.mkOnCompleteHandler[T ]).toList
407418 forever {
408- Block ( resumeFunTree :: Nil , literalUnit )
419+ adaptToUnit(toList( resumeFunTree) )
409420 }
410421 }
411422 }
@@ -422,12 +433,32 @@ trait ExprBuilder {
422433 Assign (symLookup.memberRef(name.state), Literal (Constant (nextState)))
423434
424435 private def mkHandlerCase (num : Int , rhs : List [Tree ]): CaseDef =
425- mkHandlerCase(num, Block (rhs, literalUnit))
436+ mkHandlerCase(num, adaptToUnit(rhs))
437+
438+ private def tpeOf (t : Tree ): Type = t match {
439+ case _ if t.tpe != null => t.tpe
440+ case Try (body, Nil , _) => tpeOf(body)
441+ case _ => NoType
442+ }
443+
444+ private def adaptToUnit (rhs : List [Tree ]): c.universe.Block = {
445+ rhs match {
446+ case init :+ last if tpeOf(last) <:< definitions.UnitTpe =>
447+ Block (init, last)
448+ case _ =>
449+ Block (rhs, literalUnit)
450+ }
451+ }
426452
427453 private def mkHandlerCase (num : Int , rhs : Tree ): CaseDef =
428454 CaseDef (Literal (Constant (num)), EmptyTree , rhs)
429455
430- def literalUnit = Literal (Constant (()))
456+ def literalUnit = Literal (Constant (())) // a def to avoid sharing trees
457+
458+ def toList (tree : Tree ): List [Tree ] = tree match {
459+ case Block (stats, Literal (Constant (value))) if value == () => stats
460+ case _ => tree :: Nil
461+ }
431462
432463 def literalNull = Literal (Constant (null ))
433464}
0 commit comments