diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2015-07-29 19:17:17 +1000 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2015-07-30 15:51:42 +1000 |
commit | dc3fd62912ef37f1f108fbf0c4ed2a5a47b7e73e (patch) | |
tree | d0c0e794bedecead6e632a4a95e3c687f9019407 /src | |
parent | ad6c3c0a758c50ce32656e64714a0bd90a28d0be (diff) | |
download | scala-async-dc3fd62912ef37f1f108fbf0c4ed2a5a47b7e73e.tar.gz scala-async-dc3fd62912ef37f1f108fbf0c4ed2a5a47b7e73e.tar.bz2 scala-async-dc3fd62912ef37f1f108fbf0c4ed2a5a47b7e73e.zip |
[backport] Cleanup code generation by avoiding redundant blocks
Don't bother adding `{ ...; () }` if we can use the original tree(s) instead,
e.g. if the last tree in `...` conforms to `Unit`.
This makes the debug output of the macro a little easier to read.
(cherry picked from commit de641dc265f34b06e17dfa7c64be00219f72b670)
Diffstat (limited to 'src')
-rw-r--r-- | src/main/scala/scala/async/internal/AsyncTransform.scala | 12 | ||||
-rw-r--r-- | src/main/scala/scala/async/internal/ExprBuilder.scala | 52 |
2 files changed, 45 insertions, 19 deletions
diff --git a/src/main/scala/scala/async/internal/AsyncTransform.scala b/src/main/scala/scala/async/internal/AsyncTransform.scala index 47a2704..b894e61 100644 --- a/src/main/scala/scala/async/internal/AsyncTransform.scala +++ b/src/main/scala/scala/async/internal/AsyncTransform.scala @@ -68,12 +68,12 @@ trait AsyncTransform { for ((state, flds) <- assignsOf) { val assigns = flds.map { fld => val fieldSym = fld.symbol - Block( - List( - asyncBase.nullOut(global)(Expr[String](Literal(Constant(fieldSym.name.toString))), Expr[Any](Ident(fieldSym))).tree - ), - Assign(gen.mkAttributedStableRef(fieldSym.owner.thisType, fieldSym), mkZero(fieldSym.info)) - ) + val assign = Assign(gen.mkAttributedStableRef(fieldSym.owner.thisType, fieldSym), mkZero(fieldSym.info)) + asyncBase.nullOut(global)(Expr[String](Literal(Constant(fieldSym.name.toString))), Expr[Any](Ident(fieldSym))).tree + match { + case Literal(Constant(value: Unit)) => assign + case x => Block(x :: Nil, assign) + } } val asyncState = asyncBlock.asyncStates.find(_.state == state).get asyncState.stats = assigns ++ asyncState.stats diff --git a/src/main/scala/scala/async/internal/ExprBuilder.scala b/src/main/scala/scala/async/internal/ExprBuilder.scala index 2dd485d..d107ed8 100644 --- a/src/main/scala/scala/async/internal/ExprBuilder.scala +++ b/src/main/scala/scala/async/internal/ExprBuilder.scala @@ -33,8 +33,13 @@ trait ExprBuilder { var stats: List[Tree] + def statsAnd(trees: List[Tree]): List[Tree] = { + val body = adaptToUnit(stats) + Try(body, Nil, adaptToUnit(trees)) :: Nil + } + final def allStats: List[Tree] = this match { - case a: AsyncStateWithAwait => stats :+ a.awaitable.resultValDef + case a: AsyncStateWithAwait => statsAnd(a.awaitable.resultValDef :: Nil) case _ => stats } @@ -51,8 +56,9 @@ trait ExprBuilder { def nextStates: List[Int] = List(nextState) - def mkHandlerCaseForState[T: WeakTypeTag]: CaseDef = - mkHandlerCase(state, stats :+ mkStateTree(nextState, symLookup)) + def mkHandlerCaseForState[T: WeakTypeTag]: CaseDef = { + mkHandlerCase(state, statsAnd(mkStateTree(nextState, symLookup) :: Nil)) + } override val toString: String = s"AsyncState #$state, next = $nextState" @@ -86,10 +92,10 @@ trait ExprBuilder { val tryGetOrCallOnComplete = if (futureSystemOps.continueCompletedFutureOnSameThread) If(futureSystemOps.isCompleted(Expr[futureSystem.Fut[_]](awaitable.expr)).tree, - Block(ifIsFailureTree[T](futureSystemOps.getCompleted[Any](Expr[futureSystem.Fut[Any]](awaitable.expr)).tree) :: Nil, literalUnit), - Block(callOnComplete :: Nil, Return(literalUnit))) + adaptToUnit(ifIsFailureTree[T](futureSystemOps.getCompleted[Any](Expr[futureSystem.Fut[Any]](awaitable.expr)).tree) :: Nil), + Block(toList(callOnComplete), Return(literalUnit))) else - Block(callOnComplete :: Nil, Return(literalUnit)) + Block(toList(callOnComplete), Return(literalUnit)) mkHandlerCase(state, stats ++ List(mkStateTree(onCompleteState, symLookup), tryGetOrCallOnComplete)) } @@ -109,11 +115,11 @@ trait ExprBuilder { */ def ifIsFailureTree[T: WeakTypeTag](tryReference: => Tree) = If(futureSystemOps.tryyIsFailure(Expr[futureSystem.Tryy[T]](tryReference)).tree, - Block(futureSystemOps.completeProm[T]( + Block(toList(futureSystemOps.completeProm[T]( Expr[futureSystem.Prom[T]](symLookup.memberRef(name.result)), Expr[futureSystem.Tryy[T]]( TypeApply(Select(tryReference, newTermName("asInstanceOf")), - List(TypeTree(futureSystemOps.tryType[T]))))).tree :: Nil, + List(TypeTree(futureSystemOps.tryType[T]))))).tree), Return(literalUnit)), Block(List(tryGetTree(tryReference)), mkStateTree(nextState, symLookup)) ) @@ -381,12 +387,12 @@ trait ExprBuilder { val t = Expr[Throwable](Ident(name.t)) val complete = futureSystemOps.completeProm[T]( Expr[futureSystem.Prom[T]](symLookup.memberRef(name.result)), futureSystemOps.tryyFailure[T](t)).tree - Block(complete :: Nil, Return(literalUnit)) + Block(toList(complete), Return(literalUnit)) })), EmptyTree) def forever(t: Tree): Tree = { val labelName = name.fresh("while$") - LabelDef(labelName, Nil, Block(t :: Nil, Apply(Ident(labelName), Nil))) + LabelDef(labelName, Nil, Block(toList(t), Apply(Ident(labelName), Nil))) } /** @@ -404,7 +410,7 @@ trait ExprBuilder { def onCompleteHandler[T: WeakTypeTag]: Tree = { val onCompletes = initStates.flatMap(_.mkOnCompleteHandler[T]).toList forever { - Block(resumeFunTree :: Nil, literalUnit) + adaptToUnit(toList(resumeFunTree)) } } } @@ -421,12 +427,32 @@ trait ExprBuilder { Assign(symLookup.memberRef(name.state), Literal(Constant(nextState))) private def mkHandlerCase(num: Int, rhs: List[Tree]): CaseDef = - mkHandlerCase(num, Block(rhs, literalUnit)) + mkHandlerCase(num, adaptToUnit(rhs)) + + private def tpeOf(t: Tree): Type = t match { + case _ if t.tpe != null => t.tpe + case Try(body, Nil, _) => tpeOf(body) + case _ => NoType + } + + private def adaptToUnit(rhs: List[Tree]): Block = { + rhs match { + case init :+ last if tpeOf(last) <:< definitions.UnitTpe => + Block(init, last) + case _ => + Block(rhs, literalUnit) + } + } private def mkHandlerCase(num: Int, rhs: Tree): CaseDef = CaseDef(Literal(Constant(num)), EmptyTree, rhs) - def literalUnit = Literal(Constant(())) + def literalUnit = Literal(Constant(())) // a def to avoid sharing trees + + def toList(tree: Tree): List[Tree] = tree match { + case Block(stats, Literal(Constant(value))) if value == () => stats + case _ => tree :: Nil + } def literalNull = Literal(Constant(null)) } |