aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/scala/async/ExprBuilder.scala
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2012-11-09 14:29:35 +0100
committerJason Zaugg <jzaugg@gmail.com>2012-11-09 15:47:17 +0100
commit370be9ea41c582f033a2eeef05157e77a5077144 (patch)
tree6f58e3d93f1289bbef687e7695ce3fcf36e7014b /src/main/scala/scala/async/ExprBuilder.scala
parentd434c20cfb8623a243cd30f187907bb4b199dc99 (diff)
downloadscala-async-370be9ea41c582f033a2eeef05157e77a5077144.tar.gz
scala-async-370be9ea41c582f033a2eeef05157e77a5077144.tar.bz2
scala-async-370be9ea41c582f033a2eeef05157e77a5077144.zip
Further cleanup in AST generation
- centralize names - centralize more module/class lookup - reduce duplication - centralize use of resetAllAttrs - remove uses of asInstanceOf
Diffstat (limited to 'src/main/scala/scala/async/ExprBuilder.scala')
-rw-r--r--src/main/scala/scala/async/ExprBuilder.scala166
1 files changed, 92 insertions, 74 deletions
diff --git a/src/main/scala/scala/async/ExprBuilder.scala b/src/main/scala/scala/async/ExprBuilder.scala
index 4beaa34..65e98e0 100644
--- a/src/main/scala/scala/async/ExprBuilder.scala
+++ b/src/main/scala/scala/async/ExprBuilder.scala
@@ -19,11 +19,28 @@ final class ExprBuilder[C <: Context, FS <: FutureSystem](val c: C, val futureSy
import Flag._
import defn._
- val execContextType = c.weakTypeOf[futureSystem.ExecContext]
- val execContext = futureSystemOps.execContext
+ object name {
+ // TODO do we need to freshen any of these?
+ val resume = newTermName("resume")
+ val state = newTermName("state")
+ val result = newTermName("result")
+ val tr = newTermName("tr")
+ val any = newTermName("any")
+ val x1 = newTermName("x$1")
+ val apply = newTermName("apply")
+ val isDefinedAt = newTermName("isDefinedAt")
+
+ val anon = newTypeName("$anon")
+ }
+
+ private val execContext = futureSystemOps.execContext
+
+ private def resetDuplicate(tree: Tree) = c.resetAllAttrs(tree.duplicate)
private val awaitMethod = awaitSym(c)
+ private def mkResumeApply = Apply(Ident(name.resume), List())
+
/* Make a partial function literal handling case #num:
*
* {
@@ -43,22 +60,18 @@ final class ExprBuilder[C <: Context, FS <: FutureSystem](val c: C, val futureSy
}
})
*/
- val rhsTree = c.resetAllAttrs(rhs.tree.duplicate)
+ val rhsTree = resetDuplicate(rhs.tree)
val handlerTree = mkHandlerTree(num, rhsTree)
- c.Expr(handlerTree).asInstanceOf[c.Expr[PartialFunction[Int, Unit]]]
- }
-
- def mkIncrStateTree(): c.Tree = {
- Assign(
- Ident(newTermName("state")),
- mkInt_+(c.Expr[Int](Ident(newTermName("state"))))(c.literal(1)).tree
- )
+ c.Expr(handlerTree)
}
def mkStateTree(nextState: Int): c.Tree =
+ mkStateTree(c.literal(nextState).tree)
+
+ def mkStateTree(nextState: Tree): c.Tree =
Assign(
- Ident(newTermName("state")),
- Literal(Constant(nextState)))
+ Ident(name.state),
+ nextState)
def defaultValue(tpe: Type): Literal = {
val defaultValue: Any =
@@ -72,61 +85,68 @@ final class ExprBuilder[C <: Context, FS <: FutureSystem](val c: C, val futureSy
ValDef(Modifiers(Flag.MUTABLE), resultName, TypeTree(resultType), defaultValue(resultType))
}
+ def mkHandlerCase(num: Int, rhs: List[c.Tree]): CaseDef =
+ mkHandlerCase(num, Block(rhs: _*))
+
def mkHandlerCase(num: Int, rhs: c.Tree): CaseDef =
CaseDef(
// pattern
- Bind(newTermName("any"), Typed(Ident(nme.WILDCARD), Ident(definitions.IntClass))),
+ Bind(name.any, Typed(Ident(nme.WILDCARD), Ident(definitions.IntClass))),
// guard
- mkAny_==(c.Expr(Ident(newTermName("any"))))(c.literal(num)).tree,
+ mkAny_==(c.Expr(Ident(name.any)))(c.literal(num)).tree,
rhs
)
def mkHandlerTreeFor(cases: List[(CaseDef, Int)]): c.Tree = {
- val partFunIdent = Ident(c.mirror.staticClass("scala.PartialFunction"))
+ val partFunIdent = Ident(defn.PartialFunctionClass)
val intIdent = Ident(definitions.IntClass)
val unitIdent = Ident(definitions.UnitClass)
val caseCheck =
- defn.mkList_contains(defn.mkList_apply(cases.map(p => c.literal(p._2))))(c.Expr(Ident(newTermName("x$1"))))
+ defn.mkList_contains(defn.mkList_apply(cases.map(p => c.literal(p._2))))(c.Expr(Ident(name.x1)))
Block(List(
// anonymous subclass of PartialFunction[Int, Unit]
// TODO subclass AbstractPartialFunction
- ClassDef(Modifiers(FINAL), newTypeName("$anon"), List(), Template(List(AppliedTypeTree(partFunIdent, List(intIdent, unitIdent))),
+ ClassDef(Modifiers(FINAL), name.anon, List(), Template(List(AppliedTypeTree(partFunIdent, List(intIdent, unitIdent))),
emptyValDef, List(
DefDef(Modifiers(), nme.CONSTRUCTOR, List(), List(List()), TypeTree(),
- Block(List(Apply(Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR), List())), Literal(Constant(())))),
+ Block(List(Apply(Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR), List())), c.literalUnit.tree)),
- DefDef(Modifiers(), newTermName("isDefinedAt"), List(), List(List(ValDef(Modifiers(PARAM), newTermName("x$1"), intIdent, EmptyTree))), TypeTree(),
+ DefDef(Modifiers(), name.isDefinedAt, List(), List(List(ValDef(Modifiers(PARAM), name.x1, intIdent, EmptyTree))), TypeTree(),
caseCheck.tree),
- DefDef(Modifiers(), newTermName("apply"), List(), List(List(ValDef(Modifiers(PARAM), newTermName("x$1"), intIdent, EmptyTree))), TypeTree(),
- Match(Ident(newTermName("x$1")), cases.map(_._1)) // combine all cases into a single match
+ DefDef(Modifiers(), name.apply, List(), List(List(ValDef(Modifiers(PARAM), name.x1, intIdent, EmptyTree))), TypeTree(),
+ Match(Ident(name.x1), cases.map(_._1)) // combine all cases into a single match
)
))
)),
- Apply(Select(New(Ident(newTypeName("$anon"))), nme.CONSTRUCTOR), List())
+ Apply(Select(New(Ident(name.anon)), nme.CONSTRUCTOR), List())
)
}
def mkHandlerTree(num: Int, rhs: c.Tree): c.Tree =
mkHandlerTreeFor(List(mkHandlerCase(num, rhs) -> num))
+ def mkHandlerTree(num: Int, rhs: List[c.Tree]): c.Tree =
+ mkHandlerTree(num, Block(rhs: _*))
+
class AsyncState(stats: List[c.Tree], val state: Int, val nextState: Int) {
- val body: c.Tree =
- if (stats.size == 1) stats.head
- else Block(stats: _*)
+ val body: c.Tree = stats match {
+ case stat :: Nil => stat
+ case _ => Block(stats: _*)
+ }
val varDefs: List[(TermName, Type)] = List()
def mkHandlerCaseForState(): CaseDef =
- mkHandlerCase(state, Block((stats :+ mkStateTree(nextState) :+ Apply(Ident("resume"), List())): _*))
+ mkHandlerCase(state, stats :+ mkStateTree(nextState) :+ mkResumeApply)
def mkHandlerTreeForState(): c.Tree =
- mkHandlerTree(state, Block((stats :+ mkStateTree(nextState) :+ Apply(Ident("resume"), List())): _*))
+ mkHandlerTree(state, stats :+ mkStateTree(nextState) :+ mkResumeApply)
def mkHandlerTreeForState(nextState: Int): c.Tree =
- mkHandlerTree(state, Block((stats :+ mkStateTree(nextState) :+ Apply(Ident("resume"), List())): _*))
+ mkHandlerTree(state, stats :+ mkStateTree(nextState) :+ mkResumeApply)
def varDefForResult: Option[c.Tree] =
None
@@ -143,12 +163,12 @@ final class ExprBuilder[C <: Context, FS <: FutureSystem](val c: C, val futureSy
// nextState unused, since encoded in then and else branches
override def mkHandlerTreeForState(): c.Tree =
- mkHandlerTree(state, Block(stats: _*))
+ mkHandlerTree(state, stats)
//TODO mkHandlerTreeForState(nextState: Int)
override def mkHandlerCaseForState(): CaseDef =
- mkHandlerCase(state, Block(stats: _*))
+ mkHandlerCase(state, stats)
override val toString: String =
s"AsyncStateWithIf #$state, next = $nextState"
@@ -160,6 +180,8 @@ final class ExprBuilder[C <: Context, FS <: FutureSystem](val c: C, val futureSy
val resultName: TermName
val resultType: Type
+ protected def tryType = appliedType(TryClass.toType, List(resultType))
+
override val toString: String =
s"AsyncStateWithAwait #$state, next = $nextState"
@@ -174,15 +196,15 @@ final class ExprBuilder[C <: Context, FS <: FutureSystem](val c: C, val futureSy
def mkOnCompleteTree: c.Tree = {
val assignTree =
Assign(
- Ident(resultName.toString),
- mkTry_get(c.Expr(Ident("tr"))).tree
+ Ident(resultName),
+ mkTry_get(c.Expr(Ident(name.tr))).tree
)
val handlerTree =
Match(
EmptyTree,
List(
- CaseDef(Bind(newTermName("tr"), Ident("_")), EmptyTree,
- Block(assignTree, Apply(Ident("resume"), List())) // rhs of case
+ CaseDef(Bind(name.tr, Ident("_")), EmptyTree,
+ Block(assignTree, mkResumeApply) // rhs of case
)
)
)
@@ -198,20 +220,8 @@ final class ExprBuilder[C <: Context, FS <: FutureSystem](val c: C, val futureSy
* resume()
* }
*/
- def mkOnCompleteIncrStateTree: c.Tree = {
- val tryGetTree =
- Assign(
- Ident(resultName.toString),
- Select(Ident("tr"), Try_get)
- )
-
- val handlerTree =
- Function(List(ValDef(Modifiers(PARAM), newTermName("tr"), TypeTree(tryType), EmptyTree)), Block(tryGetTree, mkIncrStateTree(), Apply(Ident("resume"), List())))
-
- futureSystemOps.onComplete(c.Expr(awaitable), c.Expr(handlerTree), execContext).tree
- }
-
- def tryType = appliedType(c.mirror.staticClass("scala.util.Try").toType, List(resultType))
+ def mkOnCompleteIncrStateTree: c.Tree =
+ mkOnCompleteTree(mkInt_+(c.Expr[Int](Ident(name.state)))(c.literal(1)).tree)
/* Make an `onComplete` invocation which sets the state to `nextState` upon resuming:
*
@@ -222,14 +232,20 @@ final class ExprBuilder[C <: Context, FS <: FutureSystem](val c: C, val futureSy
* resume()
* }
*/
- def mkOnCompleteStateTree(nextState: Int): c.Tree = {
+ def mkOnCompleteStateTree(nextState: Int): c.Tree =
+ mkOnCompleteTree(c.literal(nextState).tree)
+
+ private def mkOnCompleteTree(nextState: Tree): c.Tree = {
val tryGetTree =
Assign(
- Ident(resultName.toString),
- Select(Ident("tr"), Try_get)
+ Ident(resultName),
+ Select(Ident(name.tr), Try_get)
)
+
+ val updateState = mkStateTree(nextState)
+
val handlerTree =
- Function(List(ValDef(Modifiers(PARAM), newTermName("tr"), TypeTree(tryType), EmptyTree)), Block(tryGetTree, mkStateTree(nextState), Apply(Ident("resume"), List())))
+ Function(List(ValDef(Modifiers(PARAM), name.tr, TypeTree(tryType), EmptyTree)), Block(tryGetTree, updateState, mkResumeApply))
futureSystemOps.onComplete(c.Expr(awaitable), c.Expr(handlerTree), execContext).tree
}
@@ -240,7 +256,7 @@ final class ExprBuilder[C <: Context, FS <: FutureSystem](val c: C, val futureSy
* case any if any == num =>
* stats
* awaitable.onComplete {
- * case tr =>
+ * (try: Try[A]) =>
* resultName = tr.get
* resume()
* }
@@ -266,17 +282,17 @@ final class ExprBuilder[C <: Context, FS <: FutureSystem](val c: C, val futureSy
*/
override def mkHandlerTreeForState(): c.Tree = {
assert(awaitable != null)
- mkHandlerTree(state, Block((stats :+ mkOnCompleteIncrStateTree): _*))
+ mkHandlerTree(state, stats :+ mkOnCompleteIncrStateTree)
}
override def mkHandlerTreeForState(nextState: Int): c.Tree = {
assert(awaitable != null)
- mkHandlerTree(state, Block((stats :+ mkOnCompleteStateTree(nextState)): _*))
+ mkHandlerTree(state, stats :+ mkOnCompleteStateTree(nextState))
}
override def mkHandlerCaseForState(): CaseDef = {
assert(awaitable != null)
- mkHandlerCase(state, Block((stats :+ mkOnCompleteIncrStateTree): _*))
+ mkHandlerCase(state, stats :+ mkOnCompleteIncrStateTree)
}
override def varDefForResult: Option[c.Tree] =
@@ -315,7 +331,7 @@ final class ExprBuilder[C <: Context, FS <: FutureSystem](val c: C, val futureSy
}
def +=(stat: c.Tree): this.type = {
- stats += c.resetAllAttrs(renamer.transform(stat).duplicate)
+ stats += resetDuplicate(renamer.transform(stat))
this
}
@@ -323,7 +339,7 @@ final class ExprBuilder[C <: Context, FS <: FutureSystem](val c: C, val futureSy
def addVarDef(mods: Any, name: TermName, tpt: c.Tree, rhs: c.Tree, extNameMap: Map[c.Symbol, c.Name]): this.type = {
varDefs += (name -> tpt.tpe)
nameMap ++= extNameMap // update name map
- this += Assign(Ident(name), c.resetAllAttrs(renamer.transform(rhs).duplicate))
+ this += Assign(Ident(name), rhs)
this
}
@@ -357,7 +373,7 @@ final class ExprBuilder[C <: Context, FS <: FutureSystem](val c: C, val futureSy
def complete(awaitArg: c.Tree, awaitResultName: TermName, awaitResultType: Tree,
extNameMap: Map[c.Symbol, c.Name], nextState: Int = state + 1): this.type = {
nameMap ++= extNameMap
- awaitable = c.resetAllAttrs(renamer.transform(awaitArg).duplicate)
+ awaitable = resetDuplicate(renamer.transform(awaitArg))
resultName = awaitResultName
resultType = awaitResultType.tpe
this.nextState = nextState
@@ -372,10 +388,10 @@ final class ExprBuilder[C <: Context, FS <: FutureSystem](val c: C, val futureSy
def resultWithIf(condTree: c.Tree, thenState: Int, elseState: Int): AsyncState = {
// 1. build changed if-else tree
// 2. insert that tree at the end of the current state
- val cond = c.resetAllAttrs(condTree.duplicate)
+ val cond = resetDuplicate(condTree)
this += If(cond,
- Block(mkStateTree(thenState), Apply(Ident("resume"), List())),
- Block(mkStateTree(elseState), Apply(Ident("resume"), List())))
+ Block(mkStateTree(thenState), mkResumeApply),
+ Block(mkStateTree(elseState), mkResumeApply))
new AsyncStateWithoutAwait(stats.toList, state) {
override val varDefs = self.varDefs.toList
}
@@ -395,10 +411,10 @@ final class ExprBuilder[C <: Context, FS <: FutureSystem](val c: C, val futureSy
def resultWithMatch(scrutTree: c.Tree, cases: List[CaseDef], stateFirstCase: Int, perCasebudget: Int): AsyncState = {
// 1. build list of changed cases
val newCases = for ((cas, num) <- cases.zipWithIndex) yield cas match {
- case CaseDef(pat, guard, rhs) => CaseDef(pat, guard, Block(mkStateTree(num * perCasebudget + stateFirstCase), Apply(Ident("resume"), List())))
+ case CaseDef(pat, guard, rhs) => CaseDef(pat, guard, Block(mkStateTree(num * perCasebudget + stateFirstCase), mkResumeApply))
}
// 2. insert changed match tree at the end of the current state
- this += Match(c.resetAllAttrs(scrutTree.duplicate), newCases)
+ this += Match(resetDuplicate(scrutTree), newCases)
new AsyncStateWithoutAwait(stats.toList, state) {
override val varDefs = self.varDefs.toList
}
@@ -439,7 +455,7 @@ final class ExprBuilder[C <: Context, FS <: FutureSystem](val c: C, val futureSy
def builderForBranch(tree: c.Tree, state: Int, nextState: Int, budget: Int, nameMap: Map[c.Symbol, c.Name]): AsyncBlockBuilder = {
val (branchStats, branchExpr) = tree match {
case Block(s, e) => (s, e)
- case _ => (List(tree), Literal(Constant(())))
+ case _ => (List(tree), c.literalUnit.tree)
}
new AsyncBlockBuilder(branchStats, branchExpr, state, nextState, budget, nameMap)
}
@@ -451,7 +467,7 @@ final class ExprBuilder[C <: Context, FS <: FutureSystem](val c: C, val futureSy
val newName = c.fresh(name)
toRename += (stat.symbol -> newName)
- asyncStates += stateBuilder.complete(args(0), newName, tpt, toRename).result // complete with await
+ asyncStates += stateBuilder.complete(args.head, newName, tpt, toRename).result // complete with await
if (remainingBudget > 0)
remainingBudget -= 1
else
@@ -508,7 +524,7 @@ final class ExprBuilder[C <: Context, FS <: FutureSystem](val c: C, val futureSy
for ((cas, num) <- cases.zipWithIndex) {
val (casStats, casExpr) = cas match {
case CaseDef(_, _, Block(s, e)) => (s, e)
- case CaseDef(_, _, rhs) => (List(rhs), Literal(Constant(())))
+ case CaseDef(_, _, rhs) => (List(rhs), c.literalUnit.tree)
}
val builder = new AsyncBlockBuilder(casStats, casExpr, currState + (num * perCaseBudget) + 1, currState + matchBudget, perCaseBudget, toRename)
asyncStates ++= builder.asyncStates
@@ -532,9 +548,7 @@ final class ExprBuilder[C <: Context, FS <: FutureSystem](val c: C, val futureSy
assert(asyncStates.size > 1)
val cases = for (state <- asyncStates.toList) yield state.mkHandlerCaseForState()
- reify {
- c.Expr[PartialFunction[Int, Unit]](mkHandlerTreeFor(cases zip asyncStates.init.map(_.state))).splice: PartialFunction[Int, Unit]
- }
+ c.Expr(mkHandlerTreeFor(cases zip asyncStates.init.map(_.state)))
}
/* Builds the handler expression for a sequence of async states.
@@ -543,7 +557,7 @@ final class ExprBuilder[C <: Context, FS <: FutureSystem](val c: C, val futureSy
assert(asyncStates.size > 1)
var handlerExpr =
- c.Expr(asyncStates(0).mkHandlerTreeForState()).asInstanceOf[c.Expr[PartialFunction[Int, Unit]]]
+ c.Expr[PartialFunction[Int, Unit]](asyncStates.head.mkHandlerTreeForState())
if (asyncStates.size == 2)
handlerExpr
@@ -551,7 +565,7 @@ final class ExprBuilder[C <: Context, FS <: FutureSystem](val c: C, val futureSy
for (asyncState <- asyncStates.tail.init) {
// do not traverse first or last state
val handlerTreeForNextState = asyncState.mkHandlerTreeForState()
- val currentHandlerTreeNaked = c.resetAllAttrs(handlerExpr.tree.duplicate)
+ val currentHandlerTreeNaked = resetDuplicate(handlerExpr.tree)
handlerExpr = mkPartialFunction_orElse(c.Expr(currentHandlerTreeNaked))(c.Expr(handlerTreeForNextState))
}
handlerExpr
@@ -594,7 +608,11 @@ final class ExprBuilder[C <: Context, FS <: FutureSystem](val c: C, val futureSy
self.splice.get
}
- val Try_get = methodSym(reify((null.asInstanceOf[scala.util.Try[Any]]).get))
+ val Try_get = methodSym(reify((null: scala.util.Try[Any]).get))
+
+ val PartialFunctionClass = c.mirror.staticClass("scala.PartialFunction")
+ val TryClass = c.mirror.staticClass("scala.util.Try")
+ val NonFatalClass = c.mirror.staticModule("scala.util.control.NonFatal")
}
}