@@ -17,86 +17,94 @@ import SymUtils._
17
17
import collection .{ mutable , immutable }
18
18
import collection .mutable .{ LinkedHashMap , LinkedHashSet , TreeSet }
19
19
20
- class CapturedVars extends MiniPhaseTransform with SymTransformer { thisTransform =>
20
+ class CapturedVars extends MiniPhase with IdentityDenotTransformer { thisTransform =>
21
21
import ast .tpd ._
22
22
23
23
/** the following two members override abstract members in Transform */
24
24
val phaseName : String = " capturedVars"
25
+ val treeTransform = new Transform (Set ())
25
26
26
- override def treeTransformPhase = thisTransform.next
27
+ class Transform (captured : collection.Set [Symbol ]) extends TreeTransform {
28
+ def phase = thisTransform
29
+ override def treeTransformPhase = thisTransform.next
27
30
28
- private var captured : mutable. HashSet [ Symbol ] = _
29
-
30
- private class CollectCaptured ( implicit ctx : Context ) extends EnclosingMethodTraverser {
31
- def traverse ( enclMeth : Symbol , tree : Tree ) = tree match {
32
- case id : Ident =>
33
- val sym = id.symbol
34
- if (sym.is( Mutable , butNot = Method ) && sym.owner.isTerm && sym.enclosingMethod != enclMeth) {
35
- ctx.log( i " capturing $sym in ${sym.enclosingMethod} , referenced from $enclMeth " )
36
- captured += sym
37
- }
38
- case _ =>
39
- foldOver(enclMeth, tree)
40
- }
41
- def runOver ( tree : Tree ) = {
42
- captured = mutable. HashSet ()
43
- apply( NoSymbol , tree)
31
+ private class CollectCaptured ( implicit ctx : Context ) extends EnclosingMethodTraverser {
32
+ private val captured = mutable. HashSet [ Symbol ]()
33
+ def traverse ( enclMeth : Symbol , tree : Tree ) = tree match {
34
+ case id : Ident =>
35
+ val sym = id.symbol
36
+ if ( sym.is( Mutable , butNot = Method ) && sym.owner.isTerm && sym.enclosingMethod != enclMeth) {
37
+ ctx.log( i " capturing $ sym in ${ sym.enclosingMethod} , referenced from $ enclMeth" )
38
+ captured += sym
39
+ }
40
+ case _ =>
41
+ foldOver(enclMeth, tree)
42
+ }
43
+ def runOver ( tree : Tree ) : collection. Set [ Symbol ] = {
44
+ apply( NoSymbol , tree)
45
+ captured
46
+ }
44
47
}
45
- }
46
48
47
- override def init (implicit ctx : Context , info : TransformerInfo ): Unit =
48
- (new CollectCaptured )(ctx.withPhase(thisTransform)).runOver(ctx.compilationUnit.tpdTree)
49
+ override def prepareForUnit (tree : Tree )(implicit ctx : Context ) = {
50
+ val captured = (new CollectCaptured )(ctx.withPhase(thisTransform))
51
+ .runOver(ctx.compilationUnit.tpdTree)
52
+ new Transform (captured)
53
+ }
49
54
50
- override def transformSym ( sd : SymDenotation )( implicit ctx : Context ) : SymDenotation =
51
- if (captured(sd.symbol)) {
52
- val newd = sd.copySymDenotation(
53
- info = refCls(sd.info.classSymbol, sd.hasAnnotation(defn. VolatileAnnot )).typeRef)
54
- newd.removeAnnotation( defn.VolatileAnnot )
55
- newd
56
- } else sd
55
+ /** The {Volatile|}{Int|Double|...|Object}Ref class corresponding to the class `cls`,
56
+ * depending on whether the reference should be @volatile
57
+ */
58
+ def refCls (cls : Symbol , isVolatile : Boolean )( implicit ctx : Context ) : Symbol = {
59
+ val refMap = if (isVolatile) defn.volatileRefClass else defn.refClass
60
+ refMap.getOrElse(cls, refMap(defn. ObjectClass ))
61
+ }
57
62
58
- /** The {Volatile|}{Int|Double|...|Object}Ref class corresponding to the class `cls`,
59
- * depending on whether the reference should be @volatile
60
- */
61
- def refCls (cls : Symbol , isVolatile : Boolean )(implicit ctx : Context ): Symbol = {
62
- val refMap = if (isVolatile) defn.volatileRefClass else defn.refClass
63
- refMap.getOrElse(cls, refMap(defn.ObjectClass ))
64
- }
63
+ def capturedType (vble : Symbol )(implicit ctx : Context ): Type = {
64
+ val oldInfo = vble.denot(ctx.withPhase(thisTransform)).info
65
+ refCls(oldInfo.classSymbol, vble.isVolatile).typeRef
66
+ }
65
67
66
- def capturedType (vble : Symbol )(implicit ctx : Context ): Type = {
67
- val oldInfo = vble.denot(ctx.withPhase(thisTransform)).info
68
- refCls(oldInfo.classSymbol, vble.isVolatile).typeRef
69
- }
68
+ override def prepareForValDef (vdef : ValDef )(implicit ctx : Context ) = {
69
+ val sym = vdef.symbol
70
+ if (captured contains sym) {
71
+ val newd = sym.denot(ctx.withPhase(thisTransform)).copySymDenotation(
72
+ info = refCls(sym.info.classSymbol, sym.hasAnnotation(defn.VolatileAnnot )).typeRef)
73
+ newd.removeAnnotation(defn.VolatileAnnot )
74
+ newd.installAfter(thisTransform)
75
+ }
76
+ this
77
+ }
70
78
71
- override def transformValDef (vdef : ValDef )(implicit ctx : Context , info : TransformerInfo ): Tree = {
72
- val vble = vdef.symbol
73
- if (captured contains vble) {
74
- def boxMethod (name : TermName ): Tree =
75
- ref(vble.info.classSymbol.companionModule.info.member(name).symbol)
76
- cpy.ValDef (vdef)(
77
- rhs = vdef.rhs match {
78
- case EmptyTree => boxMethod(nme.zero).appliedToNone.withPos(vdef.pos)
79
- case arg => boxMethod(nme.create).appliedTo(arg)
80
- },
81
- tpt = TypeTree (vble.info).withPos(vdef.tpt.pos))
79
+ override def transformValDef (vdef : ValDef )(implicit ctx : Context , info : TransformerInfo ): Tree = {
80
+ val vble = vdef.symbol
81
+ if (captured contains vble) {
82
+ def boxMethod (name : TermName ): Tree =
83
+ ref(vble.info.classSymbol.companionModule.info.member(name).symbol)
84
+ cpy.ValDef (vdef)(
85
+ rhs = vdef.rhs match {
86
+ case EmptyTree => boxMethod(nme.zero).appliedToNone.withPos(vdef.pos)
87
+ case arg => boxMethod(nme.create).appliedTo(arg)
88
+ },
89
+ tpt = TypeTree (vble.info).withPos(vdef.tpt.pos))
90
+ } else vdef
82
91
}
83
- else vdef
84
- }
85
92
86
- override def transformIdent (id : Ident )(implicit ctx : Context , info : TransformerInfo ): Tree = {
87
- val vble = id.symbol
88
- if (captured(vble))
89
- (id select nme.elem).ensureConforms(vble.denot(ctx.withPhase(thisTransform)).info)
90
- else id
91
- }
93
+ override def transformIdent (id : Ident )(implicit ctx : Context , info : TransformerInfo ): Tree = {
94
+ val vble = id.symbol
95
+ if (captured(vble))
96
+ (id select nme.elem).ensureConforms(vble.denot(ctx.withPhase(thisTransform)).info)
97
+ else id
98
+ }
92
99
93
- override def transformAssign (tree : Assign )(implicit ctx : Context , info : TransformerInfo ): Tree = {
94
- val lhs1 = tree.lhs match {
95
- case TypeApply (Select (qual @ Select (qual2, nme.elem), nme.asInstanceOf_), _) =>
96
- assert(captured(qual2.symbol))
97
- qual
98
- case _ => tree.lhs
100
+ override def transformAssign (tree : Assign )(implicit ctx : Context , info : TransformerInfo ): Tree = {
101
+ val lhs1 = tree.lhs match {
102
+ case TypeApply (Select (qual @ Select (qual2, nme.elem), nme.asInstanceOf_), _) =>
103
+ assert(captured(qual2.symbol))
104
+ qual
105
+ case _ => tree.lhs
106
+ }
107
+ cpy.Assign (tree)(lhs1, tree.rhs)
99
108
}
100
- cpy.Assign (tree)(lhs1, tree.rhs)
101
109
}
102
110
}
0 commit comments