aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/transform/CapturedVars.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-11-12 18:10:47 +0100
committerMartin Odersky <odersky@gmail.com>2014-11-12 18:10:47 +0100
commit8aae56b4f08806eda9745b0a980da151c0a7dc8c (patch)
tree7cd1db74b1795cf67d7a744bb4baa21e92e87247 /src/dotty/tools/dotc/transform/CapturedVars.scala
parentc3b11ceddd46df7ecb2fb5640fd30efcd82b74c2 (diff)
downloaddotty-8aae56b4f08806eda9745b0a980da151c0a7dc8c.tar.gz
dotty-8aae56b4f08806eda9745b0a980da151c0a7dc8c.tar.bz2
dotty-8aae56b4f08806eda9745b0a980da151c0a7dc8c.zip
Make CapturedVars a functional transform.
No global side effect on capturedVars anymore.
Diffstat (limited to 'src/dotty/tools/dotc/transform/CapturedVars.scala')
-rw-r--r--src/dotty/tools/dotc/transform/CapturedVars.scala141
1 files changed, 72 insertions, 69 deletions
diff --git a/src/dotty/tools/dotc/transform/CapturedVars.scala b/src/dotty/tools/dotc/transform/CapturedVars.scala
index b2118d3ec..14bb4a738 100644
--- a/src/dotty/tools/dotc/transform/CapturedVars.scala
+++ b/src/dotty/tools/dotc/transform/CapturedVars.scala
@@ -17,91 +17,94 @@ import SymUtils._
import collection.{ mutable, immutable }
import collection.mutable.{ LinkedHashMap, LinkedHashSet, TreeSet }
-class CapturedVars extends MiniPhaseTransform with IdentityDenotTransformer { thisTransform =>
+class CapturedVars extends MiniPhase with IdentityDenotTransformer { thisTransform =>
import ast.tpd._
/** the following two members override abstract members in Transform */
val phaseName: String = "capturedVars"
+ val treeTransform = new Transform(Set())
- override def treeTransformPhase = thisTransform.next
+ class Transform(captured: collection.Set[Symbol]) extends TreeTransform {
+ def phase = thisTransform
+ override def treeTransformPhase = thisTransform.next
- private var captured: mutable.HashSet[Symbol] = _
-
- private class CollectCaptured(implicit ctx: Context) extends EnclosingMethodTraverser {
- def traverse(enclMeth: Symbol, tree: Tree) = tree match {
- case id: Ident =>
- val sym = id.symbol
- if (sym.is(Mutable, butNot = Method) && sym.owner.isTerm && sym.enclosingMethod != enclMeth) {
- ctx.log(i"capturing $sym in ${sym.enclosingMethod}, referenced from $enclMeth")
- captured += sym
- }
- case _ =>
- foldOver(enclMeth, tree)
- }
- def runOver(tree: Tree) = {
- captured = mutable.HashSet()
- apply(NoSymbol, tree)
+ private class CollectCaptured(implicit ctx: Context) extends EnclosingMethodTraverser {
+ private val captured = mutable.HashSet[Symbol]()
+ def traverse(enclMeth: Symbol, tree: Tree) = tree match {
+ case id: Ident =>
+ val sym = id.symbol
+ if (sym.is(Mutable, butNot = Method) && sym.owner.isTerm && sym.enclosingMethod != enclMeth) {
+ ctx.log(i"capturing $sym in ${sym.enclosingMethod}, referenced from $enclMeth")
+ captured += sym
+ }
+ case _ =>
+ foldOver(enclMeth, tree)
+ }
+ def runOver(tree: Tree): collection.Set[Symbol] = {
+ apply(NoSymbol, tree)
+ captured
+ }
}
- }
- override def prepareForUnit(tree: Tree)(implicit ctx: Context) = {
- (new CollectCaptured)(ctx.withPhase(thisTransform)).runOver(ctx.compilationUnit.tpdTree)
- this
- }
+ override def prepareForUnit(tree: Tree)(implicit ctx: Context) = {
+ val captured = (new CollectCaptured)(ctx.withPhase(thisTransform))
+ .runOver(ctx.compilationUnit.tpdTree)
+ new Transform(captured)
+ }
- /** The {Volatile|}{Int|Double|...|Object}Ref class corresponding to the class `cls`,
- * depending on whether the reference should be @volatile
- */
- def refCls(cls: Symbol, isVolatile: Boolean)(implicit ctx: Context): Symbol = {
- val refMap = if (isVolatile) defn.volatileRefClass else defn.refClass
- refMap.getOrElse(cls, refMap(defn.ObjectClass))
- }
+ /** The {Volatile|}{Int|Double|...|Object}Ref class corresponding to the class `cls`,
+ * depending on whether the reference should be @volatile
+ */
+ def refCls(cls: Symbol, isVolatile: Boolean)(implicit ctx: Context): Symbol = {
+ val refMap = if (isVolatile) defn.volatileRefClass else defn.refClass
+ refMap.getOrElse(cls, refMap(defn.ObjectClass))
+ }
- def capturedType(vble: Symbol)(implicit ctx: Context): Type = {
- val oldInfo = vble.denot(ctx.withPhase(thisTransform)).info
- refCls(oldInfo.classSymbol, vble.isVolatile).typeRef
- }
+ def capturedType(vble: Symbol)(implicit ctx: Context): Type = {
+ val oldInfo = vble.denot(ctx.withPhase(thisTransform)).info
+ refCls(oldInfo.classSymbol, vble.isVolatile).typeRef
+ }
- override def prepareForValDef(vdef: ValDef)(implicit ctx: Context) = {
- val sym = vdef.symbol
- if (captured contains sym) {
- val newd = sym.denot(ctx.withPhase(thisTransform)).copySymDenotation(
- info = refCls(sym.info.classSymbol, sym.hasAnnotation(defn.VolatileAnnot)).typeRef)
- newd.removeAnnotation(defn.VolatileAnnot)
- newd.installAfter(thisTransform)
+ override def prepareForValDef(vdef: ValDef)(implicit ctx: Context) = {
+ val sym = vdef.symbol
+ if (captured contains sym) {
+ val newd = sym.denot(ctx.withPhase(thisTransform)).copySymDenotation(
+ info = refCls(sym.info.classSymbol, sym.hasAnnotation(defn.VolatileAnnot)).typeRef)
+ newd.removeAnnotation(defn.VolatileAnnot)
+ newd.installAfter(thisTransform)
+ }
+ this
}
- this
- }
- override def transformValDef(vdef: ValDef)(implicit ctx: Context, info: TransformerInfo): Tree = {
- val vble = vdef.symbol
- if (captured contains vble) {
- def boxMethod(name: TermName): Tree =
- ref(vble.info.classSymbol.companionModule.info.member(name).symbol)
- cpy.ValDef(vdef)(
- rhs = vdef.rhs match {
- case EmptyTree => boxMethod(nme.zero).appliedToNone.withPos(vdef.pos)
- case arg => boxMethod(nme.create).appliedTo(arg)
- },
- tpt = TypeTree(vble.info).withPos(vdef.tpt.pos))
+ override def transformValDef(vdef: ValDef)(implicit ctx: Context, info: TransformerInfo): Tree = {
+ val vble = vdef.symbol
+ if (captured contains vble) {
+ def boxMethod(name: TermName): Tree =
+ ref(vble.info.classSymbol.companionModule.info.member(name).symbol)
+ cpy.ValDef(vdef)(
+ rhs = vdef.rhs match {
+ case EmptyTree => boxMethod(nme.zero).appliedToNone.withPos(vdef.pos)
+ case arg => boxMethod(nme.create).appliedTo(arg)
+ },
+ tpt = TypeTree(vble.info).withPos(vdef.tpt.pos))
+ } else vdef
}
- else vdef
- }
- override def transformIdent(id: Ident)(implicit ctx: Context, info: TransformerInfo): Tree = {
- val vble = id.symbol
- if (captured(vble))
- (id select nme.elem).ensureConforms(vble.denot(ctx.withPhase(thisTransform)).info)
- else id
- }
+ override def transformIdent(id: Ident)(implicit ctx: Context, info: TransformerInfo): Tree = {
+ val vble = id.symbol
+ if (captured(vble))
+ (id select nme.elem).ensureConforms(vble.denot(ctx.withPhase(thisTransform)).info)
+ else id
+ }
- override def transformAssign(tree: Assign)(implicit ctx: Context, info: TransformerInfo): Tree = {
- val lhs1 = tree.lhs match {
- case TypeApply(Select(qual @ Select(qual2, nme.elem), nme.asInstanceOf_), _) =>
- assert(captured(qual2.symbol))
- qual
- case _ => tree.lhs
+ override def transformAssign(tree: Assign)(implicit ctx: Context, info: TransformerInfo): Tree = {
+ val lhs1 = tree.lhs match {
+ case TypeApply(Select(qual @ Select(qual2, nme.elem), nme.asInstanceOf_), _) =>
+ assert(captured(qual2.symbol))
+ qual
+ case _ => tree.lhs
+ }
+ cpy.Assign(tree)(lhs1, tree.rhs)
}
- cpy.Assign(tree)(lhs1, tree.rhs)
}
} \ No newline at end of file