From 3ef2995f0923fe7b2346cfd5f816196fce0f00ac Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sat, 24 Nov 2012 00:21:41 +0100 Subject: Prohibit await in if condition (for now) Test nested loops. Control ANF tracing with another system property. --- src/main/scala/scala/async/AnfTransform.scala | 4 +-- src/main/scala/scala/async/AsyncAnalysis.scala | 4 +++ src/main/scala/scala/async/AsyncUtils.scala | 12 ++++++--- src/test/scala/scala/async/TreeInterrogation.scala | 31 ++++++++++++---------- src/test/scala/scala/async/neg/NakedAwait.scala | 11 ++++++++ .../scala/scala/async/run/ifelse0/WhileSpec.scala | 20 ++++++++++++++ 6 files changed, 62 insertions(+), 20 deletions(-) diff --git a/src/main/scala/scala/async/AnfTransform.scala b/src/main/scala/scala/async/AnfTransform.scala index 0756baf..cf6ed04 100644 --- a/src/main/scala/scala/async/AnfTransform.scala +++ b/src/main/scala/scala/async/AnfTransform.scala @@ -77,9 +77,9 @@ private[async] final case class AnfTransform[C <: Context](override val c: C) ex def apply[T](prefix: String, args: Any)(t: => T): T = { indent += 1 try { - //println(s"${indentString}$prefix($args)") + AsyncUtils.trace(s"${indentString}$prefix($args)") val result = t - //println(s"${indentString}= $result") + AsyncUtils.trace(s"${indentString}= $result") result } finally { indent -= 1 diff --git a/src/main/scala/scala/async/AsyncAnalysis.scala b/src/main/scala/scala/async/AsyncAnalysis.scala index e319fe8..c1ee7f4 100644 --- a/src/main/scala/scala/async/AsyncAnalysis.scala +++ b/src/main/scala/scala/async/AsyncAnalysis.scala @@ -62,6 +62,10 @@ private[async] final case class AsyncAnalysis[C <: Context](override val c: C) e tree match { case Try(_, _, _) if containsAwait => reportUnsupportedAwait(tree, "try/catch") + super.traverse(tree) + case If(cond, _, _) if containsAwait => + reportUnsupportedAwait(cond, "condition") + super.traverse(tree) case Return(_) => c.abort(tree.pos, "return is illegal within a async block") case _ => diff --git a/src/main/scala/scala/async/AsyncUtils.scala b/src/main/scala/scala/async/AsyncUtils.scala index b2f6747..525f187 100644 --- a/src/main/scala/scala/async/AsyncUtils.scala +++ b/src/main/scala/scala/async/AsyncUtils.scala @@ -8,8 +8,12 @@ package scala.async */ object AsyncUtils { - private val verbose = false || sys.props.getOrElse("scala.async.debug", "false").equalsIgnoreCase("true") - - private[async] def vprintln(s: => Any): Unit = if (verbose) - println("[async] "+s) + private def enabled(level: String) = sys.props.getOrElse(s"scala.async.$level", "false").equalsIgnoreCase("true") + + private val verbose = enabled("debug") + private val trace = enabled("trace") + + private[async] def vprintln(s: => Any): Unit = if (verbose) println(s"[async] $s") + + private[async] def trace(s: => Any): Unit = if (trace) println(s"[async] $s") } diff --git a/src/test/scala/scala/async/TreeInterrogation.scala b/src/test/scala/scala/async/TreeInterrogation.scala index 08d2c78..485831b 100644 --- a/src/test/scala/scala/async/TreeInterrogation.scala +++ b/src/test/scala/scala/async/TreeInterrogation.scala @@ -32,29 +32,32 @@ class TreeInterrogation { val varDefs = tree1.collect { case ValDef(mods, name, _, _) if mods.hasFlag(Flag.MUTABLE) => name } - varDefs.map(_.decoded).toSet mustBe(Set("state$async", "onCompleteHandler$async", "await$1", "await$2")) + varDefs.map(_.decoded).toSet mustBe (Set("state$async", "onCompleteHandler$async", "await$1", "await$2")) } - @Test + //@Test def sandbox() { - sys.props("scala.async.debug") = "true" + sys.props("scala.async.debug") = true.toString + sys.props("scala.async.trace") = false.toString + val cm = reflect.runtime.currentMirror val tb = mkToolbox("-cp target/scala-2.10/classes") val tree = tb.parse( """ import _root_.scala.async.AsyncId._ | async { - | var xxx: Int = 0 - | var y = 0 - | println("before while") - | while (xxx < 3) { - | println("in while before await") - | y = await(xxx) - | println("in while after await") - | xxx = xxx + 1 + | var sum = 0 + | var i = 0 + | while (i < 5) { + | var j = 0 + | while (j < 5) { + | sum += await(i) * await(j) + | j += 1 + | } + | i += 1 | } - | println("after while") - | y - | }""".stripMargin) + | sum + | } + | """.stripMargin) println(tree) val tree1 = tb.typeCheck(tree.duplicate) println(cm.universe.show(tree1)) diff --git a/src/test/scala/scala/async/neg/NakedAwait.scala b/src/test/scala/scala/async/neg/NakedAwait.scala index 229feb6..b1c2d43 100644 --- a/src/test/scala/scala/async/neg/NakedAwait.scala +++ b/src/test/scala/scala/async/neg/NakedAwait.scala @@ -139,4 +139,15 @@ class NakedAwait { |""".stripMargin } } + + // TODO Anf transform if to have a simple condition. + @Test + def ifCondition() { + expectError("await must not be used under a condition.") { + """ + | import _root_.scala.async.AsyncId._ + | async { if (await(true)) () } + |""".stripMargin + } + } } diff --git a/src/test/scala/scala/async/run/ifelse0/WhileSpec.scala b/src/test/scala/scala/async/run/ifelse0/WhileSpec.scala index d08e2c5..ba1d7a5 100644 --- a/src/test/scala/scala/async/run/ifelse0/WhileSpec.scala +++ b/src/test/scala/scala/async/run/ifelse0/WhileSpec.scala @@ -40,4 +40,24 @@ class WhileSpec { } result mustBe (0) } + + @Test + def nestedWhile() { + import AsyncId._ + + val result = async { + var sum = 0 + var i = 0 + while (i < 5) { + var j = 0 + while (j < 5) { + sum += await(i) * await(j) + j += 1 + } + i += 1 + } + sum + } + result mustBe (100) + } } \ No newline at end of file -- cgit v1.2.3