aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/scala/async/AnfTransform.scala
diff options
context:
space:
mode:
authorPhilipp Haller <hallerp@gmail.com>2012-11-22 06:10:00 -0800
committerPhilipp Haller <hallerp@gmail.com>2012-11-22 06:10:00 -0800
commit1c91fec998d09e31c2c52760452af1771a092182 (patch)
tree8733f9b854baa83194b1688fa30ed5fc90fd249c /src/main/scala/scala/async/AnfTransform.scala
parentf451904320d02c7dbe6b298f6ff790ca5cf5f080 (diff)
parent8e4a8ecdff955c4faa1dec344a2b93543ffe7d45 (diff)
downloadscala-async-1c91fec998d09e31c2c52760452af1771a092182.tar.gz
scala-async-1c91fec998d09e31c2c52760452af1771a092182.tar.bz2
scala-async-1c91fec998d09e31c2c52760452af1771a092182.zip
Merge pull request #25 from phaller/topic/minimal-var-lifting-2
Topic/minimal var lifting 2
Diffstat (limited to 'src/main/scala/scala/async/AnfTransform.scala')
-rw-r--r--src/main/scala/scala/async/AnfTransform.scala101
1 files changed, 101 insertions, 0 deletions
diff --git a/src/main/scala/scala/async/AnfTransform.scala b/src/main/scala/scala/async/AnfTransform.scala
new file mode 100644
index 0000000..e1d7cd5
--- /dev/null
+++ b/src/main/scala/scala/async/AnfTransform.scala
@@ -0,0 +1,101 @@
+package scala.async
+
+import scala.reflect.macros.Context
+
+class AnfTransform[C <: Context](override val c: C) extends TransformUtils(c) {
+ import c.universe._
+ import AsyncUtils._
+
+ object inline {
+ def transformToList(tree: Tree): List[Tree] = {
+ val stats :+ expr = anf.transformToList(tree)
+ expr match {
+
+ case Apply(fun, args) if fun.toString.startsWith("scala.async.Async.await") =>
+ val liftedName = c.fresh("await$")
+ stats :+ ValDef(NoMods, liftedName, TypeTree(), expr) :+ Ident(liftedName)
+
+ case If(cond, thenp, elsep) =>
+ // if type of if-else is Unit don't introduce assignment,
+ // but add Unit value to bring it into form expected by async transform
+ if (expr.tpe =:= definitions.UnitTpe) {
+ stats :+ expr :+ Literal(Constant(()))
+ }
+ else {
+ val liftedName = c.fresh("ifres$")
+ val varDef =
+ ValDef(Modifiers(Flag.MUTABLE), liftedName, TypeTree(expr.tpe), defaultValue(expr.tpe))
+ val thenWithAssign = thenp match {
+ case Block(thenStats, thenExpr) => Block(thenStats, Assign(Ident(liftedName), thenExpr))
+ case _ => Assign(Ident(liftedName), thenp)
+ }
+ val elseWithAssign = elsep match {
+ case Block(elseStats, elseExpr) => Block(elseStats, Assign(Ident(liftedName), elseExpr))
+ case _ => Assign(Ident(liftedName), elsep)
+ }
+ val ifWithAssign =
+ If(cond, thenWithAssign, elseWithAssign)
+ stats :+ varDef :+ ifWithAssign :+ Ident(liftedName)
+ }
+ case _ =>
+ stats :+ expr
+ }
+ }
+
+ def transformToList(trees: List[Tree]): List[Tree] = trees match {
+ case fst :: rest => transformToList(fst) ++ transformToList(rest)
+ case Nil => Nil
+ }
+ }
+
+ object anf {
+ def transformToList(tree: Tree): List[Tree] = tree match {
+ case Select(qual, sel) =>
+ val stats :+ expr = inline.transformToList(qual)
+ stats :+ Select(expr, sel)
+
+ case Apply(fun, args) =>
+ val funStats :+ simpleFun = inline.transformToList(fun)
+ val argLists = args map inline.transformToList
+ val allArgStats = argLists flatMap (_.init)
+ val simpleArgs = argLists map (_.last)
+ funStats ++ allArgStats :+ Apply(simpleFun, simpleArgs)
+
+ case Block(stats, expr) =>
+ inline.transformToList(stats) ++ inline.transformToList(expr)
+
+ case ValDef(mods, name, tpt, rhs) =>
+ val stats :+ expr = inline.transformToList(rhs)
+ stats :+ ValDef(mods, name, tpt, expr).setSymbol(tree.symbol)
+
+ case Assign(name, rhs) =>
+ val stats :+ expr = inline.transformToList(rhs)
+ stats :+ Assign(name, expr)
+
+ case If(cond, thenp, elsep) =>
+ val stats :+ expr = inline.transformToList(cond)
+ val thenStats :+ thenExpr = inline.transformToList(thenp)
+ val elseStats :+ elseExpr = inline.transformToList(elsep)
+ stats :+
+ c.typeCheck(If(expr, Block(thenStats, thenExpr), Block(elseStats, elseExpr)))
+
+ //TODO
+ case Literal(_) | Ident(_) | This(_) | Match(_, _) | New(_) | Function(_, _) => List(tree)
+
+ case TypeApply(fun, targs) =>
+ val funStats :+ simpleFun = inline.transformToList(fun)
+ funStats :+ TypeApply(simpleFun, targs)
+
+ //TODO
+ case DefDef(mods, name, tparams, vparamss, tpt, rhs) => List(tree)
+
+ case ClassDef(mods, name, tparams, impl) => List(tree)
+
+ case ModuleDef(mods, name, impl) => List(tree)
+
+ case _ =>
+ c.error(tree.pos, "Internal error while compiling `async` block")
+ ???
+ }
+ }
+}