summaryrefslogtreecommitdiff
path: root/src/continuations/plugin
diff options
context:
space:
mode:
Diffstat (limited to 'src/continuations/plugin')
-rw-r--r--src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala153
-rw-r--r--src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala117
-rw-r--r--src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala6
3 files changed, 129 insertions, 147 deletions
diff --git a/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala b/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala
index 0ccba2cb80..ab1510bd7f 100644
--- a/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala
+++ b/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala
@@ -16,6 +16,13 @@ abstract class CPSAnnotationChecker extends CPSUtils {
* Checks whether @cps annotations conform
*/
object checker extends AnnotationChecker {
+ private def addPlusMarker(tp: Type) = tp withAnnotation newPlusMarker()
+ private def addMinusMarker(tp: Type) = tp withAnnotation newMinusMarker()
+
+ private def cleanPlus(tp: Type) =
+ removeAttribs(tp, MarkerCPSAdaptPlus, MarkerCPSTypes)
+ private def cleanPlusWith(tp: Type)(newAnnots: AnnotationInfo*) =
+ cleanPlus(tp) withAnnotations newAnnots.toList
/** Check annotations to decide whether tpe1 <:< tpe2 */
def annotationsConform(tpe1: Type, tpe2: Type): Boolean = {
@@ -27,78 +34,74 @@ abstract class CPSAnnotationChecker extends CPSUtils {
if (tpe1.typeSymbol eq NothingClass)
return true
- val annots1 = filterAttribs(tpe1,MarkerCPSTypes)
- val annots2 = filterAttribs(tpe2,MarkerCPSTypes)
+ val annots1 = cpsParamAnnotation(tpe1)
+ val annots2 = cpsParamAnnotation(tpe2)
// @plus and @minus should only occur at the left, and never together
// TODO: insert check
- val adaptPlusAnnots1 = filterAttribs(tpe1,MarkerCPSAdaptPlus)
- val adaptMinusAnnots1 = filterAttribs(tpe1,MarkerCPSAdaptMinus)
// @minus @cps is the same as no annotations
- if (!adaptMinusAnnots1.isEmpty)
+ if (hasMinusMarker(tpe1))
return annots2.isEmpty
// to handle answer type modification, we must make @plus <:< @cps
- if (!adaptPlusAnnots1.isEmpty && annots1.isEmpty)
+ if (hasPlusMarker(tpe1) && annots1.isEmpty)
return true
// @plus @cps will fall through and compare the @cps type args
-
// @cps parameters must match exactly
- if ((annots1 corresponds annots2) { _.atp <:< _.atp })
- return true
-
- false
+ (annots1 corresponds annots2)(_.atp <:< _.atp)
}
-
/** Refine the computed least upper bound of a list of types.
* All this should do is add annotations. */
override def annotationsLub(tpe: Type, ts: List[Type]): Type = {
if (!cpsEnabled) return tpe
- val annots1 = filterAttribs(tpe, MarkerCPSTypes)
- val annots2 = ts flatMap (filterAttribs(_, MarkerCPSTypes))
+ val annots1 = cpsParamAnnotation(tpe)
+ val annots2 = ts flatMap cpsParamAnnotation
if (annots2.nonEmpty) {
- val cpsLub = AnnotationInfo(global.lub(annots1:::annots2 map (_.atp)), Nil, Nil)
+ val cpsLub = newMarker(global.lub(annots1:::annots2 map (_.atp)))
val tpe1 = if (annots1.nonEmpty) removeAttribs(tpe, MarkerCPSTypes) else tpe
tpe1.withAnnotation(cpsLub)
- } else tpe
+ }
+ else tpe
}
/** Refine the bounds on type parameters to the given type arguments. */
override def adaptBoundsToAnnotations(bounds: List[TypeBounds], tparams: List[Symbol], targs: List[Type]): List[TypeBounds] = {
if (!cpsEnabled) return bounds
- val anyAtCPS = AnnotationInfo(appliedType(MarkerCPSTypes.tpe, List(NothingClass.tpe, AnyClass.tpe)), Nil, Nil)
+ val anyAtCPS = newCpsParamsMarker(NothingClass.tpe, AnyClass.tpe)
+
if (isFunctionType(tparams.head.owner.tpe) || tparams.head.owner == PartialFunctionClass) {
vprintln("function bound: " + tparams.head.owner.tpe + "/"+bounds+"/"+targs)
- if (targs.last.hasAnnotation(MarkerCPSTypes))
+ if (hasCpsParamTypes(targs.last))
bounds.reverse match {
- case res::b if !res.hi.hasAnnotation(MarkerCPSTypes) =>
+ case res::b if !hasCpsParamTypes(res.hi) =>
(TypeBounds(res.lo, res.hi.withAnnotation(anyAtCPS))::b).reverse
case _ => bounds
}
else
bounds
- } else if (tparams.head.owner == ByNameParamClass) {
+ }
+ else if (tparams.head.owner == ByNameParamClass) {
vprintln("byname bound: " + tparams.head.owner.tpe + "/"+bounds+"/"+targs)
- if (targs.head.hasAnnotation(MarkerCPSTypes) && !bounds.head.hi.hasAnnotation(MarkerCPSTypes))
- TypeBounds(bounds.head.lo, bounds.head.hi.withAnnotation(anyAtCPS))::Nil
+ val TypeBounds(lo, hi) = bounds.head
+ if (hasCpsParamTypes(targs.head) && !hasCpsParamTypes(hi))
+ TypeBounds(lo, hi withAnnotation anyAtCPS) :: Nil
else bounds
} else
bounds
}
-
override def canAdaptAnnotations(tree: Tree, mode: Int, pt: Type): Boolean = {
if (!cpsEnabled) return false
vprintln("can adapt annotations? " + tree + " / " + tree.tpe + " / " + Integer.toHexString(mode) + " / " + pt)
- val annots1 = filterAttribs(tree.tpe,MarkerCPSTypes)
- val annots2 = filterAttribs(pt,MarkerCPSTypes)
+ val annots1 = cpsParamAnnotation(tree.tpe)
+ val annots2 = cpsParamAnnotation(pt)
if ((mode & global.analyzer.PATTERNmode) != 0) {
//println("can adapt pattern annotations? " + tree + " / " + tree.tpe + " / " + Integer.toHexString(mode) + " / " + pt)
@@ -124,15 +127,14 @@ abstract class CPSAnnotationChecker extends CPSUtils {
}
*/
if ((mode & global.analyzer.EXPRmode) != 0) {
- if ((annots1 corresponds annots2) { case (a1,a2) => a1.atp <:< a2.atp }) {
+ if ((annots1 corresponds annots2)(_.atp <:< _.atp)) {
vprintln("already same, can't adapt further")
return false
}
if (annots1.isEmpty && !annots2.isEmpty && ((mode & global.analyzer.BYVALmode) == 0)) {
//println("can adapt annotations? " + tree + " / " + tree.tpe + " / " + Integer.toHexString(mode) + " / " + pt)
- val adapt = AnnotationInfo(MarkerCPSAdaptPlus.tpe, Nil, Nil)
- if (!tree.tpe.annotations.contains(adapt)) {
+ if (!hasPlusMarker(tree.tpe)) {
// val base = tree.tpe <:< removeAllCPSAnnotations(pt)
// val known = global.analyzer.isFullyDefined(pt)
// println(same + "/" + base + "/" + known)
@@ -144,7 +146,7 @@ abstract class CPSAnnotationChecker extends CPSUtils {
//}
}
} else if (!annots1.isEmpty && ((mode & global.analyzer.BYVALmode) != 0)) {
- if (!tree.tpe.hasAnnotation(MarkerCPSAdaptMinus)) {
+ if (!hasMinusMarker(tree.tpe)) {
vprintln("yes we can!! (byval)")
return true
}
@@ -153,18 +155,17 @@ abstract class CPSAnnotationChecker extends CPSUtils {
false
}
-
override def adaptAnnotations(tree: Tree, mode: Int, pt: Type): Tree = {
if (!cpsEnabled) return tree
vprintln("adapt annotations " + tree + " / " + tree.tpe + " / " + Integer.toHexString(mode) + " / " + pt)
- val annots1 = filterAttribs(tree.tpe,MarkerCPSTypes)
- val annots2 = filterAttribs(pt,MarkerCPSTypes)
+ val annots1 = cpsParamAnnotation(tree.tpe)
+ val annots2 = cpsParamAnnotation(pt)
if ((mode & global.analyzer.PATTERNmode) != 0) {
if (!annots1.isEmpty) {
- return tree.setType(removeAllCPSAnnotations(tree.tpe))
+ return tree modifyType removeAllCPSAnnotations
}
}
@@ -185,8 +186,6 @@ abstract class CPSAnnotationChecker extends CPSUtils {
// 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 adapt = AnnotationInfo(MarkerCPSAdaptPlus.tpe, Nil, Nil)
//val same = annots2 forall { case AnnotationInfo(atp: TypeRef, _, _) => atp.typeArgs(0) =:= atp.typeArgs(1) }
// TBD: use same or not? see infer0.scala/infer1.scala
@@ -196,9 +195,9 @@ abstract class CPSAnnotationChecker extends CPSUtils {
//val known = global.analyzer.isFullyDefined(pt)
- if (/*same &&*/ !tree.tpe.annotations.contains(adapt)) {
+ if (/*same &&*/ !hasPlusMarker(tree.tpe)) {
//if (known)
- return tree.setType(tree.tpe.withAnnotations(adapt::annots2)) // needed for #1807
+ return tree modifyType (_ withAnnotations newPlusMarker() :: annots2) // needed for #1807
//else
// return tree.setType(tree.tpe.withAnnotations(adapt::Nil))
}
@@ -206,16 +205,14 @@ abstract class CPSAnnotationChecker extends CPSUtils {
} 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 (!tree.tpe.hasAnnotation(MarkerCPSAdaptMinus)) {
- val adapt = AnnotationInfo(MarkerCPSAdaptMinus.tpe, Nil, Nil)
- return tree.setType(tree.tpe.withAnnotations(adapt::Nil))
+ if (!hasMinusMarker(tree.tpe)) {
+ return tree modifyType addMinusMarker
}
}
}
tree
}
-
def updateAttributesFromChildren(tpe: Type, childAnnots: List[AnnotationInfo], byName: List[Tree]): Type = {
tpe match {
// Would need to push annots into each alternative of overloaded type
@@ -226,7 +223,7 @@ abstract class CPSAnnotationChecker extends CPSUtils {
OverloadedType(pre, alts.map((sym: Symbol) => updateAttributes(pre.memberType(sym), annots)))
*/
case _ =>
- assert(childAnnots forall (_.atp.typeSymbol == MarkerCPSTypes), childAnnots)
+ assert(childAnnots forall (_ matches MarkerCPSTypes), childAnnots)
/*
[] + [] = []
plus + [] = plus
@@ -243,56 +240,50 @@ abstract class CPSAnnotationChecker extends CPSUtils {
synth cps + cps = synth cps! <- unify
*/
- val plus = tpe.hasAnnotation(MarkerCPSAdaptPlus) || (tpe.hasAnnotation(MarkerCPSTypes) &&
- byName.nonEmpty && byName.forall(_.tpe.hasAnnotation(MarkerCPSAdaptPlus)))
+ val plus = hasPlusMarker(tpe) || (
+ hasCpsParamTypes(tpe)
+ && byName.nonEmpty
+ && (byName forall (t => hasPlusMarker(t.tpe)))
+ )
// move @plus annotations outward from by-name children
- if (childAnnots.isEmpty) {
+ if (childAnnots.isEmpty) return {
if (plus) { // @plus or @plus @cps
- for (t <- byName) {
- //println("removeAnnotation " + t + " / " + t.tpe)
- t.setType(removeAttribs(t.tpe, MarkerCPSAdaptPlus, MarkerCPSTypes))
- }
- return tpe.withAnnotation(AnnotationInfo(MarkerCPSAdaptPlus.tpe, Nil, Nil))
- } else
- return tpe
+ byName foreach (_ modifyType cleanPlus)
+ addPlusMarker(tpe)
+ }
+ else tpe
}
- val annots1 = filterAttribs(tpe, MarkerCPSTypes)
+ val annots1 = cpsParamAnnotation(tpe)
if (annots1.isEmpty) { // nothing or @plus
- val synth = MarkerCPSSynth.tpe
- val annots2 = List(linearize(childAnnots))
- removeAttribs(tpe,MarkerCPSAdaptPlus).withAnnotations(AnnotationInfo(synth, Nil, Nil)::annots2)
- } else {
+ cleanPlusWith(tpe)(newSynthMarker(), linearize(childAnnots))
+ }
+ else {
val annot1 = single(annots1)
if (plus) { // @plus @cps
- val synth = AnnotationInfo(MarkerCPSSynth.tpe, Nil, Nil)
val annot2 = linearize(childAnnots)
- if (!(annot2.atp <:< annot1.atp))
- throw new TypeError(annot2 + " is not a subtype of " + annot1)
- val res = removeAttribs(tpe, MarkerCPSAdaptPlus, MarkerCPSTypes).withAnnotations(List(synth, annot2))
- for (t <- byName) {
- //println("removeAnnotation " + t + " / " + t.tpe)
- t.setType(removeAttribs(t.tpe, MarkerCPSAdaptPlus, MarkerCPSTypes))
+
+ if (annot2.atp <:< annot1.atp) {
+ try cleanPlusWith(tpe)(newSynthMarker(), annot2)
+ finally byName foreach (_ modifyType cleanPlus)
}
- res
- } else if (tpe.hasAnnotation(MarkerCPSSynth)) { // @synth @cps
+ else throw new TypeError(annot2 + " is not a subtype of " + annot1)
+ }
+ else if (hasSynthMarker(tpe)) { // @synth @cps
val annot2 = linearize(childAnnots)
- if (!(annot2.atp <:< annot1.atp))
+ if (annot2.atp <:< annot1.atp)
+ cleanPlusWith(tpe)(annot2)
+ else
throw new TypeError(annot2 + " is not a subtype of " + annot1)
- removeAttribs(tpe, MarkerCPSTypes).withAnnotation(annot2)
- } else { // @cps
- removeAttribs(tpe, MarkerCPSTypes).withAnnotation(linearize(childAnnots:::annots1))
}
+ else // @cps
+ cleanPlusWith(tpe)(linearize(childAnnots:::annots1))
}
}
}
-
-
-
-
def transArgList(fun: Tree, args: List[Tree]): List[List[Tree]] = {
val formals = fun.tpe.paramTypes
val overshoot = args.length - formals.length
@@ -329,7 +320,7 @@ abstract class CPSAnnotationChecker extends CPSUtils {
def transChildrenInOrder(tree: Tree, tpe: Type, childTrees: List[Tree], byName: List[Tree]) = {
val children = childTrees.flatMap { t =>
if (t.tpe eq null) Nil else {
- val types = filterAttribs(t.tpe, MarkerCPSTypes)
+ val types = cpsParamAnnotation(t.tpe)
// TODO: check that it has been adapted and if so correctly
if (types.isEmpty) Nil else List(single(types))
}
@@ -348,7 +339,7 @@ abstract class CPSAnnotationChecker extends CPSUtils {
override def addAnnotations(tree: Tree, tpe: Type): Type = {
if (!cpsEnabled) {
- if (tpe.annotations.nonEmpty && tpe.hasAnnotation(MarkerCPSTypes))
+ if (hasCpsParamTypes(tpe))
global.reporter.error(tree.pos, "this code must be compiled with the Scala continuations plugin enabled")
return tpe
}
@@ -397,7 +388,7 @@ abstract class CPSAnnotationChecker extends CPSUtils {
// we cannot safely annotate these. so we just ignore these cases and
// clean up later in the Apply/TypeApply trees.
- if (qual.tpe.hasAnnotation(MarkerCPSTypes)) {
+ if (hasCpsParamTypes(qual.tpe)) {
// however there is one special case:
// 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 (wouldn't trigger our
@@ -425,10 +416,10 @@ abstract class CPSAnnotationChecker extends CPSUtils {
case Try(block, catches, finalizer) =>
val tpe1 = transChildrenInOrder(tree, tpe, Nil, block::catches:::(catches collect { case CaseDef(_, _, body) => body }))
- val annots = filterAttribs(tpe1, MarkerCPSTypes)
+ val annots = cpsParamAnnotation(tpe1)
if (annots.nonEmpty) {
val ann = single(annots)
- val atp0::atp1::Nil = ann.atp.normalize.typeArgs
+ val (atp0, atp1) = annTypes(ann)
if (!(atp0 =:= atp1))
throw new TypeError("only simple cps types allowed in try/catch blocks (found: " + tpe1 + ")")
if (!finalizer.isEmpty) // no finalizers allowed. see explanation in SelectiveCPSTransform
@@ -445,8 +436,8 @@ abstract class CPSAnnotationChecker extends CPSUtils {
// ValDef symbols must *not* have annotations!
if (hasAnswerTypeAnn(tree.symbol.info)) { // is it okay to modify sym here?
vprintln("removing annotation from sym " + tree.symbol + "/" + tree.symbol.tpe + "/" + tpt)
- tpt.setType(removeAllCPSAnnotations(tpt.tpe))
- tree.symbol.setInfo(removeAllCPSAnnotations(tree.symbol.info))
+ tpt modifyType removeAllCPSAnnotations
+ tree.symbol modifyInfo removeAllCPSAnnotations
}
tpe
diff --git a/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala b/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala
index d1a35df04b..5cb06d42db 100644
--- a/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala
+++ b/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala
@@ -13,96 +13,90 @@ trait CPSUtils {
val verbose: Boolean = System.getProperty("cpsVerbose", "false") == "true"
def vprintln(x: =>Any): Unit = if (verbose) println(x)
- lazy val MarkerCPSSym = definitions.getClass("scala.util.continuations.cpsSym")
- lazy val MarkerCPSTypes = definitions.getClass("scala.util.continuations.cpsParam")
- lazy val MarkerCPSSynth = definitions.getClass("scala.util.continuations.cpsSynth")
-
- lazy val MarkerCPSAdaptPlus = definitions.getClass("scala.util.continuations.cpsPlus")
+ lazy val MarkerCPSSym = definitions.getClass("scala.util.continuations.cpsSym")
+ lazy val MarkerCPSTypes = definitions.getClass("scala.util.continuations.cpsParam")
+ lazy val MarkerCPSSynth = definitions.getClass("scala.util.continuations.cpsSynth")
+ lazy val MarkerCPSAdaptPlus = definitions.getClass("scala.util.continuations.cpsPlus")
lazy val MarkerCPSAdaptMinus = definitions.getClass("scala.util.continuations.cpsMinus")
-
lazy val Context = definitions.getClass("scala.util.continuations.ControlContext")
-
lazy val ModCPS = definitions.getModule("scala.util.continuations")
- lazy val MethShiftUnit = definitions.getMember(ModCPS, "shiftUnit")
- lazy val MethShiftUnitR = definitions.getMember(ModCPS, "shiftUnitR")
- lazy val MethShift = definitions.getMember(ModCPS, "shift")
- lazy val MethShiftR = definitions.getMember(ModCPS, "shiftR")
- lazy val MethReify = definitions.getMember(ModCPS, "reify")
- lazy val MethReifyR = definitions.getMember(ModCPS, "reifyR")
+ lazy val MethShiftUnit = definitions.getMember(ModCPS, "shiftUnit")
+ lazy val MethShiftUnitR = definitions.getMember(ModCPS, "shiftUnitR")
+ lazy val MethShift = definitions.getMember(ModCPS, "shift")
+ lazy val MethShiftR = definitions.getMember(ModCPS, "shiftR")
+ lazy val MethReify = definitions.getMember(ModCPS, "reify")
+ lazy val MethReifyR = definitions.getMember(ModCPS, "reifyR")
lazy val allCPSAnnotations = List(MarkerCPSSym, MarkerCPSTypes, MarkerCPSSynth,
MarkerCPSAdaptPlus, MarkerCPSAdaptMinus)
+ // TODO - needed? Can these all use the same annotation info?
+ protected def newSynthMarker() = newMarker(MarkerCPSSynth)
+ protected def newPlusMarker() = newMarker(MarkerCPSAdaptPlus)
+ protected def newMinusMarker() = newMarker(MarkerCPSAdaptMinus)
+ protected def newMarker(tpe: Type): AnnotationInfo = AnnotationInfo marker tpe
+ protected def newMarker(sym: Symbol): AnnotationInfo = AnnotationInfo marker sym.tpe
+
+ protected def newCpsParamsMarker(tp1: Type, tp2: Type) =
+ newMarker(appliedType(MarkerCPSTypes.tpe, List(tp1, tp2)))
+
// annotation checker
+ protected def annTypes(ann: AnnotationInfo): (Type, Type) = {
+ val tp0 :: tp1 :: Nil = ann.atp.normalize.typeArgs
+ ((tp0, tp1))
+ }
+ protected def hasMinusMarker(tpe: Type) = tpe hasAnnotation MarkerCPSAdaptMinus
+ protected def hasPlusMarker(tpe: Type) = tpe hasAnnotation MarkerCPSAdaptPlus
+ protected def hasSynthMarker(tpe: Type) = tpe hasAnnotation MarkerCPSSynth
+ protected def hasCpsParamTypes(tpe: Type) = tpe hasAnnotation MarkerCPSTypes
+ protected def cpsParamTypes(tpe: Type) = tpe getAnnotation MarkerCPSTypes map annTypes
+
def filterAttribs(tpe:Type, cls:Symbol) =
- tpe.annotations.filter(_.atp.typeSymbol == cls)
+ tpe.annotations filter (_ matches cls)
- def removeAttribs(tpe:Type, cls:Symbol*) =
- tpe.withoutAnnotations.withAnnotations(tpe.annotations.filterNot(cls contains _.atp.typeSymbol))
+ def removeAttribs(tpe: Type, classes: Symbol*) =
+ tpe filterAnnotations (ann => !(classes exists (ann matches _)))
def removeAllCPSAnnotations(tpe: Type) = removeAttribs(tpe, allCPSAnnotations:_*)
+ def cpsParamAnnotation(tpe: Type) = filterAttribs(tpe, MarkerCPSTypes)
+
def linearize(ann: List[AnnotationInfo]): AnnotationInfo = {
- ann.reduceLeft { (a, b) =>
- val atp0::atp1::Nil = a.atp.normalize.typeArgs
- val btp0::btp1::Nil = b.atp.normalize.typeArgs
- val (u0,v0) = (atp0, atp1)
- val (u1,v1) = (btp0, btp1)
-/*
- val (u0,v0) = (a.atp.typeArgs(0), a.atp.typeArgs(1))
- val (u1,v1) = (b.atp.typeArgs(0), b.atp.typeArgs(1))
- vprintln("check lin " + a + " andThen " + b)
-*/
- vprintln("check lin " + a + " andThen " + b)
- if (!(v1 <:< u0))
+ ann reduceLeft { (a, b) =>
+ val (u0,v0) = annTypes(a)
+ val (u1,v1) = annTypes(b)
+ // vprintln("check lin " + a + " andThen " + b)
+
+ if (v1 <:< u0)
+ newCpsParamsMarker(u1, v0)
+ else
throw new TypeError("illegal answer type modification: " + a + " andThen " + b)
- // TODO: improve error message (but it is not very common)
- AnnotationInfo(appliedType(MarkerCPSTypes.tpe, List(u1,v0)),Nil,Nil)
}
}
// anf transform
def getExternalAnswerTypeAnn(tp: Type) = {
- tp.annotations.find(a => a.atp.typeSymbol == MarkerCPSTypes) match {
- case Some(AnnotationInfo(atp, _, _)) =>
- val atp0::atp1::Nil = atp.normalize.typeArgs
- Some((atp0, atp1))
- case None =>
- if (tp.hasAnnotation(MarkerCPSAdaptPlus))
- global.warning("trying to instantiate type " + tp + " to unknown cps type")
- None
- }
- }
-
- def getAnswerTypeAnn(tp: Type) = {
- tp.annotations.find(a => a.atp.typeSymbol == MarkerCPSTypes) match {
- case Some(AnnotationInfo(atp, _, _)) =>
- if (!tp.hasAnnotation(MarkerCPSAdaptPlus)) {//&& !tp.hasAnnotation(MarkerCPSAdaptMinus))
- val atp0::atp1::Nil = atp.normalize.typeArgs
- Some((atp0, atp1))
- } else
- None
- case None => None
+ cpsParamTypes(tp) orElse {
+ if (hasPlusMarker(tp))
+ global.warning("trying to instantiate type " + tp + " to unknown cps type")
+ None
}
}
- def hasAnswerTypeAnn(tp: Type) = {
- tp.hasAnnotation(MarkerCPSTypes) && !tp.hasAnnotation(MarkerCPSAdaptPlus) /*&&
- !tp.hasAnnotation(MarkerCPSAdaptMinus)*/
- }
+ def getAnswerTypeAnn(tp: Type): Option[(Type, Type)] =
+ cpsParamTypes(tp) filterNot (_ => hasPlusMarker(tp))
- def hasSynthAnn(tp: Type) = {
- tp.annotations.exists(a => a.atp.typeSymbol == MarkerCPSSynth)
- }
+ def hasAnswerTypeAnn(tp: Type) =
+ hasCpsParamTypes(tp) && !hasPlusMarker(tp)
def updateSynthFlag(tree: Tree) = { // remove annotations if *we* added them (@synth present)
- if (hasSynthAnn(tree.tpe)) {
+ if (hasSynthMarker(tree.tpe)) {
log("removing annotation from " + tree)
- tree.setType(removeAllCPSAnnotations(tree.tpe))
+ tree modifyType removeAllCPSAnnotations
} else
tree
}
@@ -124,7 +118,4 @@ trait CPSUtils {
case _ => None
}
}
-
- // cps transform
-
-} \ No newline at end of file
+}
diff --git a/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala b/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala
index 8889b75770..9f1d3dfcd6 100644
--- a/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala
+++ b/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala
@@ -301,7 +301,7 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with
log("cps type conversion (has: " + cpsA + "/" + spc + "/" + expr.tpe + ")")
log("cps type conversion (expected: " + cpsR.get + "): " + expr)
- if (!expr.tpe.hasAnnotation(MarkerCPSAdaptPlus))
+ if (!hasPlusMarker(expr.tpe))
unit.warning(tree.pos, "expression " + tree + " is cps-transformed unexpectedly")
try {
@@ -331,9 +331,9 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with
} else {
// all is well
- if (expr.tpe.hasAnnotation(MarkerCPSAdaptPlus)) {
+ if (hasPlusMarker(expr.tpe)) {
unit.warning(tree.pos, "expression " + expr + " of type " + expr.tpe + " is not expected to have a cps type")
- expr.setType(removeAllCPSAnnotations(expr.tpe))
+ expr modifyType removeAllCPSAnnotations
}
// TODO: sanity check that types agree