@@ -28,7 +28,7 @@ trait ExprBuilder {
28
28
29
29
def nextStates : List [Int ]
30
30
31
- def mkHandlerCaseForState : CaseDef
31
+ def mkHandlerCaseForState [ T : WeakTypeTag ] : CaseDef
32
32
33
33
def mkOnCompleteHandler [T : WeakTypeTag ]: Option [CaseDef ] = None
34
34
@@ -52,8 +52,8 @@ trait ExprBuilder {
52
52
def nextStates : List [Int ] =
53
53
List (nextState)
54
54
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))
57
57
58
58
override val toString : String =
59
59
s " AsyncState # $state, next = $nextState"
@@ -63,7 +63,7 @@ trait ExprBuilder {
63
63
* a branch of an `if` or a `match`.
64
64
*/
65
65
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 =
67
67
mkHandlerCase(state, stats)
68
68
69
69
override val toString : String =
@@ -73,45 +73,54 @@ trait ExprBuilder {
73
73
/** A sequence of statements that concludes with an `await` call. The `onComplete`
74
74
* handler will unconditionally transition to `nextState`.
75
75
*/
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 ,
77
77
val awaitable : Awaitable , symLookup : SymLookup )
78
78
extends AsyncState {
79
79
80
80
def nextStates : List [Int ] =
81
81
List (nextState)
82
82
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))
87
95
}
88
96
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
+
89
122
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)))))
115
124
}
116
125
117
126
override val toString : String =
@@ -147,9 +156,10 @@ trait ExprBuilder {
147
156
}
148
157
149
158
def resultWithAwait (awaitable : Awaitable ,
159
+ onCompleteState : Int ,
150
160
nextState : Int ): AsyncState = {
151
161
val effectiveNextState = nextJumpState.getOrElse(nextState)
152
- new AsyncStateWithAwait (stats.toList, state, effectiveNextState, awaitable, symLookup)
162
+ new AsyncStateWithAwait (stats.toList, state, onCompleteState, effectiveNextState, awaitable, symLookup)
153
163
}
154
164
155
165
def resultSimple (nextState : Int ): AsyncState = {
@@ -158,7 +168,7 @@ trait ExprBuilder {
158
168
}
159
169
160
170
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)
162
172
this += If (condTree, mkBranch(thenState), mkBranch(elseState))
163
173
new AsyncStateWithoutAwait (stats.toList, state, List (thenState, elseState))
164
174
}
@@ -178,15 +188,15 @@ trait ExprBuilder {
178
188
val newCases = for ((cas, num) <- cases.zipWithIndex) yield cas match {
179
189
case CaseDef (pat, guard, rhs) =>
180
190
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)))
182
192
}
183
193
// 2. insert changed match tree at the end of the current state
184
194
this += Match (scrutTree, newCases)
185
195
new AsyncStateWithoutAwait (stats.toList, state, caseStates)
186
196
}
187
197
188
198
def resultWithLabel (startLabelState : Int , symLookup : SymLookup ): AsyncState = {
189
- this += Block ( mkStateTree(startLabelState, symLookup) :: Nil , mkResumeApply(symLookup) )
199
+ this += mkStateTree(startLabelState, symLookup)
190
200
new AsyncStateWithoutAwait (stats.toList, state, List (startLabelState))
191
201
}
192
202
@@ -227,9 +237,10 @@ trait ExprBuilder {
227
237
for (stat <- stats) stat match {
228
238
// the val name = await(..) pattern
229
239
case vd @ ValDef (mods, name, tpt, Apply (fun, arg :: Nil )) if isAwait(fun) =>
240
+ val onCompleteState = nextState()
230
241
val afterAwaitState = nextState()
231
242
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
233
244
currState = afterAwaitState
234
245
stateBuilder = new AsyncStateBuilder (currState, symLookup)
235
246
@@ -297,8 +308,6 @@ trait ExprBuilder {
297
308
def asyncStates : List [AsyncState ]
298
309
299
310
def onCompleteHandler [T : WeakTypeTag ]: Tree
300
-
301
- def resumeFunTree [T : WeakTypeTag ]: DefDef
302
311
}
303
312
304
313
case class SymLookup (stateMachineClass : Symbol , applyTrParam : Symbol ) {
@@ -331,13 +340,13 @@ trait ExprBuilder {
331
340
val lastStateBody = c.Expr [T ](lastState.body)
332
341
val rhs = futureSystemOps.completeProm(
333
342
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)) )
335
344
}
336
345
asyncStates.toList match {
337
346
case s :: Nil =>
338
347
List (caseForLastState)
339
348
case _ =>
340
- val initCases = for (state <- asyncStates.toList.init) yield state.mkHandlerCaseForState
349
+ val initCases = for (state <- asyncStates.toList.init) yield state.mkHandlerCaseForState[ T ]
341
350
initCases :+ caseForLastState
342
351
}
343
352
}
@@ -363,18 +372,23 @@ trait ExprBuilder {
363
372
* }
364
373
* }
365
374
*/
366
- def resumeFunTree [T : WeakTypeTag ]: DefDef =
367
- DefDef (Modifiers (), name.resume, Nil , List (Nil ), Ident (definitions.UnitClass ),
375
+ private def resumeFunTree [T : WeakTypeTag ]: Tree =
368
376
Try (
369
- Match (symLookup.memberRef(name.state), mkCombinedHandlerCases[T ]),
377
+ Match (symLookup.memberRef(name.state), mkCombinedHandlerCases[T ] ++ initStates.flatMap(_.mkOnCompleteHandler[ T ]) ),
370
378
List (
371
379
CaseDef (
372
380
Bind (name.t, Ident (nme.WILDCARD )),
373
381
Apply (Ident (defn.NonFatalClass ), List (Ident (name.t))), {
374
382
val t = c.Expr [Throwable ](Ident (name.t))
375
- futureSystemOps.completeProm[T ](
383
+ val complete = futureSystemOps.completeProm[T ](
376
384
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
+ }
378
392
379
393
/**
380
394
* Builds a `match` expression used as an onComplete handler.
@@ -388,8 +402,12 @@ trait ExprBuilder {
388
402
* resume()
389
403
* }
390
404
*/
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
+ }
393
411
}
394
412
}
395
413
@@ -400,9 +418,6 @@ trait ExprBuilder {
400
418
401
419
case class Awaitable (expr : Tree , resultName : Symbol , resultType : Type , resultValDef : ValDef )
402
420
403
- private def mkResumeApply (symLookup : SymLookup ) =
404
- Apply (symLookup.memberRef(name.resume), Nil )
405
-
406
421
private def mkStateTree (nextState : Int , symLookup : SymLookup ): Tree =
407
422
Assign (symLookup.memberRef(name.state), Literal (Constant (nextState)))
408
423
@@ -412,5 +427,7 @@ trait ExprBuilder {
412
427
private def mkHandlerCase (num : Int , rhs : Tree ): CaseDef =
413
428
CaseDef (Literal (Constant (num)), EmptyTree , rhs)
414
429
415
- private def literalUnit = Literal (Constant (()))
430
+ def literalUnit = Literal (Constant (()))
431
+
432
+ def literalNull = Literal (Constant (null ))
416
433
}
0 commit comments