diff options
Diffstat (limited to 'src/continuations')
4 files changed, 39 insertions, 56 deletions
diff --git a/src/continuations/library/scala/util/continuations/ControlContext.scala b/src/continuations/library/scala/util/continuations/ControlContext.scala index 19c2bc4038..910ca60eb0 100644 --- a/src/continuations/library/scala/util/continuations/ControlContext.scala +++ b/src/continuations/library/scala/util/continuations/ControlContext.scala @@ -13,7 +13,7 @@ import annotation.{ Annotation, StaticAnnotation, TypeConstraint } /** This annotation is used to mark a parameter as part of a continuation * context. * - * The type `A @cps[B,C]` is desugared to `ControlContext[A,B,C]` at compile + * The type `A @cpsParam[B,C]` is desugared to `ControlContext[A,B,C]` at compile * time. * * @tparam B The type of computation state after computation has executed, and diff --git a/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala b/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala index bed8e93d1b..862b19d0a4 100644 --- a/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala +++ b/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala @@ -3,8 +3,9 @@ package scala.tools.selectivecps import scala.tools.nsc.Global +import scala.tools.nsc.typechecker.Modes -abstract class CPSAnnotationChecker extends CPSUtils { +abstract class CPSAnnotationChecker extends CPSUtils with Modes { val global: Global import global._ import definitions._ @@ -177,59 +178,38 @@ abstract class CPSAnnotationChecker extends CPSUtils { override def adaptAnnotations(tree: Tree, mode: Int, pt: Type): Tree = { if (!cpsEnabled) return tree - vprintln("adapt annotations " + tree + " / " + tree.tpe + " / " + Integer.toHexString(mode) + " / " + pt) + vprintln("adapt annotations " + tree + " / " + tree.tpe + " / " + modeString(mode) + " / " + pt) - val annots1 = cpsParamAnnotation(tree.tpe) - val annots2 = cpsParamAnnotation(pt) + val patMode = (mode & global.analyzer.PATTERNmode) != 0 + val exprMode = (mode & global.analyzer.EXPRmode) != 0 + val byValMode = (mode & global.analyzer.BYVALmode) != 0 - if ((mode & global.analyzer.PATTERNmode) != 0) { - if (!annots1.isEmpty) { - return tree modifyType removeAllCPSAnnotations - } - } + val annotsTree = cpsParamAnnotation(tree.tpe) + val annotsExpected = cpsParamAnnotation(pt) -/* + // not sure I rephrased this comment correctly: + // replacing `patMode` in the condition below by `patMode || ((mode & global.analyzer.TYPEmode) != 0 && (mode & global.analyzer.BYVALmode))` // doesn't work correctly -- still relying on addAnnotations to remove things from ValDef symbols - if ((mode & global.analyzer.TYPEmode) != 0 && (mode & global.analyzer.BYVALmode) != 0) { - if (!annots1.isEmpty) { - println("removing annotation from " + tree + "/" + tree.tpe) - val s = tree.setType(removeAllCPSAnnotations(tree.tpe)) - println(s) - s - } - } -*/ - - if ((mode & global.analyzer.EXPRmode) != 0) { - if (annots1.isEmpty && !annots2.isEmpty && ((mode & global.analyzer.BYVALmode) == 0)) { // shiftUnit - // add a marker annotation that will make tree.tpe behave as pt, subtyping wise - // tree will look like having any possible annotation - //println("adapt annotations " + tree + " / " + tree.tpe + " / " + Integer.toHexString(mode) + " / " + pt) - //val same = annots2 forall { case AnnotationInfo(atp: TypeRef, _, _) => atp.typeArgs(0) =:= atp.typeArgs(1) } - // TBD: use same or not? see infer0.scala/infer1.scala - - // CAVEAT: - // for monomorphic answer types we want to have @plus @cps (for better checking) - // for answer type modification we want to have only @plus (because actual answer type may differ from pt) - - //val known = global.analyzer.isFullyDefined(pt) - - if (/*same &&*/ !hasPlusMarker(tree.tpe)) { - //if (known) - return tree modifyType (_ withAnnotations newPlusMarker() :: annots2) // needed for #1807 - //else - // return tree.setType(tree.tpe.withAnnotations(adapt::Nil)) - } - tree - } else if (!annots1.isEmpty && ((mode & global.analyzer.BYVALmode) != 0)) { // dropping annotation - // add a marker annotation that will make tree.tpe behave as pt, subtyping wise - // tree will look like having no annotation - if (!hasMinusMarker(tree.tpe)) { - return tree modifyType addMinusMarker - } - } - } - tree + if (patMode && !annotsTree.isEmpty) tree modifyType removeAllCPSAnnotations + else if (exprMode && !byValMode && !hasPlusMarker(tree.tpe) && annotsTree.isEmpty && annotsExpected.nonEmpty) { // shiftUnit + // add a marker annotation that will make tree.tpe behave as pt, subtyping wise + // tree will look like having any possible annotation + //println("adapt annotations " + tree + " / " + tree.tpe + " / " + Integer.toHexString(mode) + " / " + pt) + + // CAVEAT: + // for monomorphic answer types we want to have @plus @cps (for better checking) + // for answer type modification we want to have only @plus (because actual answer type may differ from pt) + + val res = tree modifyType (_ withAnnotations newPlusMarker() :: annotsExpected) // needed for #1807 + vprintln("adapted annotations (not by val) of " + tree + " to " + res.tpe) + res + } else if (exprMode && byValMode && !hasMinusMarker(tree.tpe) && annotsTree.nonEmpty) { // dropping annotation + // add a marker annotation that will make tree.tpe behave as pt, subtyping wise + // tree will look like having no annotation + val res = tree modifyType addMinusMarker + vprintln("adapted annotations (by val) of " + tree + " to " + res.tpe) + res + } else tree } def updateAttributesFromChildren(tpe: Type, childAnnots: List[AnnotationInfo], byName: List[Tree]): Type = { @@ -454,11 +434,10 @@ abstract class CPSAnnotationChecker extends CPSUtils { transChildrenInOrder(tree, tpe, List(cond), List(thenp, elsep)) case Match(select, cases) => - // TODO: can there be cases that are not CaseDefs?? check collect vs map! - transChildrenInOrder(tree, tpe, List(select), cases:::(cases collect { case CaseDef(_, _, body) => body })) + transChildrenInOrder(tree, tpe, List(select), cases:::(cases map { case CaseDef(_, _, body) => body })) case Try(block, catches, finalizer) => - val tpe1 = transChildrenInOrder(tree, tpe, Nil, block::catches:::(catches collect { case CaseDef(_, _, body) => body })) + val tpe1 = transChildrenInOrder(tree, tpe, Nil, block::catches:::(catches map { case CaseDef(_, _, body) => body })) val annots = cpsParamAnnotation(tpe1) if (annots.nonEmpty) { diff --git a/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala b/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala index e1d699debc..e9e9cf0fab 100644 --- a/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala +++ b/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala @@ -241,6 +241,8 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with // where D$idef = def L$i(..) = {L$i.body; L${i+1}(..)} case ldef @ LabelDef(name, params, rhs) => + // println("trans LABELDEF "+(name, params, tree.tpe, hasAnswerTypeAnn(tree.tpe))) + // TODO why does the labeldef's type have a cpsMinus annotation, whereas the rhs does not? (BYVALmode missing/too much somewhere?) if (hasAnswerTypeAnn(tree.tpe)) { // currentOwner.newMethod(name, tree.pos, Flags.SYNTHETIC) setInfo ldef.symbol.info val sym = ldef.symbol resetFlag Flags.LABEL @@ -456,10 +458,11 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with val (anfStats, anfExpr) = rec(stms, cpsA, List()) // println("\nanf-block:\n"+ ((stms :+ expr) mkString ("{", "\n", "}")) +"\nBECAME\n"+ ((anfStats :+ anfExpr) mkString ("{", "\n", "}"))) - + // println("synth case? "+ (anfStats map (t => (t, t.isDef, gen.hasSynthCaseSymbol(t))))) // SUPER UGLY HACK: handle virtpatmat-style matches, whose labels have already been turned into DefDefs if (anfStats.nonEmpty && (anfStats forall (t => !t.isDef || gen.hasSynthCaseSymbol(t)))) { val (prologue, rest) = (anfStats :+ anfExpr) span (s => !s.isInstanceOf[DefDef]) // find first case + // println("rest: "+ rest) // val (defs, calls) = rest partition (_.isInstanceOf[DefDef]) if (rest nonEmpty){ // the filter drops the ()'s emitted when transValue encountered a LabelDef diff --git a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala index a78de8e6c8..dcb7cd601f 100644 --- a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala +++ b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala @@ -65,6 +65,7 @@ abstract class SelectiveCPSTransform extends PluginComponent with class CPSTransformer(unit: CompilationUnit) extends TypingTransformer(unit) { + private val patmatTransformer = patmat.newTransformer(unit) override def transform(tree: Tree): Tree = { if (!cpsEnabled) return tree @@ -212,7 +213,7 @@ abstract class SelectiveCPSTransform extends PluginComponent with val catch2 = localTyper.typedCases(List(catchIfDefined), ThrowableClass.tpe, targettp) //typedCases(tree, catches, ThrowableClass.tpe, pt) - localTyper.typed(Block(List(funDef), treeCopy.Try(tree, treeCopy.Block(block1, stms, expr2), catch2, finalizer1))) + patmatTransformer.transform(localTyper.typed(Block(List(funDef), treeCopy.Try(tree, treeCopy.Block(block1, stms, expr2), catch2, finalizer1)))) /* |