improve cps handling of if-then-else. no review.

git-svn-id: http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk@26092 5e8d7ff9-d8ef-0310-90f0-a4852d11357a
This commit is contained in:
rompf 2011-11-29 18:56:51 +00:00
parent 2a34d20013
commit 90f4ba32a2
5 changed files with 103 additions and 30 deletions

View File

@ -173,40 +173,44 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with
(Nil, tree1, cpsA)
case If(cond, thenp, elsep) =>
val (condStats, condVal, spc) = transInlineValue(cond, cpsA)
case If(cond, thenp, elsep) =>
/* possible situations:
cps before (cpsA)
cps in condition (spc) <-- synth flag set if *only* here!
cps in (one or both) branches */
val (condStats, condVal, spc) = transInlineValue(cond, cpsA)
val (cpsA2, cpsR2) = if (hasSynthMarker(tree.tpe))
(spc, linearize(spc, getAnswerTypeAnn(tree.tpe))) else
(None, getAnswerTypeAnn(tree.tpe)) // if no cps in condition, branches must conform to tree.tpe directly
val thenVal = transExpr(thenp, cpsA2, cpsR2)
val elseVal = transExpr(elsep, cpsA2, cpsR2)
val (cpsA2, cpsR2) = (spc, linearize(spc, getAnswerTypeAnn(tree.tpe)))
// val (cpsA2, cpsR2) = (None, getAnswerTypeAnn(tree.tpe))
val thenVal = transExpr(thenp, cpsA2, cpsR2)
val elseVal = transExpr(elsep, cpsA2, cpsR2)
// check that then and else parts agree (not necessary any more, but left as sanity check)
if (cpsR.isDefined) {
if (elsep == EmptyTree)
unit.error(tree.pos, "always need else part in cps code")
}
if (hasAnswerTypeAnn(thenVal.tpe) != hasAnswerTypeAnn(elseVal.tpe)) {
unit.error(tree.pos, "then and else parts must both be cps code or neither of them")
}
// check that then and else parts agree (not necessary any more, but left as sanity check)
if (cpsR.isDefined) {
if (elsep == EmptyTree)
unit.error(tree.pos, "always need else part in cps code")
}
if (hasAnswerTypeAnn(thenVal.tpe) != hasAnswerTypeAnn(elseVal.tpe)) {
unit.error(tree.pos, "then and else parts must both be cps code or neither of them")
}
(condStats, updateSynthFlag(treeCopy.If(tree, condVal, thenVal, elseVal)), spc)
(condStats, updateSynthFlag(treeCopy.If(tree, condVal, thenVal, elseVal)), spc)
case Match(selector, cases) =>
val (selStats, selVal, spc) = transInlineValue(selector, cpsA)
val (cpsA2, cpsR2) = (spc, linearize(spc, getAnswerTypeAnn(tree.tpe)))
// val (cpsA2, cpsR2) = (None, getAnswerTypeAnn(tree.tpe))
case Match(selector, cases) =>
val caseVals = for {
cd @ CaseDef(pat, guard, body) <- cases
bodyVal = transExpr(body, cpsA2, cpsR2)
} yield {
treeCopy.CaseDef(cd, transform(pat), transform(guard), bodyVal)
}
(selStats, updateSynthFlag(treeCopy.Match(tree, selVal, caseVals)), spc)
val (selStats, selVal, spc) = transInlineValue(selector, cpsA)
val (cpsA2, cpsR2) = if (hasSynthMarker(tree.tpe))
(spc, linearize(spc, getAnswerTypeAnn(tree.tpe))) else
(None, getAnswerTypeAnn(tree.tpe))
val caseVals = for {
cd @ CaseDef(pat, guard, body) <- cases
bodyVal = transExpr(body, cpsA2, cpsR2)
} yield {
treeCopy.CaseDef(cd, transform(pat), transform(guard), bodyVal)
}
(selStats, updateSynthFlag(treeCopy.Match(tree, selVal, caseVals)), spc)
case ldef @ LabelDef(name, params, rhs) =>

View File

@ -0,0 +1,4 @@
10
10
10
10

View File

@ -0,0 +1,31 @@
import scala.util.continuations._
object Test {
def sh(x1:Int) = shift( (k: Int => Int) => k(k(k(x1))))
def testA(x1: Int): Int @cps[Int] = {
sh(x1)
if (x1==42) x1 else sh(x1)
}
def testB(x1: Int): Int @cps[Int] = {
if (sh(x1)==43) x1 else x1
}
def testC(x1: Int): Int @cps[Int] = {
sh(x1)
if (sh(x1)==44) x1 else x1
}
def testD(x1: Int): Int @cps[Int] = {
sh(x1)
if (sh(x1)==45) x1 else sh(x1)
}
def main(args: Array[String]): Any = {
println(reset(1 + testA(7)))
println(reset(1 + testB(9)))
println(reset(1 + testC(9)))
println(reset(1 + testD(7)))
}
}

View File

@ -0,0 +1,2 @@
10
11

View File

@ -0,0 +1,32 @@
import scala.util.continuations._
object Test {
def sh(x1:Int) = shift( (k: Int => Int) => k(k(k(x1))))
def test(x1: Int) = {
val o7 = {
val o6 = {
val o3 =
if (7 == x1) Some(x1)
else None
if (o3.isEmpty) None
else Some(sh(x1))
}
if (o6.isEmpty) {
val o5 =
if (8 == x1) Some(x1)
else None
if (o5.isEmpty) None
else Some(sh(x1))
} else o6
}
o7.get
}
def main(args: Array[String]): Any = {
println(reset(1 + test(7)))
println(reset(1 + test(8)))
}
}