diff options
author | Tiark Rompf <tiark.rompf@epfl.ch> | 2010-03-29 09:55:44 +0000 |
---|---|---|
committer | Tiark Rompf <tiark.rompf@epfl.ch> | 2010-03-29 09:55:44 +0000 |
commit | f500aeb1fda09b3d0c142da1307694ab4dacc883 (patch) | |
tree | cbcc5857c4222fe11e5eb8bb81379d45069c9bbe | |
parent | 59da69b707e2e79fbaad4aae7fc347ca1b66a34b (diff) | |
download | scala-f500aeb1fda09b3d0c142da1307694ab4dacc883.tar.gz scala-f500aeb1fda09b3d0c142da1307694ab4dacc883.tar.bz2 scala-f500aeb1fda09b3d0c142da1307694ab4dacc883.zip |
closes 2864.
-rw-r--r-- | src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala | 29 | ||||
-rw-r--r-- | src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala | 2 | ||||
-rw-r--r-- | src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala | 4 | ||||
-rw-r--r-- | src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala | 60 | ||||
-rw-r--r-- | test/files/continuations-neg/lazy.check | 6 | ||||
-rw-r--r-- | test/files/continuations-neg/lazy.scala | 16 | ||||
-rw-r--r-- | test/files/continuations-run/t2864.check | 1 | ||||
-rw-r--r-- | test/files/continuations-run/t2864.scala | 30 | ||||
-rw-r--r-- | test/files/continuations-run/t2934.check | 1 | ||||
-rw-r--r-- | test/files/continuations-run/t2934.scala (renamed from test/pending/continuations-run/t2934.scala) | 6 | ||||
-rw-r--r-- | test/files/continuations-run/t3223.check | 1 | ||||
-rw-r--r-- | test/files/continuations-run/t3223.scala | 19 | ||||
-rw-r--r-- | test/files/continuations-run/t3225.check | 12 | ||||
-rw-r--r-- | test/files/continuations-run/t3225.scala | 56 | ||||
-rw-r--r-- | test/pending/continuations-run/t2864.scala | 18 |
15 files changed, 213 insertions, 48 deletions
diff --git a/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala b/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala index 500f102790..3b99eb2008 100644 --- a/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala +++ b/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala @@ -401,6 +401,11 @@ abstract class CPSAnnotationChecker extends CPSUtils { transChildrenInOrder(tree, tpe, qual::(transArgList(fun, args).flatten), Nil) + case TypeApply(fun @ Select(qual, name), args) if (fun.tpe ne null) && !fun.tpe.isErroneous => + vprintln("[checker] checking select apply " + tree + "/" + tpe) + + transChildrenInOrder(tree, tpe, List(qual, fun), Nil) + case Apply(fun, args) if (fun.tpe ne null) && !fun.tpe.isErroneous => vprintln("[checker] checking unknown apply " + tree + "/" + tpe) @@ -418,8 +423,28 @@ abstract class CPSAnnotationChecker extends CPSUtils { vprintln("[checker] checking select " + tree + "/" + tpe) // FIXME: put it back in?? (problem with test cases select.scala and Test2.scala) - // transChildrenInOrder(tree, tpe, List(qual)) - tpe + // transChildrenInOrder(tree, tpe, List(qual), Nil) + + //TODO: cleanup + + // seem to be only a problem if qual is of type OverloadedType + + if (!tpe.isInstanceOf[OverloadedType] && !tpe.isInstanceOf[MethodType] && !tpe.isInstanceOf[PolyType]) { + transChildrenInOrder(tree, tpe, List(qual), Nil) + } else { + if (qual.tpe.hasAnnotation(MarkerCPSTypes)) { + // If it's a method without parameters, just apply it. normally done in adapt, but + // we have to do it here so we don't lose the cps information + tpe match { + case PolyType(List(), restpe) => + //println("yep: " + restpe + "," + restpe.getClass) + transChildrenInOrder(tree, restpe, List(qual), Nil) + case _ => + tpe + } + } else + tpe + } case If(cond, thenp, elsep) => transChildrenInOrder(tree, tpe, List(cond), List(thenp, elsep)) diff --git a/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala b/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala index 566f175183..57cba6e829 100644 --- a/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala +++ b/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala @@ -11,7 +11,7 @@ trait CPSUtils { var cpsEnabled = false val verbose: Boolean = System.getProperty("cpsVerbose", "false") == "true" - @inline def vprintln(x: =>Any): Unit = if (verbose) println(x) + @inline final def vprintln(x: =>Any): Unit = if (verbose) println(x) lazy val MarkerCPSSym = definitions.getClass("scala.util.continuations.cpsSym") diff --git a/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala b/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala index 5bad9e960c..92ec00be66 100644 --- a/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala +++ b/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala @@ -192,8 +192,8 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with .setInfo(ldef.symbol.info) .setFlag(Flags.SYNTHETIC) - val subst = new TreeSymSubstituter(List(ldef.symbol), List(sym)) - val rhsVal = transExpr(subst(rhs), None, getAnswerTypeAnn(tree.tpe)) + new TreeSymSubstituter(List(ldef.symbol), List(sym)).traverse(rhs) + val rhsVal = transExpr(rhs, None, getAnswerTypeAnn(tree.tpe)) val stm1 = localTyper.typed(DefDef(sym, rhsVal)) val expr = localTyper.typed(Apply(Ident(sym), List())) diff --git a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala index 3c35149636..15adfa7d82 100644 --- a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala +++ b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala @@ -84,6 +84,9 @@ abstract class SelectiveCPSTransform extends PluginComponent with log("found shift: " + tree) atPos(tree.pos) { val funR = gen.mkAttributedRef(MethShiftR) // TODO: correct? + //gen.mkAttributedSelect(gen.mkAttributedSelect(gen.mkAttributedSelect(gen.mkAttributedIdent(ScalaPackage), + //ScalaPackage.tpe.member("util")), ScalaPackage.tpe.member("util").tpe.member("continuations")), MethShiftR) + //gen.mkAttributedRef(ModCPS.tpe, MethShiftR) // TODO: correct? log(funR.tpe) Apply( TypeApply(funR, targs).setType(appliedType(funR.tpe, targs.map((t:Tree) => t.tpe))), @@ -183,21 +186,32 @@ abstract class SelectiveCPSTransform extends PluginComponent with case expr => (Nil, expr) } - val expr2 = if (catches.nonEmpty) { - val pos = catches.head.pos - val arg = currentOwner.newValueParameter(pos, "$ex").setInfo(ThrowableClass.tpe) - val catches2 = catches1 map (duplicateTree(_).asInstanceOf[CaseDef]) - val rhs = Match(Ident(arg), catches2) - val fun = Function(List(ValDef(arg)), rhs) - val expr2 = localTyper.typed(atPos(pos) { Apply(Select(expr1, expr1.tpe.member("flatMapCatch")), List(fun)) }) + val targettp = transformCPSType(tree.tpe) - arg.owner = fun.symbol +// val expr2 = if (catches.nonEmpty) { + val pos = catches.head.pos + val argSym = currentOwner.newValueParameter(pos, "$ex").setInfo(ThrowableClass.tpe) + val rhs = Match(Ident(argSym), catches1) + val fun = Function(List(ValDef(argSym)), rhs) + val funSym = currentOwner.newValueParameter(pos, "$catches").setInfo(appliedType(PartialFunctionClass.tpe, List(ThrowableClass.tpe, targettp))) + val funDef = localTyper.typed(atPos(pos) { ValDef(funSym, fun) }) + val expr2 = localTyper.typed(atPos(pos) { Apply(Select(expr1, expr1.tpe.member("flatMapCatch")), List(Ident(funSym))) }) + + argSym.owner = fun.symbol val chown = new ChangeOwnerTraverser(currentOwner, fun.symbol) chown.traverse(rhs) - expr2 - } else - expr1 + val exSym = currentOwner.newValueParameter(pos, "$ex").setInfo(ThrowableClass.tpe) + val catch2 = { localTyper.typedCases(tree, List( + CaseDef(Bind(exSym, Typed(Ident("_"), TypeTree(ThrowableClass.tpe))), + Apply(Select(Ident(funSym), "isDefinedAt"), List(Ident(exSym))), + Apply(Ident(funSym), List(Ident(exSym)))) + ), ThrowableClass.tpe, targettp) } + + //typedCases(tree, catches, ThrowableClass.tpe, pt) + + localTyper.typed(Block(List(funDef), treeCopy.Try(tree, treeCopy.Block(block1, stms, expr2), catch2, finalizer1))) + /* disabled for now - see notes above @@ -215,9 +229,6 @@ abstract class SelectiveCPSTransform extends PluginComponent with } else expr2 */ - - - treeCopy.Try(tree, treeCopy.Block(block1, stms, expr2), catches1, finalizer1) } else { treeCopy.Try(tree, block1, catches1, finalizer1) } @@ -249,7 +260,9 @@ abstract class SelectiveCPSTransform extends PluginComponent with log("found marked ValDef "+name+" of type " + vd.symbol.tpe) val tpe = vd.symbol.tpe - val rhs1 = transform(rhs) + val rhs1 = atOwner(vd.symbol) { transform(rhs) } + + new ChangeOwnerTraverser(vd.symbol, currentOwner).traverse(rhs1) // TODO: don't traverse twice log("valdef symbol " + vd.symbol + " has type " + tpe) log("right hand side " + rhs1 + " has type " + rhs1.tpe) @@ -257,8 +270,10 @@ abstract class SelectiveCPSTransform extends PluginComponent with log("currentOwner: " + currentOwner) log("currentMethod: " + currentMethod) - val (bodyStms, bodyExpr) = transBlock(rest, expr) + // FIXME: result will later be traversed again by TreeSymSubstituter and + // ChangeOwnerTraverser => exp. running time. + // Should be changed to fuse traversals into one. val specialCaseTrivial = bodyExpr match { case Apply(fun, args) => @@ -291,6 +306,8 @@ abstract class SelectiveCPSTransform extends PluginComponent with arg.owner = fun.symbol new ChangeOwnerTraverser(currentOwner, fun.symbol).traverse(body) + // see note about multiple traversals above + log("fun.symbol: "+fun.symbol) log("fun.symbol.owner: "+fun.symbol.owner) log("arg.owner: "+arg.owner) @@ -314,6 +331,8 @@ abstract class SelectiveCPSTransform extends PluginComponent with }) } + def mkBlock(stms: List[Tree], expr: Tree) = if (stms.nonEmpty) Block(stms, expr) else expr + try { if (specialCaseTrivial) { log("will optimize possible tail call: " + bodyExpr) @@ -332,9 +351,9 @@ abstract class SelectiveCPSTransform extends PluginComponent with val argSym = currentOwner.newValue(vd.symbol.name).setInfo(tpe) val argDef = localTyper.typed(ValDef(argSym, Select(ctxRef, ctxRef.tpe.member("getTrivialValue")))) val switchExpr = localTyper.typed(atPos(vd.symbol.pos) { - val body2 = duplicateTree(Block(bodyStms, bodyExpr)) // dup before typing! + val body2 = duplicateTree(mkBlock(bodyStms, bodyExpr)) // dup before typing! If(Select(ctxRef, ctxSym.tpe.member("isTrivial")), - applyTrivial(argSym, Block(argDef::bodyStms, bodyExpr)), + applyTrivial(argSym, mkBlock(argDef::bodyStms, bodyExpr)), applyCombinatorFun(ctxRef, body2)) }) (List(ctxDef), switchExpr) @@ -342,7 +361,7 @@ abstract class SelectiveCPSTransform extends PluginComponent with // ctx.flatMap { <lhs> => ... } // or // ctx.map { <lhs> => ... } - (Nil, applyCombinatorFun(rhs1, Block(bodyStms, bodyExpr))) + (Nil, applyCombinatorFun(rhs1, mkBlock(bodyStms, bodyExpr))) } } catch { case ex:TypeError => @@ -351,8 +370,9 @@ abstract class SelectiveCPSTransform extends PluginComponent with } case _ => + val stm1 = transform(stm) val (a, b) = transBlock(rest, expr) - (transform(stm)::a, b) + (stm1::a, b) } } } diff --git a/test/files/continuations-neg/lazy.check b/test/files/continuations-neg/lazy.check new file mode 100644 index 0000000000..bfa44c59a4 --- /dev/null +++ b/test/files/continuations-neg/lazy.check @@ -0,0 +1,6 @@ +lazy.scala:5: error: type mismatch; + found : Unit @scala.util.continuations.cpsParam[Unit,Unit] + required: Unit + def foo = { + ^ +one error found diff --git a/test/files/continuations-neg/lazy.scala b/test/files/continuations-neg/lazy.scala new file mode 100644 index 0000000000..dffc57ffa0 --- /dev/null +++ b/test/files/continuations-neg/lazy.scala @@ -0,0 +1,16 @@ +import scala.util.continuations._ + +object Test { + + def foo = { + lazy val x = shift((k:Unit=>Unit)=>k()) + println(x) + } + + def main(args: Array[String]) { + reset { + foo + } + } + +}
\ No newline at end of file diff --git a/test/files/continuations-run/t2864.check b/test/files/continuations-run/t2864.check new file mode 100644 index 0000000000..d411bb7c1a --- /dev/null +++ b/test/files/continuations-run/t2864.check @@ -0,0 +1 @@ +400 diff --git a/test/files/continuations-run/t2864.scala b/test/files/continuations-run/t2864.scala new file mode 100644 index 0000000000..7a2579e45c --- /dev/null +++ b/test/files/continuations-run/t2864.scala @@ -0,0 +1,30 @@ +import scala.util.continuations._ +object Test { + + def double[B](n : Int)(k : Int => B) : B = k(n * 2) + + def main(args : Array[String]) { + reset { + val result1 = shift(double[Unit](100)) + val result2 = shift(double[Unit](result1)) + println(result2) + } + } + + def foo: Int @cps[Int] = { + val a0 = shift((k:Int=>Int) => k(0)) + val x0 = 2 + val a1 = shift((k:Int=>Int) => x0) + 0 + } + +/* + def bar: ControlContext[Int,Int,Int] = { + shiftR((k:Int=>Int) => k(0)).flatMap { a0 => + val x0 = 2 + shiftR((k:Int=>Int) => x0).map { a1 => + 0 + }} + } +*/ +}
\ No newline at end of file diff --git a/test/files/continuations-run/t2934.check b/test/files/continuations-run/t2934.check new file mode 100644 index 0000000000..a92586538e --- /dev/null +++ b/test/files/continuations-run/t2934.check @@ -0,0 +1 @@ +List(3, 4, 5) diff --git a/test/pending/continuations-run/t2934.scala b/test/files/continuations-run/t2934.scala index 6089355bcf..a1b8ca9e04 100644 --- a/test/pending/continuations-run/t2934.scala +++ b/test/files/continuations-run/t2934.scala @@ -1,14 +1,10 @@ -// $Id$ - import scala.util.continuations._ - object Test { - def main(args : Array[String]) { println(reset { val x = shift(List(1,2,3).flatMap[Int, List[Int]]) List(x + 2) }) } -}
\ No newline at end of file +} diff --git a/test/files/continuations-run/t3223.check b/test/files/continuations-run/t3223.check new file mode 100644 index 0000000000..ec635144f6 --- /dev/null +++ b/test/files/continuations-run/t3223.check @@ -0,0 +1 @@ +9 diff --git a/test/files/continuations-run/t3223.scala b/test/files/continuations-run/t3223.scala new file mode 100644 index 0000000000..4e510178e6 --- /dev/null +++ b/test/files/continuations-run/t3223.scala @@ -0,0 +1,19 @@ +import scala.util.continuations._ +object Test { + + def foo(x:Int) = { + try { + throw new Exception + shiftUnit0[Int,Int](7) + } catch { + case ex => + val g = (a:Int)=>a + 9 + } + } + + def main(args: Array[String]) { + println(reset(foo(0))) + } + +}
\ No newline at end of file diff --git a/test/files/continuations-run/t3225.check b/test/files/continuations-run/t3225.check new file mode 100644 index 0000000000..df1a8a9ce4 --- /dev/null +++ b/test/files/continuations-run/t3225.check @@ -0,0 +1,12 @@ +8 +8 +9 +9 +8 +9 +8 +8 +9 +9 +8 +9 diff --git a/test/files/continuations-run/t3225.scala b/test/files/continuations-run/t3225.scala new file mode 100644 index 0000000000..ecfde279cf --- /dev/null +++ b/test/files/continuations-run/t3225.scala @@ -0,0 +1,56 @@ +// $Id$ + +import scala.util.continuations._ + + +object Test { + + class Bla { + val x = 8 + def y[T] = 9 + } + +/* + def bla[A] = shift { k:(Bla=>A) => k(new Bla) } +*/ + + def bla1 = shift { k:(Bla=>Bla) => k(new Bla) } + def bla2 = shift { k:(Bla=>Int) => k(new Bla) } + + def fooA = bla2.x + def fooB[T] = bla2.y[T] + + def testMono() = { + println(reset(bla1).x) + println(reset(bla2.x)) + println(reset(bla2.y[Int])) + println(reset(bla2.y)) + println(reset(fooA)) + println(reset(fooB)) + 0 + } + + def blaX[A] = shift { k:(Bla=>A) => k(new Bla) } + + def fooX[A] = blaX[A].x + def fooY[A] = blaX[A].y[A] + + def testPoly() = { + println(reset(blaX[Bla]).x) + println(reset(blaX[Int].x)) + println(reset(blaX[Int].y[Int])) + println(reset(blaX[Int].y)) + println(reset(fooX[Int])) + println(reset(fooY[Int])) + 0 + } + + + // TODO: check whether this also applies to a::shift { k => ... } + + def main(args: Array[String]) = { + testMono() + testPoly() + } + +} diff --git a/test/pending/continuations-run/t2864.scala b/test/pending/continuations-run/t2864.scala deleted file mode 100644 index 291e739332..0000000000 --- a/test/pending/continuations-run/t2864.scala +++ /dev/null @@ -1,18 +0,0 @@ -// $Id$ - -import scala.util.continuations._ - - - -object Test { - - def double[B](n : Int)(k : Int => B) : B = k(n * 2) - - def main(args : Array[String]) { - reset { - val result1 = shift(double[Unit](100)) - val result2 = shift(double[Unit](result1)) - println(result2) - } - } -}
\ No newline at end of file |