@@ -34,8 +34,18 @@ trait ExprBuilder {
34
34
35
35
var stats : List [Tree ]
36
36
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
+
37
47
final def allStats : List [Tree ] = this match {
38
- case a : AsyncStateWithAwait => stats :+ a.awaitable.resultValDef
48
+ case a : AsyncStateWithAwait => statsAnd( a.awaitable.resultValDef :: Nil )
39
49
case _ => stats
40
50
}
41
51
@@ -52,8 +62,9 @@ trait ExprBuilder {
52
62
def nextStates : List [Int ] =
53
63
List (nextState)
54
64
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
+ }
57
68
58
69
override val toString : String =
59
70
s " AsyncState # $state, next = $nextState"
@@ -87,10 +98,10 @@ trait ExprBuilder {
87
98
val tryGetOrCallOnComplete =
88
99
if (futureSystemOps.continueCompletedFutureOnSameThread)
89
100
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)))
92
103
else
93
- Block (callOnComplete :: Nil , Return (literalUnit))
104
+ Block (toList( callOnComplete) , Return (literalUnit))
94
105
mkHandlerCase(state, stats ++ List (mkStateTree(onCompleteState, symLookup), tryGetOrCallOnComplete))
95
106
}
96
107
@@ -110,11 +121,11 @@ trait ExprBuilder {
110
121
*/
111
122
def ifIsFailureTree [T : WeakTypeTag ](tryReference : => Tree ) =
112
123
If (futureSystemOps.tryyIsFailure(c.Expr [futureSystem.Tryy [T ]](tryReference)).tree,
113
- Block (futureSystemOps.completeProm[T ](
124
+ Block (toList( futureSystemOps.completeProm[T ](
114
125
c.Expr [futureSystem.Prom [T ]](symLookup.memberRef(name.result)),
115
126
c.Expr [futureSystem.Tryy [T ]](
116
127
TypeApply (Select (tryReference, newTermName(" asInstanceOf" )),
117
- List (TypeTree (futureSystemOps.tryType[T ]))))).tree :: Nil ,
128
+ List (TypeTree (futureSystemOps.tryType[T ]))))).tree) ,
118
129
Return (literalUnit)),
119
130
Block (List (tryGetTree(tryReference)), mkStateTree(nextState, symLookup))
120
131
)
@@ -382,12 +393,12 @@ trait ExprBuilder {
382
393
val t = c.Expr [Throwable ](Ident (name.t))
383
394
val complete = futureSystemOps.completeProm[T ](
384
395
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))
386
397
})), EmptyTree )
387
398
388
399
def forever (t : Tree ): Tree = {
389
400
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 )))
391
402
}
392
403
393
404
/**
@@ -405,7 +416,7 @@ trait ExprBuilder {
405
416
def onCompleteHandler [T : WeakTypeTag ]: Tree = {
406
417
val onCompletes = initStates.flatMap(_.mkOnCompleteHandler[T ]).toList
407
418
forever {
408
- Block ( resumeFunTree :: Nil , literalUnit )
419
+ adaptToUnit(toList( resumeFunTree) )
409
420
}
410
421
}
411
422
}
@@ -422,12 +433,32 @@ trait ExprBuilder {
422
433
Assign (symLookup.memberRef(name.state), Literal (Constant (nextState)))
423
434
424
435
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
+ }
426
452
427
453
private def mkHandlerCase (num : Int , rhs : Tree ): CaseDef =
428
454
CaseDef (Literal (Constant (num)), EmptyTree , rhs)
429
455
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
+ }
431
462
432
463
def literalNull = Literal (Constant (null ))
433
464
}
0 commit comments