1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
// $Id$
package scala.tools.selectivecps
import scala.tools.nsc.Global
trait CPSUtils {
val global: Global
import global._
import definitions._
var cpsEnabled = false
val verbose: Boolean = System.getProperty("cpsVerbose", "false") == "true"
@inline 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 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 allCPSAnnotations = List(MarkerCPSSym, MarkerCPSTypes, MarkerCPSSynth,
MarkerCPSAdaptPlus, MarkerCPSAdaptMinus)
// annotation checker
def filterAttribs(tpe:Type, cls:Symbol) =
tpe.annotations.filter(_.atp.typeSymbol == cls)
def removeAttribs(tpe:Type, cls:Symbol*) =
tpe.withoutAnnotations.withAnnotations(tpe.annotations.filterNot(cls contains _.atp.typeSymbol))
def removeAllCPSAnnotations(tpe: Type) = removeAttribs(tpe, allCPSAnnotations:_*)
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))
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
}
}
def hasAnswerTypeAnn(tp: Type) = {
tp.hasAnnotation(MarkerCPSTypes) && !tp.hasAnnotation(MarkerCPSAdaptPlus) /*&&
!tp.hasAnnotation(MarkerCPSAdaptMinus)*/
}
def hasSynthAnn(tp: Type) = {
tp.annotations.exists(a => a.atp.typeSymbol == MarkerCPSSynth)
}
def updateSynthFlag(tree: Tree) = { // remove annotations if *we* added them (@synth present)
if (hasSynthAnn(tree.tpe)) {
log("removing annotation from " + tree)
tree.setType(removeAllCPSAnnotations(tree.tpe))
} else
tree
}
type CPSInfo = Option[(Type,Type)]
def linearize(a: CPSInfo, b: CPSInfo)(implicit unit: CompilationUnit, pos: Position): CPSInfo = {
(a,b) match {
case (Some((u0,v0)), Some((u1,v1))) =>
vprintln("check lin " + a + " andThen " + b)
if (!(v1 <:< u0)) {
unit.error(pos,"cannot change answer type in composition of cps expressions " +
"from " + u1 + " to " + v0 + " because " + v1 + " is not a subtype of " + u0 + ".")
throw new Exception("check lin " + a + " andThen " + b)
}
Some((u1,v0))
case (Some(_), _) => a
case (_, Some(_)) => b
case _ => None
}
}
// cps transform
}
|