diff options
Diffstat (limited to 'src/dotty/tools/dotc/ast/Trees.scala')
-rw-r--r-- | src/dotty/tools/dotc/ast/Trees.scala | 1232 |
1 files changed, 650 insertions, 582 deletions
diff --git a/src/dotty/tools/dotc/ast/Trees.scala b/src/dotty/tools/dotc/ast/Trees.scala index 2ae474d15..5836b0863 100644 --- a/src/dotty/tools/dotc/ast/Trees.scala +++ b/src/dotty/tools/dotc/ast/Trees.scala @@ -12,6 +12,7 @@ import collection.mutable.ListBuffer import parsing.Tokens.Token import printing.Printer import util.Stats +import annotation.unchecked.uncheckedVariance object Trees { @@ -96,7 +97,7 @@ object Trees { * It should have as end the end of the opening keywords(s). * If there is no opening keyword, point should equal end. */ - case class Modifiers[T >: Untyped] ( + case class Modifiers[-T >: Untyped] ( flags: FlagSet = EmptyFlags, privateWithin: TypeName = tpnme.EMPTY, annotations: List[Tree[T]] = Nil) extends Positioned with Cloneable { @@ -115,7 +116,7 @@ object Trees { if (this.flags == flags) this else copy(flags = flags) - def withAnnotations(annots: List[Tree[T]]) = + def withAnnotations[U >: Untyped <: T](annots: List[Tree[U]]): Modifiers[U] = if (annots.isEmpty) this else copy(annotations = annotations ++ annots) @@ -146,19 +147,21 @@ object Trees { * - Type checking an untyped tree should remove all embedded `TypedSplice` * nodes. */ - abstract class Tree[T >: Untyped] extends Positioned with Product with printing.Showable with Cloneable { + abstract class Tree[-T >: Untyped] extends Positioned with Product with printing.Showable with Cloneable { if (Stats.enabled) ntrees += 1 /** The type constructor at the root of the tree */ type ThisTree[T >: Untyped] <: Tree[T] - private var myTpe: T = _ + private[this] var myTpe: T = _ + + private def setMyTpe(tpe: T) = myTpe = tpe /** The type of the tree. In case of an untyped tree, * an UnAssignedTypeException is thrown. (Overridden by empty trees) */ - def tpe: T = { + def tpe: T @uncheckedVariance = { if (myTpe == null) throw new UnAssignedTypeException(this) myTpe } @@ -182,7 +185,7 @@ object Trees { (if (myTpe == null || (myTpe.asInstanceOf[AnyRef] eq tpe.asInstanceOf[AnyRef])) this else clone).asInstanceOf[Tree[Type]] - tree.myTpe = tpe + tree setMyTpe tpe tree.asInstanceOf[ThisTree[Type]] } @@ -228,8 +231,8 @@ object Trees { def toList: List[Tree[T]] = this :: Nil /** if this tree is the empty tree, the alternative, else this tree */ - def orElse(that: => Tree[T]): Tree[T] = - if (this eq EmptyTree) that else this + def orElse[U >: Untyped <: T](that: => Tree[U]): Tree[U] = + if (this eq genericEmptyTree) that else this override def toText(printer: Printer) = printer.toText(this) @@ -246,30 +249,30 @@ object Trees { /** Instances of this class are trees for which isType is definitely true. * Note that some trees have isType = true without being TypTrees (e.g. Ident, AnnotatedTree) */ - trait TypTree[T >: Untyped] extends Tree[T] { - type ThisTree[T >: Untyped] <: TypTree[T] + trait TypTree[-T >: Untyped] extends Tree[T] { + type ThisTree[-T >: Untyped] <: TypTree[T] override def isType = true } /** Instances of this class are trees for which isTerm is definitely true. * Note that some trees have isTerm = true without being TermTrees (e.g. Ident, AnnotatedTree) */ - trait TermTree[T >: Untyped] extends Tree[T] { - type ThisTree[T >: Untyped] <: TermTree[T] + trait TermTree[-T >: Untyped] extends Tree[T] { + type ThisTree[-T >: Untyped] <: TermTree[T] override def isTerm = true } /** Instances of this class are trees which are not terms but are legal * parts of patterns. */ - trait PatternTree[T >: Untyped] extends Tree[T] { - type ThisTree[T >: Untyped] <: PatternTree[T] + trait PatternTree[-T >: Untyped] extends Tree[T] { + type ThisTree[-T >: Untyped] <: PatternTree[T] override def isPattern = true } /** Tree's denotation can be derived from its type */ - abstract class DenotingTree[T >: Untyped] extends Tree[T] { - type ThisTree[T >: Untyped] <: DenotingTree[T] + abstract class DenotingTree[-T >: Untyped] extends Tree[T] { + type ThisTree[-T >: Untyped] <: DenotingTree[T] override def denot(implicit ctx: Context) = tpe match { case tpe: NamedType => tpe.denot case _ => NoDenotation @@ -279,8 +282,8 @@ object Trees { /** Tree's denot/isType/isTerm properties come from a subtree * identified by `forwardTo`. */ - abstract class ProxyTree[T >: Untyped] extends Tree[T] { - type ThisTree[T >: Untyped] <: ProxyTree[T] + abstract class ProxyTree[-T >: Untyped] extends Tree[T] { + type ThisTree[-T >: Untyped] <: ProxyTree[T] def forwardTo: Tree[T] override def denot(implicit ctx: Context): Denotation = forwardTo.denot override def isTerm = forwardTo.isTerm @@ -288,23 +291,23 @@ object Trees { } /** Tree has a name */ - abstract class NameTree[T >: Untyped] extends DenotingTree[T] { - type ThisTree[T >: Untyped] <: NameTree[T] + abstract class NameTree[-T >: Untyped] extends DenotingTree[T] { + type ThisTree[-T >: Untyped] <: NameTree[T] def name: Name - def withName(name1: Name): NameTree[T] + def withName(name1: Name)(implicit ctx: Context): untpd.NameTree } /** Tree refers by name to a denotation */ - abstract class RefTree[T >: Untyped] extends NameTree[T] { - type ThisTree[T >: Untyped] <: RefTree[T] + abstract class RefTree[-T >: Untyped] extends NameTree[T] { + type ThisTree[-T >: Untyped] <: RefTree[T] def qualifier: Tree[T] override def isType = name.isTypeName override def isTerm = name.isTermName } /** Tree defines a new symbol */ - trait DefTree[T >: Untyped] extends DenotingTree[T] { - type ThisTree[T >: Untyped] <: DefTree[T] + trait DefTree[-T >: Untyped] extends DenotingTree[T] { + type ThisTree[-T >: Untyped] <: DefTree[T] override def isDef = true } @@ -313,14 +316,14 @@ object Trees { * The envelope of a MemberDef contains the whole definition and his its point * on the opening keyword (or the next token after that if keyword is missing). */ - trait MemberDef[T >: Untyped] extends NameTree[T] with DefTree[T] { - type ThisTree[T >: Untyped] <: MemberDef[T] + trait MemberDef[-T >: Untyped] extends NameTree[T] with DefTree[T] { + type ThisTree[-T >: Untyped] <: MemberDef[T] def mods: Modifiers[T] override def envelope: Position = mods.pos union pos union initialPos } /** A ValDef or DefDef tree */ - trait ValOrDefDef[T >: Untyped] extends MemberDef[T] { + trait ValOrDefDef[-T >: Untyped] extends MemberDef[T] { def tpt: Tree[T] def rhs: Tree[T] } @@ -328,128 +331,126 @@ object Trees { // ----------- Tree case classes ------------------------------------ /** name */ - case class Ident[T >: Untyped](name: Name) + case class Ident[-T >: Untyped] private[ast] (name: Name) extends RefTree[T] { - type ThisTree[T >: Untyped] = Ident[T] - def withName(name: Name) = this.derivedIdent(name) - def qualifier: Tree[T] = emptyTree[T] + type ThisTree[-T >: Untyped] = Ident[T] + def withName(name: Name)(implicit ctx: Context): untpd.Ident = untpd.cpy.Ident(this, name) + def qualifier: Tree[T] = genericEmptyTree } - class BackquotedIdent[T >: Untyped](name: Name) + class BackquotedIdent[-T >: Untyped] private[ast] (name: Name) extends Ident[T](name) /** qualifier.name */ - case class Select[T >: Untyped](qualifier: Tree[T], name: Name) + case class Select[-T >: Untyped] private[ast] (qualifier: Tree[T], name: Name) extends RefTree[T] { - type ThisTree[T >: Untyped] = Select[T] - def withName(name: Name) = this.derivedSelect(qualifier, name) + type ThisTree[-T >: Untyped] = Select[T] + def withName(name: Name)(implicit ctx: Context): untpd.Select = untpd.cpy.Select(this, qualifier, name) } + class SelectWithSig[-T >: Untyped] private[ast] (qualifier: Tree[T], name: Name, val sig: Signature) + extends Select[T](qualifier, name) + /** qual.this */ - case class This[T >: Untyped](qual: TypeName) + case class This[-T >: Untyped] private[ast] (qual: TypeName) extends DenotingTree[T] with TermTree[T] { - type ThisTree[T >: Untyped] = This[T] + type ThisTree[-T >: Untyped] = This[T] } /** C.super[mix], where qual = C.this */ - case class Super[T >: Untyped](qual: Tree[T], mix: TypeName) + case class Super[-T >: Untyped] private[ast] (qual: Tree[T], mix: TypeName) extends ProxyTree[T] with TermTree[T] { - type ThisTree[T >: Untyped] = Super[T] + type ThisTree[-T >: Untyped] = Super[T] def forwardTo = qual } - abstract class GenericApply[T >: Untyped] extends ProxyTree[T] with TermTree[T] { - type ThisTree[T >: Untyped] <: GenericApply[T] + abstract class GenericApply[-T >: Untyped] extends ProxyTree[T] with TermTree[T] { + type ThisTree[-T >: Untyped] <: GenericApply[T] val fun: Tree[T] val args: List[Tree[T]] def forwardTo = fun } /** fun(args) */ - case class Apply[T >: Untyped](fun: Tree[T], args: List[Tree[T]]) + case class Apply[-T >: Untyped] private[ast] (fun: Tree[T], args: List[Tree[T]]) extends GenericApply[T] { - type ThisTree[T >: Untyped] = Apply[T] + type ThisTree[-T >: Untyped] = Apply[T] } /** fun[args] */ - case class TypeApply[T >: Untyped](fun: Tree[T], args: List[Tree[T]]) + case class TypeApply[-T >: Untyped] private[ast] (fun: Tree[T], args: List[Tree[T]]) extends GenericApply[T] { - type ThisTree[T >: Untyped] = TypeApply[T] + type ThisTree[-T >: Untyped] = TypeApply[T] } /** const */ - case class Literal[T >: Untyped](const: Constant) + case class Literal[-T >: Untyped] private[ast] (const: Constant) extends TermTree[T] { - type ThisTree[T >: Untyped] = Literal[T] + type ThisTree[-T >: Untyped] = Literal[T] } /** new tpt, but no constructor call */ - case class New[T >: Untyped](tpt: Tree[T]) + case class New[-T >: Untyped] private[ast] (tpt: Tree[T]) extends TermTree[T] { - type ThisTree[T >: Untyped] = New[T] + type ThisTree[-T >: Untyped] = New[T] } - /** new tpt(args1)...(args_n) - */ - def New[T >: Untyped](tpt: Tree[T], argss: List[List[Tree[T]]]): Tree[T] = - ((Select(New(tpt), nme.CONSTRUCTOR): Tree[T]) /: argss)(Apply(_, _)) - /** (left, right) */ - case class Pair[T >: Untyped](left: Tree[T], right: Tree[T]) + case class Pair[-T >: Untyped] private[ast] (left: Tree[T], right: Tree[T]) extends TermTree[T] { - type ThisTree[T >: Untyped] = Pair[T] + type ThisTree[-T >: Untyped] = Pair[T] override def isTerm = left.isTerm && right.isTerm override def isType = left.isType && right.isType override def isPattern = !isTerm && (left.isPattern || left.isTerm) && (right.isPattern || right.isTerm) } /** expr : tpt */ - case class Typed[T >: Untyped](expr: Tree[T], tpt: Tree[T]) + case class Typed[-T >: Untyped] private[ast] (expr: Tree[T], tpt: Tree[T]) extends ProxyTree[T] with TermTree[T] { - type ThisTree[T >: Untyped] = Typed[T] + type ThisTree[-T >: Untyped] = Typed[T] def forwardTo = expr } /** name = arg, in a parameter list */ - case class NamedArg[T >: Untyped](name: Name, arg: Tree[T]) + case class NamedArg[-T >: Untyped] private[ast] (name: Name, arg: Tree[T]) extends Tree[T] { - type ThisTree[T >: Untyped] = NamedArg[T] + type ThisTree[-T >: Untyped] = NamedArg[T] } /** name = arg, outside a parameter list */ - case class Assign[T >: Untyped](lhs: Tree[T], rhs: Tree[T]) + case class Assign[-T >: Untyped] private[ast] (lhs: Tree[T], rhs: Tree[T]) extends TermTree[T] { - type ThisTree[T >: Untyped] = Assign[T] + type ThisTree[-T >: Untyped] = Assign[T] } /** { stats; expr } */ - case class Block[T >: Untyped](stats: List[Tree[T]], expr: Tree[T]) + case class Block[-T >: Untyped] private[ast] (stats: List[Tree[T]], expr: Tree[T]) extends TermTree[T] { - type ThisTree[T >: Untyped] = Block[T] + type ThisTree[-T >: Untyped] = Block[T] } /** if cond then thenp else elsep */ - case class If[T >: Untyped](cond: Tree[T], thenp: Tree[T], elsep: Tree[T]) + case class If[-T >: Untyped] private[ast] (cond: Tree[T], thenp: Tree[T], elsep: Tree[T]) extends TermTree[T] { - type ThisTree[T >: Untyped] = If[T] + type ThisTree[-T >: Untyped] = If[T] } /** A closure with an environment and a reference to a method */ - case class Closure[T >: Untyped](env: List[Tree[T]], meth: RefTree[T]) + case class Closure[-T >: Untyped] private[ast] (env: List[Tree[T]], meth: RefTree[T]) extends TermTree[T] { - type ThisTree[T >: Untyped] = Closure[T] + type ThisTree[-T >: Untyped] = Closure[T] } /** selector match { cases } */ - case class Match[T >: Untyped](selector: Tree[T], cases: List[CaseDef[T]]) + case class Match[-T >: Untyped] private[ast] (selector: Tree[T], cases: List[CaseDef[T]]) extends TermTree[T] { - type ThisTree[T >: Untyped] = Match[T] + type ThisTree[-T >: Untyped] = Match[T] } /** case pat if guard => body */ - case class CaseDef[T >: Untyped](pat: Tree[T], guard: Tree[T], body: Tree[T]) + case class CaseDef[-T >: Untyped] private[ast] (pat: Tree[T], guard: Tree[T], body: Tree[T]) extends Tree[T] { - type ThisTree[T >: Untyped] = CaseDef[T] + type ThisTree[-T >: Untyped] = CaseDef[T] } /** return expr @@ -457,121 +458,114 @@ object Trees { * After program transformations this is not necessarily the enclosing method, because * closures can intervene. */ - case class Return[T >: Untyped](expr: Tree[T], from: Tree[T] = emptyTree[T]()) + case class Return[-T >: Untyped] private[ast] (expr: Tree[T], from: Tree[T] = genericEmptyTree) extends TermTree[T] { - type ThisTree[T >: Untyped] = Return[T] + type ThisTree[-T >: Untyped] = Return[T] } /** try block catch handler finally finalizer */ - case class Try[T >: Untyped](expr: Tree[T], handler: Tree[T], finalizer: Tree[T]) + case class Try[-T >: Untyped] private[ast] (expr: Tree[T], handler: Tree[T], finalizer: Tree[T]) extends TermTree[T] { - type ThisTree[T >: Untyped] = Try[T] + type ThisTree[-T >: Untyped] = Try[T] } /** throw expr */ - case class Throw[T >: Untyped](expr: Tree[T]) + case class Throw[-T >: Untyped] private[ast] (expr: Tree[T]) extends TermTree[T] { - type ThisTree[T >: Untyped] = Throw[T] + type ThisTree[-T >: Untyped] = Throw[T] } /** Array[elemtpt](elems) */ - case class SeqLiteral[T >: Untyped](elems: List[Tree[T]]) + case class SeqLiteral[-T >: Untyped] private[ast] (elems: List[Tree[T]]) extends Tree[T] { - type ThisTree[T >: Untyped] = SeqLiteral[T] + type ThisTree[-T >: Untyped] = SeqLiteral[T] } /** A type tree that represents an existing or inferred type */ - case class TypeTree[T >: Untyped](original: Tree[T] = emptyTree[T]) + case class TypeTree[-T >: Untyped] private[ast] (original: Tree[T]) extends DenotingTree[T] with TypTree[T] { - type ThisTree[T >: Untyped] = TypeTree[T] + type ThisTree[-T >: Untyped] = TypeTree[T] override def initialPos = NoPosition override def isEmpty = !hasType && original.isEmpty } - object TypeTree { - def apply(tpe: Type): TypeTree[Type] = TypeTree().withType(tpe) - } - /** ref.type */ - case class SingletonTypeTree[T >: Untyped](ref: Tree[T]) + case class SingletonTypeTree[-T >: Untyped] private[ast] (ref: Tree[T]) extends DenotingTree[T] with TypTree[T] { - type ThisTree[T >: Untyped] = SingletonTypeTree[T] + type ThisTree[-T >: Untyped] = SingletonTypeTree[T] } /** qualifier # name */ - case class SelectFromTypeTree[T >: Untyped](qualifier: Tree[T], name: Name) + case class SelectFromTypeTree[-T >: Untyped] private[ast] (qualifier: Tree[T], name: Name) extends RefTree[T] { - type ThisTree[T >: Untyped] = SelectFromTypeTree[T] - def withName(name: Name) = this.derivedSelectFromTypeTree(qualifier, name) + type ThisTree[-T >: Untyped] = SelectFromTypeTree[T] + def withName(name: Name)(implicit ctx: Context): untpd.SelectFromTypeTree = untpd.cpy.SelectFromTypeTree(this, qualifier, name) } /** left & right */ - case class AndTypeTree[T >: Untyped](left: Tree[T], right: Tree[T]) + case class AndTypeTree[-T >: Untyped] private[ast] (left: Tree[T], right: Tree[T]) extends TypTree[T] { - type ThisTree[T >: Untyped] = AndTypeTree[T] + type ThisTree[-T >: Untyped] = AndTypeTree[T] } /** left | right */ - case class OrTypeTree[T >: Untyped](left: Tree[T], right: Tree[T]) + case class OrTypeTree[-T >: Untyped] private[ast] (left: Tree[T], right: Tree[T]) extends TypTree[T] { - type ThisTree[T >: Untyped] = OrTypeTree[T] + type ThisTree[-T >: Untyped] = OrTypeTree[T] } /** tpt { refinements } */ - case class RefinedTypeTree[T >: Untyped](tpt: Tree[T], refinements: List[Tree[T]]) + case class RefinedTypeTree[-T >: Untyped] private[ast] (tpt: Tree[T], refinements: List[Tree[T]]) extends ProxyTree[T] with TypTree[T] { - type ThisTree[T >: Untyped] = RefinedTypeTree[T] + type ThisTree[-T >: Untyped] = RefinedTypeTree[T] def forwardTo = tpt } /** tpt[args] */ - case class AppliedTypeTree[T >: Untyped](tpt: Tree[T], args: List[Tree[T]]) + case class AppliedTypeTree[-T >: Untyped] private[ast] (tpt: Tree[T], args: List[Tree[T]]) extends ProxyTree[T] with TypTree[T] { - type ThisTree[T >: Untyped] = AppliedTypeTree[T] + type ThisTree[-T >: Untyped] = AppliedTypeTree[T] def forwardTo = tpt } - def AppliedTypeTree[T >: Untyped](tpt: Tree[T], arg: Tree[T]): AppliedTypeTree[T] = - AppliedTypeTree(tpt, arg :: Nil) - /** >: lo <: hi */ - case class TypeBoundsTree[T >: Untyped](lo: Tree[T], hi: Tree[T]) + case class TypeBoundsTree[-T >: Untyped] private[ast] (lo: Tree[T], hi: Tree[T]) extends Tree[T] { - type ThisTree[T >: Untyped] = TypeBoundsTree[T] + type ThisTree[-T >: Untyped] = TypeBoundsTree[T] } /** name @ body */ - case class Bind[T >: Untyped](name: Name, body: Tree[T]) + case class Bind[-T >: Untyped] private[ast] (name: Name, body: Tree[T]) extends NameTree[T] with DefTree[T] with PatternTree[T] { - type ThisTree[T >: Untyped] = Bind[T] + type ThisTree[-T >: Untyped] = Bind[T] override def envelope: Position = pos union initialPos - def withName(name: Name) = this.derivedBind(name, body) + def withName(name: Name)(implicit ctx: Context): untpd.Bind = untpd.cpy.Bind(this, name, body) } /** tree_1 | ... | tree_n */ - case class Alternative[T >: Untyped](trees: List[Tree[T]]) + case class Alternative[-T >: Untyped] private[ast] (trees: List[Tree[T]]) extends PatternTree[T] { - type ThisTree[T >: Untyped] = Alternative[T] + type ThisTree[-T >: Untyped] = Alternative[T] } /** fun(args) in a pattern, if fun is an extractor */ - case class UnApply[T >: Untyped](fun: Tree[T], args: List[Tree[T]]) + case class UnApply[-T >: Untyped] private[ast] (fun: Tree[T], args: List[Tree[T]]) extends PatternTree[T] { - type ThisTree[T >: Untyped] = UnApply[T] + type ThisTree[-T >: Untyped] = UnApply[T] } /** mods val name: tpt = rhs */ - case class ValDef[T >: Untyped](mods: Modifiers[T], name: TermName, tpt: Tree[T], rhs: Tree[T]) + case class ValDef[-T >: Untyped] private[ast] (mods: Modifiers[T], name: TermName, tpt: Tree[T], rhs: Tree[T]) extends ValOrDefDef[T] { - type ThisTree[T >: Untyped] = ValDef[T] - def withName(name: Name) = this.derivedValDef(mods, name.toTermName, tpt, rhs) + type ThisTree[-T >: Untyped] = ValDef[T] + def withName(name: Name)(implicit ctx: Context): untpd.ValDef = untpd.cpy.ValDef(this, mods, name.toTermName, tpt, rhs) } /** mods def name[tparams](vparams_1)...(vparams_n): tpt = rhs */ - case class DefDef[T >: Untyped](mods: Modifiers[T], name: TermName, tparams: List[TypeDef[T]], vparamss: List[List[ValDef[T]]], tpt: Tree[T], rhs: Tree[T]) + case class DefDef[-T >: Untyped] private[ast] (mods: Modifiers[T], name: TermName, tparams: List[TypeDef[T]], vparamss: List[List[ValDef[T]]], tpt: Tree[T], rhs: Tree[T]) extends ValOrDefDef[T] { - type ThisTree[T >: Untyped] = DefDef[T] - def withName(name: Name) = this.derivedDefDef(mods, name.toTermName, tparams, vparamss, tpt, rhs) + type ThisTree[-T >: Untyped] = DefDef[T] + def withName(name: Name)(implicit ctx: Context): untpd.DefDef = untpd.cpy.DefDef(this, mods, name.toTermName, tparams, vparamss, tpt, rhs) } /** mods class name template or @@ -579,10 +573,10 @@ object Trees { * mods type name = rhs or * mods type name >: lo <: hi, if rhs = TypeBoundsTree(lo, hi) & (lo ne hi) */ - case class TypeDef[T >: Untyped](mods: Modifiers[T], name: TypeName, rhs: Tree[T]) + case class TypeDef[-T >: Untyped] private[ast] (mods: Modifiers[T], name: TypeName, rhs: Tree[T]) extends MemberDef[T] { - type ThisTree[T >: Untyped] = TypeDef[T] - def withName(name: Name) = this.derivedTypeDef(mods, name.toTypeName, rhs, tparams) + type ThisTree[-T >: Untyped] = TypeDef[T] + def withName(name: Name)(implicit ctx: Context): untpd.TypeDef = untpd.cpy.TypeDef(this, mods, name.toTypeName, rhs, tparams) /** Is this a definition of a class? */ def isClassDef = rhs.isInstanceOf[Template[_]] @@ -595,97 +589,76 @@ object Trees { } /** extends parents { self => body } */ - case class Template[T >: Untyped](constr: DefDef[T], parents: List[Tree[T]], self: ValDef[T], body: List[Tree[T]]) + case class Template[-T >: Untyped] private[ast] (constr: DefDef[T], parents: List[Tree[T]], self: ValDef[T], body: List[Tree[T]]) extends DefTree[T] { - type ThisTree[T >: Untyped] = Template[T] + type ThisTree[-T >: Untyped] = Template[T] } /** import expr.selectors * where a selector is either an untyped `Ident`, `name` or * an untyped `Pair` `name => rename` */ - case class Import[T >: Untyped](expr: Tree[T], selectors: List[Tree[Untyped]]) + case class Import[-T >: Untyped] private[ast] (expr: Tree[T], selectors: List[Tree[Untyped]]) extends DenotingTree[T] { - type ThisTree[T >: Untyped] = Import[T] + type ThisTree[-T >: Untyped] = Import[T] } /** package pid { stats } */ - case class PackageDef[T >: Untyped](pid: RefTree[T], stats: List[Tree[T]]) + case class PackageDef[-T >: Untyped] private[ast] (pid: RefTree[T], stats: List[Tree[T]]) extends ProxyTree[T] { - type ThisTree[T >: Untyped] = PackageDef[T] + type ThisTree[-T >: Untyped] = PackageDef[T] def forwardTo = pid } /** arg @annot */ - case class Annotated[T >: Untyped](annot: Tree[T], arg: Tree[T]) + case class Annotated[-T >: Untyped] private[ast] (annot: Tree[T], arg: Tree[T]) extends ProxyTree[T] { - type ThisTree[T >: Untyped] = Annotated[T] + type ThisTree[-T >: Untyped] = Annotated[T] def forwardTo = arg } - trait WithoutType[T >: Untyped] extends Tree[T] { - override def tpe = NoType.asInstanceOf[T] + trait WithoutType[-T >: Untyped] extends Tree[T] { + override def tpe: T @uncheckedVariance = NoType.asInstanceOf[T] override def withType(tpe: Type) = this.asInstanceOf[ThisTree[Type]] } - val EmptyTree: Thicket[_] = Thicket(Nil) - - def emptyTree[T >: Untyped](): Thicket[T] = EmptyTree.asInstanceOf[Thicket[T]] - - class EmptyValDef[T >: Untyped] extends ValDef[T]( - Modifiers[T](Private), nme.WILDCARD, emptyTree[T], emptyTree[T]) with WithoutType[T] { - override def isEmpty: Boolean = true - } - - private object theEmptyValDef extends EmptyValDef[Untyped] - - object EmptyValDef { - def apply[T >: Untyped](): EmptyValDef[T] = theEmptyValDef.asInstanceOf[EmptyValDef[T]] - } - - /** A tree that can be shared without its position - * polluting containing trees. Accumulators and tranformers - * memoize results of shared subtrees - */ - case class SharedTree[T >: Untyped](shared: Tree[T]) extends ProxyTree[T] { - type ThisTree[T >: Untyped] = SharedTree[T] - def forwardTo: Tree[T] = shared - } - /** Temporary class that results from translation of ModuleDefs * (and possibly other statements). * The contained trees will be integrated when transformed with * a `transform(List[Tree])` call. */ - case class Thicket[T >: Untyped](trees: List[Tree[T]]) + case class Thicket[-T >: Untyped](trees: List[Tree[T]]) extends Tree[T] with WithoutType[T] { - type ThisTree[T >: Untyped] = Thicket[T] + type ThisTree[-T >: Untyped] = Thicket[T] override def isEmpty: Boolean = trees.isEmpty override def toList: List[Tree[T]] = trees override def toString = if (isEmpty) "EmptyTree" else "Thicket(" + trees.mkString(", ") + ")" } - object Thicket { - def apply[T >: Untyped](): Thicket[T] = emptyTree() - def apply[T >: Untyped](x1: Tree[T], x2: Tree[T]): Thicket[T] = Thicket(x1 :: x2 :: Nil) - def apply[T >: Untyped](x1: Tree[T], x2: Tree[T], x3: Tree[T]): Thicket[T] = Thicket(x1 :: x2 :: x3 :: Nil) - def make[T >: Untyped](xs: List[Tree[T]]): Tree[T] = flatten(xs) match { - case x :: Nil => x - case _ => apply(xs) - } + class EmptyValDef[T >: Untyped] extends ValDef[T]( + Modifiers[T](Private), nme.WILDCARD, genericEmptyTree[T], genericEmptyTree[T]) with WithoutType[T] { + override def isEmpty: Boolean = true } - // ----- Auxiliary creation methods ------------------ + val theEmptyTree: Thicket[Type] = Thicket(Nil) + val theEmptyValDef = new EmptyValDef[Type] + + def genericEmptyValDef[T >: Untyped]: ValDef[T] = theEmptyValDef.asInstanceOf[ValDef[T]] + def genericEmptyTree[T >: Untyped]: Thicket[T] = theEmptyTree.asInstanceOf[Thicket[T]] - def Block[T >: Untyped](stat: Tree[T], expr: Tree[T]): Block[T] = - Block(stat :: Nil, expr) + /** A tree that can be shared without its position + * polluting containing trees. Accumulators and tranformers + * memoize results of shared subtrees + */ + case class SharedTree[-T >: Untyped](shared: Tree[T]) extends ProxyTree[T] { + type ThisTree[-T >: Untyped] = SharedTree[T] + def forwardTo: Tree[T] = shared + } - def Apply[T >: Untyped](fn: Tree[T], arg: Tree[T]): Apply[T] = - Apply(fn, arg :: Nil) // ----- Generic Tree Instances, inherited from `tpt` and `untpd`. - abstract class Instance[T >: Untyped] { + abstract class Instance[T >: Untyped] extends DotClass { inst => type Modifiers = Trees.Modifiers[T] type Tree = Trees.Tree[T] @@ -703,6 +676,7 @@ object Trees { type Ident = Trees.Ident[T] type BackquotedIdent = Trees.BackquotedIdent[T] type Select = Trees.Select[T] + type SelectWithSig = Trees.SelectWithSig[T] type This = Trees.This[T] type Super = Trees.Super[T] type Apply = Trees.Apply[T] @@ -743,182 +717,521 @@ object Trees { type SharedTree = Trees.SharedTree[T] type Thicket = Trees.Thicket[T] - protected implicit def pos(implicit ctx: Context): Position = ctx.position + def Ident(name: Name)(implicit ctx: Context): Ident = new Ident(name) + def BackquotedIdent(name: Name)(implicit ctx: Context): BackquotedIdent = new BackquotedIdent(name) + def Select(qualifier: Tree, name: Name)(implicit ctx: Context): Select = new Select(qualifier, name) + def SelectWithSig(qualifier: Tree, name: Name, sig: Signature)(implicit ctx: Context): Select = new SelectWithSig(qualifier, name, sig) + def This(qual: TypeName)(implicit ctx: Context): This = new This(qual) + def Super(qual: Tree, mix: TypeName)(implicit ctx: Context): Super = new Super(qual, mix) + def Apply(fun: Tree, args: List[Tree])(implicit ctx: Context): Apply = new Apply(fun, args) + def TypeApply(fun: Tree, args: List[Tree])(implicit ctx: Context): TypeApply = new TypeApply(fun, args) + def Literal(const: Constant)(implicit ctx: Context): Literal = new Literal(const) + def New(tpt: Tree)(implicit ctx: Context): New = new New(tpt) + def Pair(left: Tree, right: Tree)(implicit ctx: Context): Pair = new Pair(left, right) + def Typed(expr: Tree, tpt: Tree)(implicit ctx: Context): Typed = new Typed(expr, tpt) + def NamedArg(name: Name, arg: Tree)(implicit ctx: Context): NamedArg = new NamedArg(name, arg) + def Assign(lhs: Tree, rhs: Tree)(implicit ctx: Context): Assign = new Assign(lhs, rhs) + def Block(stats: List[Tree], expr: Tree)(implicit ctx: Context): Block = new Block(stats, expr) + def If(cond: Tree, thenp: Tree, elsep: Tree)(implicit ctx: Context): If = new If(cond, thenp, elsep) + def Closure(env: List[Tree], meth: RefTree)(implicit ctx: Context): Closure = new Closure(env, meth) + def Match(selector: Tree, cases: List[CaseDef])(implicit ctx: Context): Match = new Match(selector, cases) + def CaseDef(pat: Tree, guard: Tree, body: Tree)(implicit ctx: Context): CaseDef = new CaseDef(pat, guard, body) + def Return(expr: Tree, from: Tree)(implicit ctx: Context): Return = new Return(expr, from) + def Try(expr: Tree, handler: Tree, finalizer: Tree)(implicit ctx: Context): Try = new Try(expr, handler, finalizer) + def Throw(expr: Tree)(implicit ctx: Context): Throw = new Throw(expr) + def SeqLiteral(elems: List[Tree])(implicit ctx: Context): SeqLiteral = new SeqLiteral(elems) + def TypeTree(original: Tree)(implicit ctx: Context): TypeTree = new TypeTree(original) + def TypeTree() = new TypeTree(EmptyTree) + def SingletonTypeTree(ref: Tree)(implicit ctx: Context): SingletonTypeTree = new SingletonTypeTree(ref) + def SelectFromTypeTree(qualifier: Tree, name: Name)(implicit ctx: Context): SelectFromTypeTree = new SelectFromTypeTree(qualifier, name) + def AndTypeTree(left: Tree, right: Tree)(implicit ctx: Context): AndTypeTree = new AndTypeTree(left, right) + def OrTypeTree(left: Tree, right: Tree)(implicit ctx: Context): OrTypeTree = new OrTypeTree(left, right) + def RefinedTypeTree(tpt: Tree, refinements: List[Tree])(implicit ctx: Context): RefinedTypeTree = new RefinedTypeTree(tpt, refinements) + def AppliedTypeTree(tpt: Tree, args: List[Tree])(implicit ctx: Context): AppliedTypeTree = new AppliedTypeTree(tpt, args) + def TypeBoundsTree(lo: Tree, hi: Tree)(implicit ctx: Context): TypeBoundsTree = new TypeBoundsTree(lo, hi) + def Bind(name: Name, body: Tree)(implicit ctx: Context): Bind = new Bind(name, body) + def Alternative(trees: List[Tree])(implicit ctx: Context): Alternative = new Alternative(trees) + def UnApply(fun: Tree, args: List[Tree])(implicit ctx: Context): UnApply = new UnApply(fun, args) + def ValDef(mods: Modifiers, name: TermName, tpt: Tree, rhs: Tree)(implicit ctx: Context): ValDef = new ValDef(mods, name, tpt, rhs) + def DefDef(mods: Modifiers, name: TermName, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree)(implicit ctx: Context): DefDef = new DefDef(mods, name, tparams, vparamss, tpt, rhs) + def TypeDef(mods: Modifiers, name: TypeName, rhs: Tree)(implicit ctx: Context): TypeDef = new TypeDef(mods, name, rhs) + def Template(constr: DefDef, parents: List[Tree], self: ValDef, body: List[Tree])(implicit ctx: Context): Template = new Template(constr, parents, self, body) + def Import(expr: Tree, selectors: List[untpd.Tree])(implicit ctx: Context): Import = new Import(expr, selectors) + def PackageDef(pid: RefTree, stats: List[Tree])(implicit ctx: Context): PackageDef = new PackageDef(pid, stats) + def Annotated(annot: Tree, arg: Tree)(implicit ctx: Context): Annotated = new Annotated(annot, arg) + def SharedTree(shared: Tree)(implicit ctx: Context): SharedTree = new SharedTree(shared) + def Thicket(trees: List[Tree])(implicit ctx: Context): Thicket = new Thicket(trees) + + val EmptyTree: Thicket = genericEmptyTree + val EmptyValDef: ValDef = genericEmptyValDef + + def Modifiers(flags: FlagSet = EmptyFlags, + privateWithin: TypeName = tpnme.EMPTY, + annotations: List[Tree] = Nil) = new Modifiers(flags, privateWithin, annotations) + + // ----- Auxiliary creation methods ------------------ + + // def TypeTree(tpe: Type): TypeTree = TypeTree().withType(tpe) todo: move to untpd/tpd + + /** new tpt(args1)...(args_n) + */ + def New(tpt: Tree, argss: List[List[Tree]])(implicit ctx: Context): Tree = + ((Select(New(tpt), nme.CONSTRUCTOR): Tree) /: argss)(Apply(_, _)) - def defPos(sym: Symbol)(implicit ctx: Context) = ctx.position union sym.coord.toPosition - } + def Block(stat: Tree, expr: Tree)(implicit ctx: Context): Block = + Block(stat :: Nil, expr) - // ----- Helper functions and classes --------------------------------------- + def Apply(fn: Tree, arg: Tree)(implicit ctx: Context): Apply = + Apply(fn, arg :: Nil) - implicit class TreeCopier[T >: Untyped](val tree: Tree[T]) extends AnyVal { - def derivedIdent(name: Name): Ident[T] = tree match { - case tree: BackquotedIdent[_] => - if (name == tree.name) tree - else new BackquotedIdent[T](name).withPos(tree.pos) - case tree: Ident[_] if (name == tree.name) => tree - case _ => Ident[T](name).withPos(tree.pos) - } - def derivedSelect(qualifier: Tree[T], name: Name): Select[T] = tree match { - case tree: Select[_] if (qualifier eq tree.qualifier) && (name == tree.name) => tree - case _ => Select(qualifier, name).withPos(tree.pos) - } - def derivedThis(qual: TypeName): This[T] = tree match { - case tree: This[_] if (qual == tree.qual) => tree - case _ => This[T](qual).withPos(tree.pos) - } - def derivedSuper(qual: Tree[T], mix: TypeName): Super[T] = tree match { - case tree: Super[_] if (qual eq tree.qual) && (mix == tree.mix) => tree - case _ => Super(qual, mix).withPos(tree.pos) - } - def derivedApply(fun: Tree[T], args: List[Tree[T]]): Apply[T] = tree match { - case tree: Apply[_] if (fun eq tree.fun) && (args eq tree.args) => tree - case _ => Apply(fun, args).withPos(tree.pos) - } - def derivedTypeApply(fun: Tree[T], args: List[Tree[T]]): TypeApply[T] = tree match { - case tree: TypeApply[_] if (fun eq tree.fun) && (args eq tree.args) => tree - case _ => TypeApply(fun, args).withPos(tree) - } - def derivedLiteral(const: Constant): Literal[T] = tree match { - case tree: Literal[_] if (const == tree.const) => tree - case _ => Literal[T](const).withPos(tree.pos) - } - def derivedNew(tpt: Tree[T]): New[T] = tree match { - case tree: New[_] if (tpt eq tree.tpt) => tree - case _ => New(tpt).withPos(tree.pos) - } - def derivedPair(left: Tree[T], right: Tree[T]): Pair[T] = tree match { - case tree: Pair[_] if (left eq tree.left) && (right eq tree.right) => tree - case _ => Pair(left, right).withPos(tree.pos) - } - def derivedTyped(expr: Tree[T], tpt: Tree[T]): Typed[T] = tree match { - case tree: Typed[_] if (expr eq tree.expr) && (tpt eq tree.tpt) => tree - case _ => Typed(expr, tpt).withPos(tree.pos) - } - def derivedNamedArg(name: Name, arg: Tree[T]): NamedArg[T] = tree match { - case tree: NamedArg[_] if (name == tree.name) && (arg eq tree.arg) => tree - case _ => NamedArg(name, arg).withPos(tree.pos) - } - def derivedAssign(lhs: Tree[T], rhs: Tree[T]): Assign[T] = tree match { - case tree: Assign[_] if (lhs eq tree.lhs) && (rhs eq tree.rhs) => tree - case _ => Assign(lhs, rhs).withPos(tree.pos) - } - def derivedBlock(stats: List[Tree[T]], expr: Tree[T]): Block[T] = tree match { - case tree: Block[_] if (stats eq tree.stats) && (expr eq tree.expr) => tree - case _ => Block(stats, expr).withPos(tree.pos) - } - def derivedIf(cond: Tree[T], thenp: Tree[T], elsep: Tree[T]): If[T] = tree match { - case tree: If[_] if (cond eq tree.cond) && (thenp eq tree.thenp) && (elsep eq tree.elsep) => tree - case _ => If(cond, thenp, elsep).withPos(tree.pos) - } - def derivedClosure(env: List[Tree[T]], meth: RefTree[T]): Closure[T] = tree match { - case tree: Closure[_] if (env eq tree.env) && (meth eq tree.meth) => tree - case _ => Closure(env, meth).withPos(tree.pos) - } - def derivedMatch(selector: Tree[T], cases: List[CaseDef[T]]): Match[T] = tree match { - case tree: Match[_] if (selector eq tree.selector) && (cases eq tree.cases) => tree - case _ => Match(selector, cases).withPos(tree.pos) - } - def derivedCaseDef(pat: Tree[T], guard: Tree[T], body: Tree[T]): CaseDef[T] = tree match { - case tree: CaseDef[_] if (pat eq tree.pat) && (guard eq tree.guard) && (body eq tree.body) => tree - case _ => CaseDef(pat, guard, body).withPos(tree.pos) - } - def derivedReturn(expr: Tree[T], from: Tree[T]): Return[T] = tree match { - case tree: Return[_] if (expr eq tree.expr) && (from eq tree.from) => tree - case _ => Return(expr, from).withPos(tree.pos) - } - def derivedTry(expr: Tree[T], handler: Tree[T], finalizer: Tree[T]): Try[T] = tree match { - case tree: Try[_] if (expr eq tree.expr) && (handler eq tree.handler) && (finalizer eq tree.finalizer) => tree - case _ => Try(expr, handler, finalizer).withPos(tree.pos) - } - def derivedThrow(expr: Tree[T]): Throw[T] = tree match { - case tree: Throw[_] if (expr eq tree.expr) => tree - case _ => Throw(expr).withPos(tree.pos) - } - def derivedSeqLiteral(elems: List[Tree[T]]): SeqLiteral[T] = tree match { - case tree: SeqLiteral[_] if (elems eq tree.elems) => tree - case _ => SeqLiteral(elems).withPos(tree.pos) - } - def derivedSingletonTypeTree(ref: Tree[T]): SingletonTypeTree[T] = tree match { - case tree: SingletonTypeTree[_] if (ref eq tree.ref) => tree - case _ => SingletonTypeTree(ref).withPos(tree.pos) - } - def derivedSelectFromTypeTree(qualifier: Tree[T], name: Name): SelectFromTypeTree[T] = tree match { - case tree: SelectFromTypeTree[_] if (qualifier eq tree.qualifier) && (name == tree.name) => tree - case _ => SelectFromTypeTree(qualifier, name).withPos(tree.pos) - } - def derivedAndTypeTree(left: Tree[T], right: Tree[T]): AndTypeTree[T] = tree match { - case tree: AndTypeTree[_] if (left eq tree.left) && (right eq tree.right) => tree - case _ => AndTypeTree(left, right).withPos(tree.pos) - } - def derivedOrTypeTree(left: Tree[T], right: Tree[T]): OrTypeTree[T] = tree match { - case tree: OrTypeTree[_] if (left eq tree.left) && (right eq tree.right) => tree - case _ => OrTypeTree(left, right).withPos(tree.pos) - } - def derivedRefinedTypeTree(tpt: Tree[T], refinements: List[Tree[T]]): RefinedTypeTree[T] = tree match { - case tree: RefinedTypeTree[_] if (tpt eq tree.tpt) && (refinements eq tree.refinements) => tree - case _ => RefinedTypeTree(tpt, refinements).withPos(tree.pos) - } - def derivedAppliedTypeTree(tpt: Tree[T], args: List[Tree[T]]): AppliedTypeTree[T] = tree match { - case tree: AppliedTypeTree[_] if (tpt eq tree.tpt) && (args eq tree.args) => tree - case _ => AppliedTypeTree(tpt, args).withPos(tree.pos) - } - def derivedTypeBoundsTree(lo: Tree[T], hi: Tree[T]): TypeBoundsTree[T] = tree match { - case tree: TypeBoundsTree[_] if (lo eq tree.lo) && (hi eq tree.hi) => tree - case _ => TypeBoundsTree(lo, hi).withPos(tree.pos) - } - def derivedBind(name: Name, body: Tree[T]): Bind[T] = tree match { - case tree: Bind[_] if (name eq tree.name) && (body eq tree.body) => tree - case _ => Bind(name, body).withPos(tree.pos) - } - def derivedAlternative(trees: List[Tree[T]]): Alternative[T] = tree match { - case tree: Alternative[_] if (trees eq tree.trees) => tree - case _ => Alternative(trees).withPos(tree.pos) - } - def derivedUnApply(fun: Tree[T], args: List[Tree[T]]): UnApply[T] = tree match { - case tree: UnApply[_] if (fun eq tree.fun) && (args eq tree.args) => tree - case _ => UnApply(fun, args).withPos(tree.pos) - } - def derivedValDef(mods: Modifiers[T], name: TermName, tpt: Tree[T], rhs: Tree[T]): ValDef[T] = tree match { - case tree: ValDef[_] if (mods == tree.mods) && (name == tree.name) && (tpt eq tree.tpt) && (rhs eq tree.rhs) => tree - case _ => ValDef(mods, name, tpt, rhs).withPos(tree.pos) - } - def derivedDefDef(mods: Modifiers[T], name: TermName, tparams: List[TypeDef[T]], vparamss: List[List[ValDef[T]]], tpt: Tree[T], rhs: Tree[T]): DefDef[T] = tree match { - case tree: DefDef[_] if (mods == tree.mods) && (name == tree.name) && (tparams eq tree.tparams) && (vparamss eq tree.vparamss) && (tpt eq tree.tpt) && (rhs eq tree.rhs) => tree - case _ => DefDef(mods, name, tparams, vparamss, tpt, rhs).withPos(tree.pos) - } - def derivedTypeDef(mods: Modifiers[T], name: TypeName, rhs: Tree[T], tparams: List[untpd.TypeDef] = Nil): TypeDef[T] = tree match { - case tree: TypeDef[_] if (mods == tree.mods) && (name == tree.name) && (rhs eq tree.rhs) && (tparams eq tree.tparams) => tree - case _ => - if (tparams.nonEmpty) - (untpd.typeDef _).asInstanceOf[(Modifiers[T], TypeName, List[untpd.TypeDef], Tree[T]) => TypeDef[T]]( - mods, name, tparams, rhs).withPos(tree.pos) - else TypeDef(mods, name, rhs).withPos(tree.pos) + def AppliedTypeTree(tpt: Tree, arg: Tree)(implicit ctx: Context): AppliedTypeTree = + AppliedTypeTree(tpt, arg :: Nil) + + def Thicket()(implicit ctx: Context): Thicket = EmptyTree + def Thicket(x1: Tree, x2: Tree)(implicit ctx: Context): Thicket = Thicket(x1 :: x2 :: Nil) + def Thicket(x1: Tree, x2: Tree, x3: Tree)(implicit ctx: Context): Thicket = Thicket(x1 :: x2 :: x3 :: Nil) + def flatTree(xs: List[Tree])(implicit ctx: Context): Tree = flatten(xs) match { + case x :: Nil => x + case _ => Thicket(xs) } - def derivedTemplate(constr: DefDef[T], parents: List[Tree[T]], self: ValDef[T], body: List[Tree[T]]): Template[T] = tree match { - case tree: Template[_] if (constr eq tree.constr) && (parents eq tree.parents) && (self eq tree.self) && (body eq tree.body) => tree - case _ => Template(constr, parents, self, body).withPos(tree.pos) + + def flatten(trees: List[Tree]): List[Tree] = { + var buf: ListBuffer[Tree] = null + def add(tree: Tree) = { + assert(!tree.isInstanceOf[Thicket]) + buf += tree + } + var xs = trees + while (xs.nonEmpty) { + xs.head match { + case Thicket(elems) => + if (buf == null) { + buf = new ListBuffer + var ys = trees + while (ys ne xs) { + buf += ys.head + ys = ys.tail + } + } + for (elem <- elems) { + assert(!elem.isInstanceOf[Thicket]) + buf += elem + } + case tree => + if (buf != null) buf += tree + } + xs = xs.tail + } + if (buf != null) buf.toList else trees } - def derivedImport(expr: Tree[T], selectors: List[Tree[Untyped]]): Import[T] = tree match { - case tree: Import[_] if (expr eq tree.expr) && (selectors eq tree.selectors) => tree - case _ => Import(expr, selectors).withPos(tree.pos) + + // ----- Position handling ----------------------------------------- + + protected implicit def pos(implicit ctx: Context): Position = ctx.position + + def defPos(sym: Symbol)(implicit ctx: Context) = ctx.position union sym.coord.toPosition + + // ----- Helper classes for copying, transforming, accumulating ----------------- + + val cpy: TreeCopier + + abstract class TreeCopier { + + def postProcess(tree: Tree, copied: untpd.Tree): copied.ThisTree[T] + + def finalize(tree: Tree, copied: untpd.Tree): copied.ThisTree[T] = + postProcess(tree, copied withPos tree.pos) + + private def copyAttrs(t: untpd.Tree, tree: Tree): t.ThisTree[T] = + t.withType(tree.typeOpt).withPos(tree.pos).asInstanceOf[t.ThisTree[T]] + + def Ident(tree: Tree, name: Name)(implicit ctx: Context): Ident = tree match { + case tree: BackquotedIdent => + if (name == tree.name) tree + else finalize(tree, new BackquotedIdent(name)) + case tree: Ident if (name == tree.name) => tree + case _ => finalize(tree, untpd.Ident(name)) + } + def Select(tree: Tree, qualifier: Tree, name: Name)(implicit ctx: Context): Select = tree match { + case tree: SelectWithSig => + if ((qualifier eq tree.qualifier) && (name == tree.name) ) tree + else finalize(tree, new SelectWithSig(qualifier, name, tree.sig)) + case tree: Select if (qualifier eq tree.qualifier) && (name == tree.name) => tree + case _ => finalize(tree, untpd.Select(qualifier, name)) + } + def This(tree: Tree, qual: TypeName)(implicit ctx: Context): This = tree match { + case tree: This if (qual == tree.qual) => tree + case _ => finalize(tree, untpd.This(qual)) + } + def Super(tree: Tree, qual: Tree, mix: TypeName)(implicit ctx: Context): Super = tree match { + case tree: Super if (qual eq tree.qual) && (mix == tree.mix) => tree + case _ => finalize(tree, untpd.Super(qual, mix)) + } + def Apply(tree: Tree, fun: Tree, args: List[Tree])(implicit ctx: Context): Apply = tree match { + case tree: Apply if (fun eq tree.fun) && (args eq tree.args) => tree + case _ => finalize(tree, untpd.Apply(fun, args)) + } + def TypeApply(tree: Tree, fun: Tree, args: List[Tree])(implicit ctx: Context): TypeApply = tree match { + case tree: TypeApply if (fun eq tree.fun) && (args eq tree.args) => tree + case _ => inst.TypeApply(fun, args).withPos(tree) + } + def Literal(tree: Tree, const: Constant)(implicit ctx: Context): Literal = tree match { + case tree: Literal if (const == tree.const) => tree + case _ => finalize(tree, untpd.Literal(const)) + } + def New(tree: Tree, tpt: Tree)(implicit ctx: Context): New = tree match { + case tree: New if (tpt eq tree.tpt) => tree + case _ => finalize(tree, untpd.New(tpt)) + } + def Pair(tree: Tree, left: Tree, right: Tree)(implicit ctx: Context): Pair = tree match { + case tree: Pair if (left eq tree.left) && (right eq tree.right) => tree + case _ => finalize(tree, untpd.Pair(left, right)) + } + def Typed(tree: Tree, expr: Tree, tpt: Tree)(implicit ctx: Context): Typed = tree match { + case tree: Typed if (expr eq tree.expr) && (tpt eq tree.tpt) => tree + case _ => finalize(tree, untpd.Typed(expr, tpt)) + } + def NamedArg(tree: Tree, name: Name, arg: Tree)(implicit ctx: Context): NamedArg = tree match { + case tree: NamedArg if (name == tree.name) && (arg eq tree.arg) => tree + case _ => finalize(tree, untpd.NamedArg(name, arg)) + } + def Assign(tree: Tree, lhs: Tree, rhs: Tree)(implicit ctx: Context): Assign = tree match { + case tree: Assign if (lhs eq tree.lhs) && (rhs eq tree.rhs) => tree + case _ => finalize(tree, untpd.Assign(lhs, rhs)) + } + def Block(tree: Tree, stats: List[Tree], expr: Tree)(implicit ctx: Context): Block = tree match { + case tree: Block if (stats eq tree.stats) && (expr eq tree.expr) => tree + case _ => finalize(tree, untpd.Block(stats, expr)) + } + def If(tree: Tree, cond: Tree, thenp: Tree, elsep: Tree)(implicit ctx: Context): If = tree match { + case tree: If if (cond eq tree.cond) && (thenp eq tree.thenp) && (elsep eq tree.elsep) => tree + case _ => finalize(tree, untpd.If(cond, thenp, elsep)) + } + def Closure(tree: Tree, env: List[Tree], meth: RefTree)(implicit ctx: Context): Closure = tree match { + case tree: Closure if (env eq tree.env) && (meth eq tree.meth) => tree + case _ => finalize(tree, untpd.Closure(env, meth)) + } + def Match(tree: Tree, selector: Tree, cases: List[CaseDef])(implicit ctx: Context): Match = tree match { + case tree: Match if (selector eq tree.selector) && (cases eq tree.cases) => tree + case _ => finalize(tree, untpd.Match(selector, cases)) + } + def CaseDef(tree: Tree, pat: Tree, guard: Tree, body: Tree)(implicit ctx: Context): CaseDef = tree match { + case tree: CaseDef if (pat eq tree.pat) && (guard eq tree.guard) && (body eq tree.body) => tree + case _ => finalize(tree, untpd.CaseDef(pat, guard, body)) + } + def Return(tree: Tree, expr: Tree, from: Tree)(implicit ctx: Context): Return = tree match { + case tree: Return if (expr eq tree.expr) && (from eq tree.from) => tree + case _ => finalize(tree, untpd.Return(expr, from)) + } + def Try(tree: Tree, expr: Tree, handler: Tree, finalizer: Tree)(implicit ctx: Context): Try = tree match { + case tree: Try if (expr eq tree.expr) && (handler eq tree.handler) && (finalizer eq tree.finalizer) => tree + case _ => finalize(tree, untpd.Try(expr, handler, finalizer)) + } + def Throw(tree: Tree, expr: Tree)(implicit ctx: Context): Throw = tree match { + case tree: Throw if (expr eq tree.expr) => tree + case _ => finalize(tree, untpd.Throw(expr)) + } + def SeqLiteral(tree: Tree, elems: List[Tree])(implicit ctx: Context): SeqLiteral = tree match { + case tree: SeqLiteral if (elems eq tree.elems) => tree + case _ => finalize(tree, untpd.SeqLiteral(elems)) + } + def SingletonTypeTree(tree: Tree, ref: Tree)(implicit ctx: Context): SingletonTypeTree = tree match { + case tree: SingletonTypeTree if (ref eq tree.ref) => tree + case _ => finalize(tree, untpd.SingletonTypeTree(ref)) + } + def SelectFromTypeTree(tree: Tree, qualifier: Tree, name: Name)(implicit ctx: Context): SelectFromTypeTree = tree match { + case tree: SelectFromTypeTree if (qualifier eq tree.qualifier) && (name == tree.name) => tree + case _ => finalize(tree, untpd.SelectFromTypeTree(qualifier, name)) + } + def AndTypeTree(tree: Tree, left: Tree, right: Tree)(implicit ctx: Context): AndTypeTree = tree match { + case tree: AndTypeTree if (left eq tree.left) && (right eq tree.right) => tree + case _ => finalize(tree, untpd.AndTypeTree(left, right)) + } + def OrTypeTree(tree: Tree, left: Tree, right: Tree)(implicit ctx: Context): OrTypeTree = tree match { + case tree: OrTypeTree if (left eq tree.left) && (right eq tree.right) => tree + case _ => finalize(tree, untpd.OrTypeTree(left, right)) + } + def RefinedTypeTree(tree: Tree, tpt: Tree, refinements: List[Tree])(implicit ctx: Context): RefinedTypeTree = tree match { + case tree: RefinedTypeTree if (tpt eq tree.tpt) && (refinements eq tree.refinements) => tree + case _ => finalize(tree, untpd.RefinedTypeTree(tpt, refinements)) + } + def AppliedTypeTree(tree: Tree, tpt: Tree, args: List[Tree])(implicit ctx: Context): AppliedTypeTree = tree match { + case tree: AppliedTypeTree if (tpt eq tree.tpt) && (args eq tree.args) => tree + case _ => finalize(tree, untpd.AppliedTypeTree(tpt, args)) + } + def TypeBoundsTree(tree: Tree, lo: Tree, hi: Tree)(implicit ctx: Context): TypeBoundsTree = tree match { + case tree: TypeBoundsTree if (lo eq tree.lo) && (hi eq tree.hi) => tree + case _ => finalize(tree, untpd.TypeBoundsTree(lo, hi)) + } + def Bind(tree: Tree, name: Name, body: Tree)(implicit ctx: Context): Bind = tree match { + case tree: Bind if (name eq tree.name) && (body eq tree.body) => tree + case _ => finalize(tree, untpd.Bind(name, body)) + } + def Alternative(tree: Tree, trees: List[Tree])(implicit ctx: Context): Alternative = tree match { + case tree: Alternative if (trees eq tree.trees) => tree + case _ => finalize(tree, untpd.Alternative(trees)) + } + def UnApply(tree: Tree, fun: Tree, args: List[Tree])(implicit ctx: Context): UnApply = tree match { + case tree: UnApply if (fun eq tree.fun) && (args eq tree.args) => tree + case _ => finalize(tree, untpd.UnApply(fun, args)) + } + def ValDef(tree: Tree, mods: Modifiers, name: TermName, tpt: Tree, rhs: Tree)(implicit ctx: Context): ValDef = tree match { + case tree: ValDef if (mods == tree.mods) && (name == tree.name) && (tpt eq tree.tpt) && (rhs eq tree.rhs) => tree + case _ => finalize(tree, untpd.ValDef(mods, name, tpt, rhs)) + } + def DefDef(tree: Tree, mods: Modifiers, name: TermName, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree)(implicit ctx: Context): DefDef = tree match { + case tree: DefDef if (mods == tree.mods) && (name == tree.name) && (tparams eq tree.tparams) && (vparamss eq tree.vparamss) && (tpt eq tree.tpt) && (rhs eq tree.rhs) => tree + case _ => finalize(tree, untpd.DefDef(mods, name, tparams, vparamss, tpt, rhs)) + } + def TypeDef(tree: Tree, mods: Modifiers, name: TypeName, rhs: Tree, tparams: List[untpd.TypeDef] = Nil)(implicit ctx: Context): TypeDef = tree match { + case tree: TypeDef if (mods == tree.mods) && (name == tree.name) && (rhs eq tree.rhs) && (tparams eq tree.tparams) => tree + case _ => finalize(tree, untpd.TypeDef(mods, name, tparams, rhs)) + } + def Template(tree: Tree, constr: DefDef, parents: List[Tree], self: ValDef, body: List[Tree])(implicit ctx: Context): Template = tree match { + case tree: Template if (constr eq tree.constr) && (parents eq tree.parents) && (self eq tree.self) && (body eq tree.body) => tree + case _ => finalize(tree, untpd.Template(constr, parents, self, body)) + } + def Import(tree: Tree, expr: Tree, selectors: List[untpd.Tree])(implicit ctx: Context): Import = tree match { + case tree: Import if (expr eq tree.expr) && (selectors eq tree.selectors) => tree + case _ => finalize(tree, untpd.Import(expr, selectors)) + } + def PackageDef(tree: Tree, pid: RefTree, stats: List[Tree])(implicit ctx: Context): PackageDef = tree match { + case tree: PackageDef if (pid eq tree.pid) && (stats eq tree.stats) => tree + case _ => finalize(tree, untpd.PackageDef(pid, stats)) + } + def Annotated(tree: Tree, annot: Tree, arg: Tree)(implicit ctx: Context): Annotated = tree match { + case tree: Annotated if (annot eq tree.annot) && (arg eq tree.arg) => tree + case _ => finalize(tree, untpd.Annotated(annot, arg)) + } + def SharedTree(tree: Tree, shared: Tree)(implicit ctx: Context): SharedTree = tree match { + case tree: SharedTree if (shared eq tree.shared) => tree + case _ => finalize(tree, untpd.SharedTree(shared)) + } + def Thicket(tree: Tree, trees: List[Tree])(implicit ctx: Context): Thicket = tree match { + case tree: Thicket if (trees eq tree.trees) => tree + case _ => finalize(tree, untpd.Thicket(trees)) + } } - def derivedPackageDef(pid: RefTree[T], stats: List[Tree[T]]): PackageDef[T] = tree match { - case tree: PackageDef[_] if (pid eq tree.pid) && (stats eq tree.stats) => tree - case _ => PackageDef(pid, stats).withPos(tree.pos) + + abstract class TreeTransformer(val cpy: TreeCopier = inst.cpy) { + var sharedMemo: Map[SharedTree, SharedTree] = Map() + + def transform(tree: Tree)(implicit ctx: Context): Tree = tree match { + case Ident(name) => + tree + case Select(qualifier, name) => + cpy.Select(tree, transform(qualifier), name) + case This(qual) => + tree + case Super(qual, mix) => + cpy.Super(tree, transform(qual), mix) + case Apply(fun, args) => + cpy.Apply(tree, transform(fun), transform(args)) + case TypeApply(fun, args) => + cpy.TypeApply(tree, transform(fun), transform(args)) + case Literal(const) => + tree + case New(tpt) => + cpy.New(tree, transform(tpt)) + case Pair(left, right) => + cpy.Pair(tree, transform(left), transform(right)) + case Typed(expr, tpt) => + cpy.Typed(tree, transform(expr), transform(tpt)) + case NamedArg(name, arg) => + cpy.NamedArg(tree, name, transform(arg)) + case Assign(lhs, rhs) => + cpy.Assign(tree, transform(lhs), transform(rhs)) + case Block(stats, expr) => + cpy.Block(tree, transformStats(stats), transform(expr)) + case If(cond, thenp, elsep) => + cpy.If(tree, transform(cond), transform(thenp), transform(elsep)) + case Closure(env, meth) => + cpy.Closure(tree, transform(env), transformSub(meth)) + case Match(selector, cases) => + cpy.Match(tree, transform(selector), transformSub(cases)) + case CaseDef(pat, guard, body) => + cpy.CaseDef(tree, transform(pat), transform(guard), transform(body)) + case Return(expr, from) => + cpy.Return(tree, transform(expr), transformSub(from)) + case Try(block, handler, finalizer) => + cpy.Try(tree, transform(block), transform(handler), transform(finalizer)) + case Throw(expr) => + cpy.Throw(tree, transform(expr)) + case SeqLiteral(elems) => + cpy.SeqLiteral(tree, transform(elems)) + case TypeTree(original) => + tree + case SingletonTypeTree(ref) => + cpy.SingletonTypeTree(tree, transform(ref)) + case SelectFromTypeTree(qualifier, name) => + cpy.SelectFromTypeTree(tree, transform(qualifier), name) + case AndTypeTree(left, right) => + cpy.AndTypeTree(tree, transform(left), transform(right)) + case OrTypeTree(left, right) => + cpy.OrTypeTree(tree, transform(left), transform(right)) + case RefinedTypeTree(tpt, refinements) => + cpy.RefinedTypeTree(tree, transform(tpt), transformSub(refinements)) + case AppliedTypeTree(tpt, args) => + cpy.AppliedTypeTree(tree, transform(tpt), transform(args)) + case TypeBoundsTree(lo, hi) => + cpy.TypeBoundsTree(tree, transform(lo), transform(hi)) + case Bind(name, body) => + cpy.Bind(tree, name, transform(body)) + case Alternative(trees) => + cpy.Alternative(tree, transform(trees)) + case UnApply(fun, args) => + cpy.UnApply(tree, transform(fun), transform(args)) + case ValDef(mods, name, tpt, rhs) => + cpy.ValDef(tree, mods, name, transform(tpt), transform(rhs)) + case DefDef(mods, name, tparams, vparamss, tpt, rhs) => + cpy.DefDef(tree, mods, name, transformSub(tparams), vparamss mapConserve (transformSub(_)), transform(tpt), transform(rhs)) + case tree @ TypeDef(mods, name, rhs) => + cpy.TypeDef(tree, mods, name, transform(rhs), tree.tparams) + case Template(constr, parents, self, body) => + cpy.Template(tree, transformSub(constr), transform(parents), transformSub(self), transformStats(body)) + case Import(expr, selectors) => + cpy.Import(tree, transform(expr), selectors) + case PackageDef(pid, stats) => + cpy.PackageDef(tree, transformSub(pid), transformStats(stats)) + case Annotated(annot, arg) => + cpy.Annotated(tree, transform(annot), transform(arg)) + case Thicket(trees) => + val trees1 = transform(trees) + if (trees1 eq trees) tree else Thicket(trees1) + case tree @ SharedTree(shared) => + sharedMemo get tree match { + case Some(tree1) => tree1 + case None => + val tree1 = cpy.SharedTree(tree, transform(shared)) + sharedMemo = sharedMemo.updated(tree, tree1) + tree1 + } + } + def transformStats(trees: List[Tree])(implicit ctx: Context): List[Tree] = + transform(trees) + def transform(trees: List[Tree])(implicit ctx: Context): List[Tree] = + flatten(trees mapConserve (transform(_))) + def transformSub[Tr <: Tree](tree: Tr)(implicit ctx: Context): Tr = + transform(tree).asInstanceOf[Tr] + def transformSub[Tr <: Tree](trees: List[Tr])(implicit ctx: Context): List[Tr] = + transform(trees).asInstanceOf[List[Tr]] } - def derivedAnnotated(annot: Tree[T], arg: Tree[T]): Annotated[T] = tree match { - case tree: Annotated[_] if (annot eq tree.annot) && (arg eq tree.arg) => tree - case _ => Annotated(annot, arg).withPos(tree.pos) + + abstract class TreeAccumulator[X] extends ((X, Tree) => X) { + var sharedMemo: Map[SharedTree, X] = Map() + def apply(x: X, tree: Tree): X + def apply(x: X, trees: Traversable[Tree]): X = (x /: trees)(apply) + def foldOver(x: X, tree: Tree): X = tree match { + case Ident(name) => + x + case Select(qualifier, name) => + this(x, qualifier) + case This(qual) => + x + case Super(qual, mix) => + this(x, qual) + case Apply(fun, args) => + this(this(x, fun), args) + case TypeApply(fun, args) => + this(this(x, fun), args) + case Literal(const) => + x + case New(tpt) => + this(x, tpt) + case Pair(left, right) => + this(this(x, left), right) + case Typed(expr, tpt) => + this(this(x, expr), tpt) + case NamedArg(name, arg) => + this(x, arg) + case Assign(lhs, rhs) => + this(this(x, lhs), rhs) + case Block(stats, expr) => + this(this(x, stats), expr) + case If(cond, thenp, elsep) => + this(this(this(x, cond), thenp), elsep) + case Closure(env, meth) => + this(this(x, env), meth) + case Match(selector, cases) => + this(this(x, selector), cases) + case CaseDef(pat, guard, body) => + this(this(this(x, pat), guard), body) + case Return(expr, from) => + this(this(x, expr), from) + case Try(block, handler, finalizer) => + this(this(this(x, block), handler), finalizer) + case Throw(expr) => + this(x, expr) + case SeqLiteral(elems) => + this(x, elems) + case TypeTree(original) => + x + case SingletonTypeTree(ref) => + this(x, ref) + case SelectFromTypeTree(qualifier, name) => + this(x, qualifier) + case AndTypeTree(left, right) => + this(this(x, left), right) + case OrTypeTree(left, right) => + this(this(x, left), right) + case RefinedTypeTree(tpt, refinements) => + this(this(x, tpt), refinements) + case AppliedTypeTree(tpt, args) => + this(this(x, tpt), args) + case TypeBoundsTree(lo, hi) => + this(this(x, lo), hi) + case Bind(name, body) => + this(x, body) + case Alternative(trees) => + this(x, trees) + case UnApply(fun, args) => + this(this(x, fun), args) + case ValDef(mods, name, tpt, rhs) => + this(this(x, tpt), rhs) + case DefDef(mods, name, tparams, vparamss, tpt, rhs) => + this(this((this(x, tparams) /: vparamss)(apply), tpt), rhs) + case TypeDef(mods, name, rhs) => + this(x, rhs) + case Template(constr, parents, self, body) => + this(this(this(this(x, constr), parents), self), body) + case Import(expr, selectors) => + this(x, expr) + case PackageDef(pid, stats) => + this(this(x, pid), stats) + case Annotated(annot, arg) => + this(this(x, annot), arg) + case Thicket(ts) => + this(x, ts) + case tree @ SharedTree(shared) => + sharedMemo get tree match { + case Some(x1) => x1 + case None => + val x1 = this(x, shared) + sharedMemo = sharedMemo.updated(tree, x1) + x1 + } + } } - def derivedSharedTree(shared: Tree[T]): SharedTree[T] = tree match { - case tree: SharedTree[_] if (shared eq tree.shared) => tree - case _ => SharedTree(shared).withPos(tree.pos) + + /** Fold `f` over all tree nodes, in depth-first, prefix order */ + class DeepFolder[X](f: (X, Tree) => X) extends TreeAccumulator[X] { + def apply(x: X, tree: Tree): X = foldOver(f(x, tree), tree) } - def derivedThicket(trees: List[Tree[T]]): Thicket[T] = tree match { - case tree: Thicket[_] if (trees eq tree.trees) => tree - case _ => Thicket(trees).withPos(tree.pos) + + /** Fold `f` over all tree nodes, in depth-first, prefix order, but don't visit + * subtrees where `f` returns a different result for the root, i.e. `f(x, root) ne x`. + */ + class ShallowFolder[X](f: (X, Tree) => X) extends TreeAccumulator[X] { + def apply(x: X, tree: Tree): X = { + val x1 = f(x, tree) + if (x1.asInstanceOf[AnyRef] ne x1.asInstanceOf[AnyRef]) x1 + else foldOver(x1, tree) + } } } +} + // ----- Helper functions and classes --------------------------------------- +/* abstract class FullTreeTransformer[T >: Untyped, C] { var sharedMemo: Map[SharedTree[T], SharedTree[T]] = Map() @@ -1068,250 +1381,5 @@ object Trees { def finishEmptyTree(tree: Tree[T], old: Tree[T], c: C, plugins: Plugins) = tree def finishSharedTree(tree: Tree[T], old: Tree[T], c: C, plugins: Plugins) = tree } +*/ - def flatten[T >: Untyped](trees: List[Tree[T]]): List[Tree[T]] = { - var buf: ListBuffer[Tree[T]] = null - def add(tree: Tree[T]) = { - assert(!tree.isInstanceOf[Thicket[_]]) - buf += tree - } - var xs = trees - while (xs.nonEmpty) { - xs.head match { - case Thicket(elems) => - if (buf == null) { - buf = new ListBuffer - var ys = trees - while (ys ne xs) { - buf += ys.head - ys = ys.tail - } - } - for (elem <- elems) { - assert(!elem.isInstanceOf[Thicket[_]]) - buf += elem - } - case tree => - if (buf != null) buf += tree - } - xs = xs.tail - } - if (buf != null) buf.toList else trees - } - - abstract class TreeTransformer[T >: Untyped] { - var sharedMemo: Map[SharedTree[T], SharedTree[T]] = Map() - - def transform(tree: Tree[T]): Tree[T] = tree match { - case Ident(name) => - tree - case Select(qualifier, name) => - tree.derivedSelect(transform(qualifier), name) - case This(qual) => - tree - case Super(qual, mix) => - tree.derivedSuper(transform(qual), mix) - case Apply(fun, args) => - tree.derivedApply(transform(fun), transform(args)) - case TypeApply(fun, args) => - tree.derivedTypeApply(transform(fun), transform(args)) - case Literal(const) => - tree - case New(tpt) => - tree.derivedNew(transform(tpt)) - case Pair(left, right) => - tree.derivedPair(transform(left), transform(right)) - case Typed(expr, tpt) => - tree.derivedTyped(transform(expr), transform(tpt)) - case NamedArg(name, arg) => - tree.derivedNamedArg(name, transform(arg)) - case Assign(lhs, rhs) => - tree.derivedAssign(transform(lhs), transform(rhs)) - case Block(stats, expr) => - tree.derivedBlock(transformStats(stats), transform(expr)) - case If(cond, thenp, elsep) => - tree.derivedIf(transform(cond), transform(thenp), transform(elsep)) - case Closure(env, meth) => - tree.derivedClosure(transform(env), transformSub(meth)) - case Match(selector, cases) => - tree.derivedMatch(transform(selector), transformSub(cases)) - case CaseDef(pat, guard, body) => - tree.derivedCaseDef(transform(pat), transform(guard), transform(body)) - case Return(expr, from) => - tree.derivedReturn(transform(expr), transformSub(from)) - case Try(block, handler, finalizer) => - tree.derivedTry(transform(block), transform(handler), transform(finalizer)) - case Throw(expr) => - tree.derivedThrow(transform(expr)) - case SeqLiteral(elems) => - tree.derivedSeqLiteral(transform(elems)) - case TypeTree(original) => - tree - case SingletonTypeTree(ref) => - tree.derivedSingletonTypeTree(transform(ref)) - case SelectFromTypeTree(qualifier, name) => - tree.derivedSelectFromTypeTree(transform(qualifier), name) - case AndTypeTree(left, right) => - tree.derivedAndTypeTree(transform(left), transform(right)) - case OrTypeTree(left, right) => - tree.derivedOrTypeTree(transform(left), transform(right)) - case RefinedTypeTree(tpt, refinements) => - tree.derivedRefinedTypeTree(transform(tpt), transformSub(refinements)) - case AppliedTypeTree(tpt, args) => - tree.derivedAppliedTypeTree(transform(tpt), transform(args)) - case TypeBoundsTree(lo, hi) => - tree.derivedTypeBoundsTree(transform(lo), transform(hi)) - case Bind(name, body) => - tree.derivedBind(name, transform(body)) - case Alternative(trees) => - tree.derivedAlternative(transform(trees)) - case UnApply(fun, args) => - tree.derivedUnApply(transform(fun), transform(args)) - case ValDef(mods, name, tpt, rhs) => - tree.derivedValDef(mods, name, transform(tpt), transform(rhs)) - case DefDef(mods, name, tparams, vparamss, tpt, rhs) => - tree.derivedDefDef(mods, name, transformSub(tparams), vparamss mapConserve (transformSub(_)), transform(tpt), transform(rhs)) - case tree @ TypeDef(mods, name, rhs) => - tree.derivedTypeDef(mods, name, transform(rhs), tree.tparams) - case Template(constr, parents, self, body) => - tree.derivedTemplate(transformSub(constr), transform(parents), transformSub(self), transformStats(body)) - case Import(expr, selectors) => - tree.derivedImport(transform(expr), selectors) - case PackageDef(pid, stats) => - tree.derivedPackageDef(transformSub(pid), transformStats(stats)) - case Annotated(annot, arg) => - tree.derivedAnnotated(transform(annot), transform(arg)) - case Thicket(trees) => - val trees1 = transform(trees) - if (trees1 eq trees) tree else Thicket(trees1) - case tree @ SharedTree(shared) => - sharedMemo get tree match { - case Some(tree1) => tree1 - case None => - val tree1 = tree.derivedSharedTree(transform(shared)) - sharedMemo = sharedMemo.updated(tree, tree1) - tree1 - } - } - def transformStats(trees: List[Tree[T]]): List[Tree[T]] = - transform(trees) - def transform(trees: List[Tree[T]]): List[Tree[T]] = - flatten(trees mapConserve (transform(_))) - def transformSub(tree: Tree[T]): tree.ThisTree[T] = - transform(tree).asInstanceOf[tree.ThisTree[T]] - def transformSub[TT <: Tree[T]](trees: List[TT]): List[TT] = - transform(trees).asInstanceOf[List[TT]] - } - - abstract class TreeAccumulator[X, T >: Untyped] extends ((X, Tree[T]) => X) { - var sharedMemo: Map[SharedTree[T], X] = Map() - def apply(x: X, tree: Tree[T]): X - def apply(x: X, trees: Traversable[Tree[T]]): X = (x /: trees)(apply) - def foldOver(x: X, tree: Tree[T]): X = tree match { - case Ident(name) => - x - case Select(qualifier, name) => - this(x, qualifier) - case This(qual) => - x - case Super(qual, mix) => - this(x, qual) - case Apply(fun, args) => - this(this(x, fun), args) - case TypeApply(fun, args) => - this(this(x, fun), args) - case Literal(const) => - x - case New(tpt) => - this(x, tpt) - case Pair(left, right) => - this(this(x, left), right) - case Typed(expr, tpt) => - this(this(x, expr), tpt) - case NamedArg(name, arg) => - this(x, arg) - case Assign(lhs, rhs) => - this(this(x, lhs), rhs) - case Block(stats, expr) => - this(this(x, stats), expr) - case If(cond, thenp, elsep) => - this(this(this(x, cond), thenp), elsep) - case Closure(env, meth) => - this(this(x, env), meth) - case Match(selector, cases) => - this(this(x, selector), cases) - case CaseDef(pat, guard, body) => - this(this(this(x, pat), guard), body) - case Return(expr, from) => - this(this(x, expr), from) - case Try(block, handler, finalizer) => - this(this(this(x, block), handler), finalizer) - case Throw(expr) => - this(x, expr) - case SeqLiteral(elems) => - this(x, elems) - case TypeTree(original) => - x - case SingletonTypeTree(ref) => - this(x, ref) - case SelectFromTypeTree(qualifier, name) => - this(x, qualifier) - case AndTypeTree(left, right) => - this(this(x, left), right) - case OrTypeTree(left, right) => - this(this(x, left), right) - case RefinedTypeTree(tpt, refinements) => - this(this(x, tpt), refinements) - case AppliedTypeTree(tpt, args) => - this(this(x, tpt), args) - case TypeBoundsTree(lo, hi) => - this(this(x, lo), hi) - case Bind(name, body) => - this(x, body) - case Alternative(trees) => - this(x, trees) - case UnApply(fun, args) => - this(this(x, fun), args) - case ValDef(mods, name, tpt, rhs) => - this(this(x, tpt), rhs) - case DefDef(mods, name, tparams, vparamss, tpt, rhs) => - this(this((this(x, tparams) /: vparamss)(apply), tpt), rhs) - case TypeDef(mods, name, rhs) => - this(x, rhs) - case Template(constr, parents, self, body) => - this(this(this(this(x, constr), parents), self), body) - case Import(expr, selectors) => - this(x, expr) - case PackageDef(pid, stats) => - this(this(x, pid), stats) - case Annotated(annot, arg) => - this(this(x, annot), arg) - case Thicket(ts) => - this(x, ts) - case tree @ SharedTree(shared) => - sharedMemo get tree match { - case Some(x1) => x1 - case None => - val x1 = this(x, shared) - sharedMemo = sharedMemo.updated(tree, x1) - x1 - } - } - } - - /** Fold `f` over all tree nodes, in depth-first, prefix order */ - class DeepFolder[X, T >: Untyped](f: (X, Tree[T]) => X) extends TreeAccumulator[X, T] { - def apply(x: X, tree: Tree[T]): X = foldOver(f(x, tree), tree) - } - - /** Fold `f` over all tree nodes, in depth-first, prefix order, but don't visit - * subtrees where `f` returns a different result for the root, i.e. `f(x, root) ne x`. - */ - class ShallowFolder[X, T >: Untyped](f: (X, Tree[T]) => X) extends TreeAccumulator[X, T] { - def apply(x: X, tree: Tree[T]): X = { - val x1 = f(x, tree) - if (x1.asInstanceOf[AnyRef] ne x1.asInstanceOf[AnyRef]) x1 - else foldOver(x1, tree) - } - } -} |