summaryrefslogtreecommitdiff
path: root/src/continuations
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-11-23 23:09:30 +0000
committerPaul Phillips <paulp@improving.org>2011-11-23 23:09:30 +0000
commit4cfca8a7f6763fbbaab37a3473d74118b3ec52bc (patch)
tree0fcd94312cbb08a4c58add11a8cc51bd0c0c9b6a /src/continuations
parent8e965f00e472398b466bc08da1a2d25f4566a670 (diff)
downloadscala-4cfca8a7f6763fbbaab37a3473d74118b3ec52bc.tar.gz
scala-4cfca8a7f6763fbbaab37a3473d74118b3ec52bc.tar.bz2
scala-4cfca8a7f6763fbbaab37a3473d74118b3ec52bc.zip
AnnotationInfo inertia takes me into continuati...
AnnotationInfo inertia takes me into continuations. And kept carrying me until I was carried away. The changes are mostly of the janitorial variety, just doing my part to make the interesting logic visible without being buried in low level compiler plumbing. Added at least one seriously convenient convenience method: tree modifyType fn // equivalent to if (tree.tpe == null) tree else tree setType fn(tree.tpe) This is the analogue to the recently added: symbol modifyInfo fn // same idea It's like having our carpets steam cleaned when we can keep pushing until machinery stays in the machine and the relevant logic stands gloriously on top. You'll eventually exclaim, "I didn't even know these carpets were that color!"
Diffstat (limited to 'src/continuations')
-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