diff options
Diffstat (limited to 'src/compiler/scala/reflect/internal/Trees.scala')
-rw-r--r-- | src/compiler/scala/reflect/internal/Trees.scala | 1325 |
1 files changed, 1241 insertions, 84 deletions
diff --git a/src/compiler/scala/reflect/internal/Trees.scala b/src/compiler/scala/reflect/internal/Trees.scala index 3e7f23800c..11d0790100 100644 --- a/src/compiler/scala/reflect/internal/Trees.scala +++ b/src/compiler/scala/reflect/internal/Trees.scala @@ -7,10 +7,808 @@ package scala.reflect package internal import Flags._ -import api.Modifier +import base.Attachments +import collection.mutable.{ListBuffer, LinkedHashSet} trait Trees extends api.Trees { self: SymbolTable => + private[scala] var nodeCount = 0 + + abstract class Tree extends TreeContextApiImpl with Product { + val id = nodeCount // TODO: add to attachment? + nodeCount += 1 + + @inline final def pos: Position = rawatt.pos + def pos_=(pos: Position): Unit = rawatt = (rawatt withPos pos) + def setPos(newpos: Position): this.type = { pos = newpos; this } + + private var rawatt: Attachments { type Pos = Position } = NoPosition + def attachments = rawatt + def addAttachment(attachment: Any): this.type = { rawatt = rawatt.add(attachment); this } + def removeAttachment[T: ClassTag]: this.type = { rawatt = rawatt.remove[T]; this } + + private[this] var rawtpe: Type = _ + @inline final def tpe = rawtpe + def tpe_=(t: Type) = rawtpe = t + def setType(tp: Type): this.type = { rawtpe = tp; this } + def defineType(tp: Type): this.type = setType(tp) + + def symbol: Symbol = null + def symbol_=(sym: Symbol) { throw new UnsupportedOperationException("symbol_= inapplicable for " + this) } + def setSymbol(sym: Symbol): this.type = { symbol = sym; this } + def hasSymbol = false + + def isDef = false + + def isEmpty = false + + /** The canonical way to test if a Tree represents a term. + */ + def isTerm: Boolean = this match { + case _: TermTree => true + case Bind(name, _) => name.isTermName + case Select(_, name) => name.isTermName + case Ident(name) => name.isTermName + case Annotated(_, arg) => arg.isTerm + case _ => false + } + + /** The canonical way to test if a Tree represents a type. + */ + def isType: Boolean = this match { + case _: TypTree => true + case Bind(name, _) => name.isTypeName + case Select(_, name) => name.isTypeName + case Ident(name) => name.isTypeName + case Annotated(_, arg) => arg.isType + case _ => false + } + + private[scala] def copyAttrs(tree: Tree): this.type = { + rawatt = tree.rawatt + tpe = tree.tpe + if (hasSymbol) symbol = tree.symbol + this + } + + override def hashCode(): Int = System.identityHashCode(this) + override def equals(that: Any) = this eq that.asInstanceOf[AnyRef] + + override def duplicate: this.type = + (duplicator transform this).asInstanceOf[this.type] + } + + abstract class TreeContextApiImpl extends TreeContextApi { this: Tree => + + override def orElse(alt: => Tree) = if (!isEmpty) this else alt + + override def foreach(f: Tree => Unit) { new ForeachTreeTraverser(f).traverse(this) } + + override def withFilter(f: Tree => Boolean): List[Tree] = { + val ft = new FilterTreeTraverser(f) + ft.traverse(this) + ft.hits.toList + } + + override def filter(f: Tree => Boolean): List[Tree] = withFilter(f) + + override def collect[T](pf: PartialFunction[Tree, T]): List[T] = { + val ctt = new CollectTreeTraverser[T](pf) + ctt.traverse(this) + ctt.results.toList + } + + override def find(p: Tree => Boolean): Option[Tree] = { + val ft = new FindTreeTraverser(p) + ft.traverse(this) + ft.result + } + + override def exists(p: Tree => Boolean): Boolean = !find(p).isEmpty + + override def forAll(p: Tree => Boolean): Boolean = find(!p(_)).isEmpty + + override def equalsStructure(that : Tree) = correspondsStructure(that)(_ eq _) + + def correspondsStructure(that: Tree)(f: (Tree,Tree) => Boolean): Boolean = + f(this, that) || ((productArity == that.productArity) && { + def equals0(this0: Any, that0: Any): Boolean = (this0, that0) match { + case (x: Tree, y: Tree) => f(x, y) || (x correspondsStructure y)(f) + case (xs: List[_], ys: List[_]) => (xs corresponds ys)(equals0) + case _ => this0 == that0 + } + def compareOriginals() = (this, that) match { + case (x: TypeTree, y: TypeTree) if x.original != null && y.original != null => + (x.original correspondsStructure y.original)(f) + case _ => + true + } + + (productIterator zip that.productIterator forall { case (x, y) => equals0(x, y) }) && compareOriginals() + }) + + override def children: List[Tree] = { + def subtrees(x: Any): List[Tree] = x match { + case EmptyTree => Nil + case t: Tree => List(t) + case xs: List[_] => xs flatMap subtrees + case _ => Nil + } + productIterator.toList flatMap subtrees + } + + override def freeTerms: List[FreeTermSymbol] = freeSyms[FreeTermSymbol](_.isFreeTerm, _.termSymbol) + override def freeTypes: List[FreeTypeSymbol] = freeSyms[FreeTypeSymbol](_.isFreeType, _.typeSymbol) + + private def freeSyms[S <: Symbol](isFree: Symbol => Boolean, symOfType: Type => Symbol): List[S] = { + val s = collection.mutable.LinkedHashSet[S]() + def addIfFree(sym: Symbol): Unit = if (sym != null && isFree(sym)) s += sym.asInstanceOf[S] + for (t <- this) { + addIfFree(t.symbol) + if (t.tpe != null) { + for (tp <- t.tpe) { + addIfFree(symOfType(tp)) + } + } + } + s.toList + } + + override def substituteSymbols(from: List[Symbol], to: List[Symbol]): Tree = + new TreeSymSubstituter(from, to)(this) + + override def substituteTypes(from: List[Symbol], to: List[Type]): Tree = + new TreeTypeSubstituter(from, to)(this) + + override def substituteThis(clazz: Symbol, to: Tree): Tree = + new ThisSubstituter(clazz, to) transform this + + def hasSymbolWhich(f: Symbol => Boolean) = + hasSymbol && symbol != null && f(symbol) + + def isErroneous = (tpe ne null) && tpe.isErroneous + def isTyped = (tpe ne null) && !tpe.isErroneous + + /** Sets the tree's type to the result of the given function. + * If the type is null, it remains null - the function is not called. + */ + def modifyType(f: Type => Type): Tree = + if (tpe eq null) this + else this setType f(tpe) + + /** If `pf` is defined for a given subtree, call super.traverse(pf(tree)), + * otherwise super.traverse(tree). + */ + def foreachPartial(pf: PartialFunction[Tree, Tree]) { + new ForeachPartialTreeTraverser(pf).traverse(this) + } + + def changeOwner(pairs: (Symbol, Symbol)*): Tree = { + pairs.foldLeft(this) { case (t, (oldOwner, newOwner)) => + new ChangeOwnerTraverser(oldOwner, newOwner) apply t + } + } + + def shallowDuplicate: Tree = new ShallowDuplicator(this) transform this + def shortClass: String = (getClass.getName split "[.$]").last + + def isErrorTyped = (tpe ne null) && tpe.isError + + /** When you want to know a little more than the class, but a lot + * less than the whole tree. + */ + def summaryString: String = this match { + case Literal(const) => "Literal(" + const + ")" + case Ident(name) => "Ident(%s)".format(name.decode) + case Select(qual, name) => "Select(%s, %s)".format(qual.summaryString, name.decode) + case t: NameTree => t.name.longString + case t => + t.shortClass + ( + if (t.symbol != null && t.symbol != NoSymbol) "(" + t.symbol + ")" + else "" + ) + } + } + + trait TermTree extends Tree with TermTreeApi + + trait TypTree extends Tree with TypTreeApi + + trait SymTree extends Tree with SymTreeContextApi { + override def hasSymbol = true + override var symbol: Symbol = NoSymbol + } + + trait NameTree extends Tree with NameTreeApi { + def name: Name + } + + trait RefTree extends SymTree with NameTree with RefTreeApi { + def qualifier: Tree // empty for Idents + def name: Name + } + + abstract class DefTree extends SymTree with NameTree with DefTreeApi { + def name: Name + override def isDef = true + } + + case object EmptyTree extends TermTree { + super.tpe_=(NoType) + override def tpe_=(t: Type) = + if (t != NoType) throw new UnsupportedOperationException("tpe_=("+t+") inapplicable for <empty>") + override def isEmpty = true + } + + abstract class MemberDef extends DefTree with MemberDefApi { + def mods: Modifiers + def keyword: String = this match { + case TypeDef(_, _, _, _) => "type" + case ClassDef(mods, _, _, _) => if (mods hasFlag TRAIT) "trait" else "class" + case DefDef(_, _, _, _, _, _) => "def" + case ModuleDef(_, _, _) => "object" + case PackageDef(_, _) => "package" + case ValDef(mods, _, _, _) => if (mods hasFlag MUTABLE) "var" else "val" + case _ => "" + } + } + + case class PackageDef(pid: RefTree, stats: List[Tree]) + extends MemberDef with PackageDefApi { + def name = pid.name + def mods = NoMods + } + object PackageDef extends PackageDefExtractor + + abstract class ImplDef extends MemberDef with ImplDefApi { + def impl: Template + } + + case class ClassDef(mods: Modifiers, name: TypeName, tparams: List[TypeDef], impl: Template) + extends ImplDef with ClassDefApi + object ClassDef extends ClassDefExtractor + + case class ModuleDef(mods: Modifiers, name: TermName, impl: Template) + extends ImplDef with ModuleDefApi + object ModuleDef extends ModuleDefExtractor + + abstract class ValOrDefDef extends MemberDef with ValOrDefDefApi { + def name: Name + def tpt: Tree + def rhs: Tree + } + + case class ValDef(mods: Modifiers, name: TermName, tpt: Tree, rhs: Tree) extends ValOrDefDef with ValDefApi + object ValDef extends ValDefExtractor + + case class DefDef(mods: Modifiers, name: Name, tparams: List[TypeDef], + vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree) extends ValOrDefDef with DefDefApi + object DefDef extends DefDefExtractor + + case class TypeDef(mods: Modifiers, name: TypeName, tparams: List[TypeDef], rhs: Tree) + extends MemberDef with TypeDefApi + object TypeDef extends TypeDefExtractor + + case class LabelDef(name: TermName, params: List[Ident], rhs: Tree) + extends DefTree with TermTree with LabelDefApi + object LabelDef extends LabelDefExtractor + + case class ImportSelector(name: Name, namePos: Int, rename: Name, renamePos: Int) extends ImportSelectorApi + object ImportSelector extends ImportSelectorExtractor + + case class Import(expr: Tree, selectors: List[ImportSelector]) + extends SymTree with ImportApi + object Import extends ImportExtractor + + case class Template(parents: List[Tree], self: ValDef, body: List[Tree]) + extends SymTree with TemplateApi + object Template extends TemplateExtractor + + case class Block(stats: List[Tree], expr: Tree) + extends TermTree with BlockApi + object Block extends BlockExtractor + + case class CaseDef(pat: Tree, guard: Tree, body: Tree) + extends Tree with CaseDefApi + object CaseDef extends CaseDefExtractor + + case class Alternative(trees: List[Tree]) + extends TermTree with AlternativeApi + object Alternative extends AlternativeExtractor + + case class Star(elem: Tree) + extends TermTree with StarApi + object Star extends StarExtractor + + case class Bind(name: Name, body: Tree) + extends DefTree with BindApi + object Bind extends BindExtractor + + case class UnApply(fun: Tree, args: List[Tree]) + extends TermTree with UnApplyApi + object UnApply extends UnApplyExtractor + + case class ArrayValue(elemtpt: Tree, elems: List[Tree]) + extends TermTree with ArrayValueApi + object ArrayValue extends ArrayValueExtractor + + case class Function(vparams: List[ValDef], body: Tree) + extends TermTree with SymTree with FunctionApi + object Function extends FunctionExtractor + + case class Assign(lhs: Tree, rhs: Tree) + extends TermTree with AssignApi + object Assign extends AssignExtractor + + case class AssignOrNamedArg(lhs: Tree, rhs: Tree) + extends TermTree with AssignOrNamedArgApi + object AssignOrNamedArg extends AssignOrNamedArgExtractor + + case class If(cond: Tree, thenp: Tree, elsep: Tree) + extends TermTree with IfApi + object If extends IfExtractor + + case class Match(selector: Tree, cases: List[CaseDef]) + extends TermTree with MatchApi + object Match extends MatchExtractor + + case class Return(expr: Tree) + extends TermTree with SymTree with ReturnApi + object Return extends ReturnExtractor + + case class Try(block: Tree, catches: List[CaseDef], finalizer: Tree) + extends TermTree with TryApi + object Try extends TryExtractor + + case class Throw(expr: Tree) + extends TermTree with ThrowApi + object Throw extends ThrowExtractor + + case class New(tpt: Tree) extends TermTree with NewApi + object New extends NewExtractor + + case class Typed(expr: Tree, tpt: Tree) + extends TermTree with TypedApi + object Typed extends TypedExtractor + + abstract class GenericApply extends TermTree with GenericApplyApi { + val fun: Tree + val args: List[Tree] + } + + case class TypeApply(fun: Tree, args: List[Tree]) + extends GenericApply with TypeApplyApi { + override def symbol: Symbol = fun.symbol + override def symbol_=(sym: Symbol) { fun.symbol = sym } + } + object TypeApply extends TypeApplyExtractor + + case class Apply(fun: Tree, args: List[Tree]) + extends GenericApply with ApplyApi { + override def symbol: Symbol = fun.symbol + override def symbol_=(sym: Symbol) { fun.symbol = sym } + } + object Apply extends ApplyExtractor + + // TODO remove this class, add a tree attachment to Apply to track whether implicits were involved + // copying trees will all too easily forget to distinguish subclasses + class ApplyToImplicitArgs(fun: Tree, args: List[Tree]) extends Apply(fun, args) + + // TODO remove this class, add a tree attachment to Apply to track whether implicits were involved + // copying trees will all too easily forget to distinguish subclasses + class ApplyImplicitView(fun: Tree, args: List[Tree]) extends Apply(fun, args) + + def ApplyConstructor(tpt: Tree, args: List[Tree]) = Apply(Select(New(tpt), nme.CONSTRUCTOR), args) + + case class ApplyDynamic(qual: Tree, args: List[Tree]) + extends TermTree with SymTree with ApplyDynamicApi + object ApplyDynamic extends ApplyDynamicExtractor + + case class Super(qual: Tree, mix: TypeName) extends TermTree with SuperApi { + override def symbol: Symbol = qual.symbol + override def symbol_=(sym: Symbol) { qual.symbol = sym } + } + object Super extends SuperExtractor + + case class This(qual: TypeName) + extends TermTree with SymTree with ThisApi + object This extends ThisExtractor + + case class Select(qualifier: Tree, name: Name) + extends RefTree with SelectApi + object Select extends SelectExtractor + + case class Ident(name: Name) extends RefTree with IdentContextApi { + def qualifier: Tree = EmptyTree + def isBackquoted = this.attachments.get[BackquotedIdentifierAttachment.type].isDefined + } + object Ident extends IdentExtractor + + case class ReferenceToBoxed(ident: Ident) extends TermTree with ReferenceToBoxedApi { + override def symbol: Symbol = ident.symbol + override def symbol_=(sym: Symbol) { ident.symbol = sym } + } + object ReferenceToBoxed extends ReferenceToBoxedExtractor + + case class Literal(value: Constant) + extends TermTree with LiteralApi { + assert(value ne null) + } + object Literal extends LiteralExtractor + +// @deprecated("will be removed and then be re-introduced with changed semantics, use Literal(Constant(x)) instead") +// def Literal(x: Any) = new Literal(Constant(x)) + + case class Annotated(annot: Tree, arg: Tree) extends Tree with AnnotatedApi + object Annotated extends AnnotatedExtractor + + case class SingletonTypeTree(ref: Tree) + extends TypTree with SingletonTypeTreeApi + object SingletonTypeTree extends SingletonTypeTreeExtractor + + case class SelectFromTypeTree(qualifier: Tree, name: TypeName) + extends TypTree with RefTree with SelectFromTypeTreeApi + object SelectFromTypeTree extends SelectFromTypeTreeExtractor + + case class CompoundTypeTree(templ: Template) + extends TypTree with CompoundTypeTreeApi + object CompoundTypeTree extends CompoundTypeTreeExtractor + + case class AppliedTypeTree(tpt: Tree, args: List[Tree]) + extends TypTree with AppliedTypeTreeApi { + override def symbol: Symbol = tpt.symbol + override def symbol_=(sym: Symbol) { tpt.symbol = sym } + } + object AppliedTypeTree extends AppliedTypeTreeExtractor + + case class TypeBoundsTree(lo: Tree, hi: Tree) + extends TypTree with TypeBoundsTreeApi + object TypeBoundsTree extends TypeBoundsTreeExtractor + + case class ExistentialTypeTree(tpt: Tree, whereClauses: List[Tree]) + extends TypTree with ExistentialTypeTreeApi + object ExistentialTypeTree extends ExistentialTypeTreeExtractor + + case class TypeTree() extends TypTree with TypeTreeContextApi { + private var orig: Tree = null + private[scala] var wasEmpty: Boolean = false + + override def symbol = if (tpe == null) null else tpe.typeSymbol + override def isEmpty = (tpe eq null) || tpe == NoType + + def original: Tree = orig + def setOriginal(tree: Tree): this.type = { + def followOriginal(t: Tree): Tree = t match { + case tt: TypeTree => followOriginal(tt.original) + case t => t + } + + orig = followOriginal(tree); setPos(tree.pos); + this + } + + override def defineType(tp: Type): this.type = { + wasEmpty = isEmpty + setType(tp) + } + } + object TypeTree extends TypeTreeExtractor + + def TypeTree(tp: Type): TypeTree = TypeTree() setType tp + + class StrictTreeCopier extends TreeCopierOps { + def ClassDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], impl: Template) = + new ClassDef(mods, name.toTypeName, tparams, impl).copyAttrs(tree) + def PackageDef(tree: Tree, pid: RefTree, stats: List[Tree]) = + new PackageDef(pid, stats).copyAttrs(tree) + def ModuleDef(tree: Tree, mods: Modifiers, name: Name, impl: Template) = + new ModuleDef(mods, name.toTermName, impl).copyAttrs(tree) + def ValDef(tree: Tree, mods: Modifiers, name: Name, tpt: Tree, rhs: Tree) = + new ValDef(mods, name.toTermName, tpt, rhs).copyAttrs(tree) + def DefDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree) = + new DefDef(mods, name.toTermName, tparams, vparamss, tpt, rhs).copyAttrs(tree) + def TypeDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], rhs: Tree) = + new TypeDef(mods, name.toTypeName, tparams, rhs).copyAttrs(tree) + def LabelDef(tree: Tree, name: Name, params: List[Ident], rhs: Tree) = + new LabelDef(name.toTermName, params, rhs).copyAttrs(tree) + def Import(tree: Tree, expr: Tree, selectors: List[ImportSelector]) = + new Import(expr, selectors).copyAttrs(tree) + def Template(tree: Tree, parents: List[Tree], self: ValDef, body: List[Tree]) = + new Template(parents, self, body).copyAttrs(tree) + def Block(tree: Tree, stats: List[Tree], expr: Tree) = + new Block(stats, expr).copyAttrs(tree) + def CaseDef(tree: Tree, pat: Tree, guard: Tree, body: Tree) = + new CaseDef(pat, guard, body).copyAttrs(tree) + def Alternative(tree: Tree, trees: List[Tree]) = + new Alternative(trees).copyAttrs(tree) + def Star(tree: Tree, elem: Tree) = + new Star(elem).copyAttrs(tree) + def Bind(tree: Tree, name: Name, body: Tree) = + new Bind(name, body).copyAttrs(tree) + def UnApply(tree: Tree, fun: Tree, args: List[Tree]) = + new UnApply(fun, args).copyAttrs(tree) + def ArrayValue(tree: Tree, elemtpt: Tree, trees: List[Tree]) = + new ArrayValue(elemtpt, trees).copyAttrs(tree) + def Function(tree: Tree, vparams: List[ValDef], body: Tree) = + new Function(vparams, body).copyAttrs(tree) + def Assign(tree: Tree, lhs: Tree, rhs: Tree) = + new Assign(lhs, rhs).copyAttrs(tree) + def AssignOrNamedArg(tree: Tree, lhs: Tree, rhs: Tree) = + new AssignOrNamedArg(lhs, rhs).copyAttrs(tree) + def If(tree: Tree, cond: Tree, thenp: Tree, elsep: Tree) = + new If(cond, thenp, elsep).copyAttrs(tree) + def Match(tree: Tree, selector: Tree, cases: List[CaseDef]) = + new Match(selector, cases).copyAttrs(tree) + def Return(tree: Tree, expr: Tree) = + new Return(expr).copyAttrs(tree) + def Try(tree: Tree, block: Tree, catches: List[CaseDef], finalizer: Tree) = + new Try(block, catches, finalizer).copyAttrs(tree) + def Throw(tree: Tree, expr: Tree) = + new Throw(expr).copyAttrs(tree) + def New(tree: Tree, tpt: Tree) = + new New(tpt).copyAttrs(tree) + def Typed(tree: Tree, expr: Tree, tpt: Tree) = + new Typed(expr, tpt).copyAttrs(tree) + def TypeApply(tree: Tree, fun: Tree, args: List[Tree]) = + new TypeApply(fun, args).copyAttrs(tree) + def Apply(tree: Tree, fun: Tree, args: List[Tree]) = + (tree match { // TODO: use a tree attachment to track whether this is an apply to implicit args or a view + case _: ApplyToImplicitArgs => new ApplyToImplicitArgs(fun, args) + case _: ApplyImplicitView => new ApplyImplicitView(fun, args) + // TODO: ApplyConstructor ??? + case _ => new Apply(fun, args) + }).copyAttrs(tree) + def ApplyDynamic(tree: Tree, qual: Tree, args: List[Tree]) = + new ApplyDynamic(qual, args).copyAttrs(tree) + def Super(tree: Tree, qual: Tree, mix: TypeName) = + new Super(qual, mix).copyAttrs(tree) + def This(tree: Tree, qual: Name) = + new This(qual.toTypeName).copyAttrs(tree) + def Select(tree: Tree, qualifier: Tree, selector: Name) = + new Select(qualifier, selector).copyAttrs(tree) + def Ident(tree: Tree, name: Name) = + new Ident(name) copyAttrs tree + def ReferenceToBoxed(tree: Tree, idt: Ident) = + new ReferenceToBoxed(idt).copyAttrs(tree) + def Literal(tree: Tree, value: Constant) = + new Literal(value).copyAttrs(tree) + def TypeTree(tree: Tree) = + new TypeTree().copyAttrs(tree) + def Annotated(tree: Tree, annot: Tree, arg: Tree) = + new Annotated(annot, arg).copyAttrs(tree) + def SingletonTypeTree(tree: Tree, ref: Tree) = + new SingletonTypeTree(ref).copyAttrs(tree) + def SelectFromTypeTree(tree: Tree, qualifier: Tree, selector: Name) = + new SelectFromTypeTree(qualifier, selector.toTypeName).copyAttrs(tree) + def CompoundTypeTree(tree: Tree, templ: Template) = + new CompoundTypeTree(templ).copyAttrs(tree) + def AppliedTypeTree(tree: Tree, tpt: Tree, args: List[Tree]) = + new AppliedTypeTree(tpt, args).copyAttrs(tree) + def TypeBoundsTree(tree: Tree, lo: Tree, hi: Tree) = + new TypeBoundsTree(lo, hi).copyAttrs(tree) + def ExistentialTypeTree(tree: Tree, tpt: Tree, whereClauses: List[Tree]) = + new ExistentialTypeTree(tpt, whereClauses).copyAttrs(tree) + } + + class LazyTreeCopier extends TreeCopierOps { + val treeCopy: TreeCopier = newStrictTreeCopier + def ClassDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], impl: Template) = tree match { + case t @ ClassDef(mods0, name0, tparams0, impl0) + if (mods0 == mods) && (name0 == name) && (tparams0 == tparams) && (impl0 == impl) => t + case _ => treeCopy.ClassDef(tree, mods, name, tparams, impl) + } + def PackageDef(tree: Tree, pid: RefTree, stats: List[Tree]) = tree match { + case t @ PackageDef(pid0, stats0) + if (pid0 == pid) && (stats0 == stats) => t + case _ => treeCopy.PackageDef(tree, pid, stats) + } + def ModuleDef(tree: Tree, mods: Modifiers, name: Name, impl: Template) = tree match { + case t @ ModuleDef(mods0, name0, impl0) + if (mods0 == mods) && (name0 == name) && (impl0 == impl) => t + case _ => treeCopy.ModuleDef(tree, mods, name, impl) + } + def ValDef(tree: Tree, mods: Modifiers, name: Name, tpt: Tree, rhs: Tree) = tree match { + case t @ ValDef(mods0, name0, tpt0, rhs0) + if (mods0 == mods) && (name0 == name) && (tpt0 == tpt) && (rhs0 == rhs) => t + case _ => treeCopy.ValDef(tree, mods, name, tpt, rhs) + } + def DefDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree) = tree match { + case t @ DefDef(mods0, name0, tparams0, vparamss0, tpt0, rhs0) + if (mods0 == mods) && (name0 == name) && (tparams0 == tparams) && + (vparamss0 == vparamss) && (tpt0 == tpt) && (rhs == rhs0) => t + case _ => treeCopy.DefDef(tree, mods, name, tparams, vparamss, tpt, rhs) + } + def TypeDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], rhs: Tree) = tree match { + case t @ TypeDef(mods0, name0, tparams0, rhs0) + if (mods0 == mods) && (name0 == name) && (tparams0 == tparams) && (rhs0 == rhs) => t + case _ => treeCopy.TypeDef(tree, mods, name, tparams, rhs) + } + def LabelDef(tree: Tree, name: Name, params: List[Ident], rhs: Tree) = tree match { + case t @ LabelDef(name0, params0, rhs0) + if (name0 == name) && (params0 == params) && (rhs0 == rhs) => t + case _ => treeCopy.LabelDef(tree, name, params, rhs) + } + def Import(tree: Tree, expr: Tree, selectors: List[ImportSelector]) = tree match { + case t @ Import(expr0, selectors0) + if (expr0 == expr) && (selectors0 == selectors) => t + case _ => treeCopy.Import(tree, expr, selectors) + } + def Template(tree: Tree, parents: List[Tree], self: ValDef, body: List[Tree]) = tree match { + case t @ Template(parents0, self0, body0) + if (parents0 == parents) && (self0 == self) && (body0 == body) => t + case _ => treeCopy.Template(tree, parents, self, body) + } + def Block(tree: Tree, stats: List[Tree], expr: Tree) = tree match { + case t @ Block(stats0, expr0) + if ((stats0 == stats) && (expr0 == expr)) => t + case _ => treeCopy.Block(tree, stats, expr) + } + def CaseDef(tree: Tree, pat: Tree, guard: Tree, body: Tree) = tree match { + case t @ CaseDef(pat0, guard0, body0) + if (pat0 == pat) && (guard0 == guard) && (body0 == body) => t + case _ => treeCopy.CaseDef(tree, pat, guard, body) + } + def Alternative(tree: Tree, trees: List[Tree]) = tree match { + case t @ Alternative(trees0) + if trees0 == trees => t + case _ => treeCopy.Alternative(tree, trees) + } + def Star(tree: Tree, elem: Tree) = tree match { + case t @ Star(elem0) + if elem0 == elem => t + case _ => treeCopy.Star(tree, elem) + } + def Bind(tree: Tree, name: Name, body: Tree) = tree match { + case t @ Bind(name0, body0) + if (name0 == name) && (body0 == body) => t + case _ => treeCopy.Bind(tree, name, body) + } + def UnApply(tree: Tree, fun: Tree, args: List[Tree]) = tree match { + case t @ UnApply(fun0, args0) + if (fun0 == fun) && (args0 == args) => t + case _ => treeCopy.UnApply(tree, fun, args) + } + def ArrayValue(tree: Tree, elemtpt: Tree, trees: List[Tree]) = tree match { + case t @ ArrayValue(elemtpt0, trees0) + if (elemtpt0 == elemtpt) && (trees0 == trees) => t + case _ => treeCopy.ArrayValue(tree, elemtpt, trees) + } + def Function(tree: Tree, vparams: List[ValDef], body: Tree) = tree match { + case t @ Function(vparams0, body0) + if (vparams0 == vparams) && (body0 == body) => t + case _ => treeCopy.Function(tree, vparams, body) + } + def Assign(tree: Tree, lhs: Tree, rhs: Tree) = tree match { + case t @ Assign(lhs0, rhs0) + if (lhs0 == lhs) && (rhs0 == rhs) => t + case _ => treeCopy.Assign(tree, lhs, rhs) + } + def AssignOrNamedArg(tree: Tree, lhs: Tree, rhs: Tree) = tree match { + case t @ AssignOrNamedArg(lhs0, rhs0) + if (lhs0 == lhs) && (rhs0 == rhs) => t + case _ => treeCopy.AssignOrNamedArg(tree, lhs, rhs) + } + def If(tree: Tree, cond: Tree, thenp: Tree, elsep: Tree) = tree match { + case t @ If(cond0, thenp0, elsep0) + if (cond0 == cond) && (thenp0 == thenp) && (elsep0 == elsep) => t + case _ => treeCopy.If(tree, cond, thenp, elsep) + } + def Match(tree: Tree, selector: Tree, cases: List[CaseDef]) = tree match { + case t @ Match(selector0, cases0) + if (selector0 == selector) && (cases0 == cases) => t + case _ => treeCopy.Match(tree, selector, cases) + } + def Return(tree: Tree, expr: Tree) = tree match { + case t @ Return(expr0) + if expr0 == expr => t + case _ => treeCopy.Return(tree, expr) + } + def Try(tree: Tree, block: Tree, catches: List[CaseDef], finalizer: Tree) = tree match { + case t @ Try(block0, catches0, finalizer0) + if (block0 == block) && (catches0 == catches) && (finalizer0 == finalizer) => t + case _ => treeCopy.Try(tree, block, catches, finalizer) + } + def Throw(tree: Tree, expr: Tree) = tree match { + case t @ Throw(expr0) + if expr0 == expr => t + case _ => treeCopy.Throw(tree, expr) + } + def New(tree: Tree, tpt: Tree) = tree match { + case t @ New(tpt0) + if tpt0 == tpt => t + case _ => treeCopy.New(tree, tpt) + } + def Typed(tree: Tree, expr: Tree, tpt: Tree) = tree match { + case t @ Typed(expr0, tpt0) + if (expr0 == expr) && (tpt0 == tpt) => t + case _ => treeCopy.Typed(tree, expr, tpt) + } + def TypeApply(tree: Tree, fun: Tree, args: List[Tree]) = tree match { + case t @ TypeApply(fun0, args0) + if (fun0 == fun) && (args0 == args) => t + case _ => treeCopy.TypeApply(tree, fun, args) + } + def Apply(tree: Tree, fun: Tree, args: List[Tree]) = tree match { + case t @ Apply(fun0, args0) + if (fun0 == fun) && (args0 == args) => t + case _ => treeCopy.Apply(tree, fun, args) + } + def ApplyDynamic(tree: Tree, qual: Tree, args: List[Tree]) = tree match { + case t @ ApplyDynamic(qual0, args0) + if (qual0 == qual) && (args0 == args) => t + case _ => treeCopy.ApplyDynamic(tree, qual, args) + } + def Super(tree: Tree, qual: Tree, mix: TypeName) = tree match { + case t @ Super(qual0, mix0) + if (qual0 == qual) && (mix0 == mix) => t + case _ => treeCopy.Super(tree, qual, mix) + } + def This(tree: Tree, qual: Name) = tree match { + case t @ This(qual0) + if qual0 == qual => t + case _ => treeCopy.This(tree, qual) + } + def Select(tree: Tree, qualifier: Tree, selector: Name) = tree match { + case t @ Select(qualifier0, selector0) + if (qualifier0 == qualifier) && (selector0 == selector) => t + case _ => treeCopy.Select(tree, qualifier, selector) + } + def Ident(tree: Tree, name: Name) = tree match { + case t @ Ident(name0) + if name0 == name => t + case _ => treeCopy.Ident(tree, name) + } + def ReferenceToBoxed(tree: Tree, idt: Ident) = tree match { + case t @ ReferenceToBoxed(idt0) + if (idt0 == idt) => t + case _ => this.treeCopy.ReferenceToBoxed(tree, idt) + } + def Literal(tree: Tree, value: Constant) = tree match { + case t @ Literal(value0) + if value0 == value => t + case _ => treeCopy.Literal(tree, value) + } + def TypeTree(tree: Tree) = tree match { + case t @ TypeTree() => t + case _ => treeCopy.TypeTree(tree) + } + def Annotated(tree: Tree, annot: Tree, arg: Tree) = tree match { + case t @ Annotated(annot0, arg0) + if (annot0==annot) => t + case _ => treeCopy.Annotated(tree, annot, arg) + } + def SingletonTypeTree(tree: Tree, ref: Tree) = tree match { + case t @ SingletonTypeTree(ref0) + if ref0 == ref => t + case _ => treeCopy.SingletonTypeTree(tree, ref) + } + def SelectFromTypeTree(tree: Tree, qualifier: Tree, selector: Name) = tree match { + case t @ SelectFromTypeTree(qualifier0, selector0) + if (qualifier0 == qualifier) && (selector0 == selector) => t + case _ => treeCopy.SelectFromTypeTree(tree, qualifier, selector) + } + def CompoundTypeTree(tree: Tree, templ: Template) = tree match { + case t @ CompoundTypeTree(templ0) + if templ0 == templ => t + case _ => treeCopy.CompoundTypeTree(tree, templ) + } + def AppliedTypeTree(tree: Tree, tpt: Tree, args: List[Tree]) = tree match { + case t @ AppliedTypeTree(tpt0, args0) + if (tpt0 == tpt) && (args0 == args) => t + case _ => treeCopy.AppliedTypeTree(tree, tpt, args) + } + def TypeBoundsTree(tree: Tree, lo: Tree, hi: Tree) = tree match { + case t @ TypeBoundsTree(lo0, hi0) + if (lo0 == lo) && (hi0 == hi) => t + case _ => treeCopy.TypeBoundsTree(tree, lo, hi) + } + def ExistentialTypeTree(tree: Tree, tpt: Tree, whereClauses: List[Tree]) = tree match { + case t @ ExistentialTypeTree(tpt0, whereClauses0) + if (tpt0 == tpt) && (whereClauses0 == whereClauses) => t + case _ => treeCopy.ExistentialTypeTree(tree, tpt, whereClauses) + } + } + // Belongs in TreeInfo but then I can't reach it from TreePrinters. def isReferenceToScalaMember(t: Tree, Id: Name) = t match { case Ident(Id) => true @@ -33,7 +831,7 @@ trait Trees extends api.Trees { self: SymbolTable => */ case class Modifiers(flags: Long, privateWithin: Name, - annotations: List[Tree]) extends AbsModifiers with HasFlags { + annotations: List[Tree]) extends ModifiersApi with HasFlags { var positions: Map[Long, Position] = Map() @@ -79,82 +877,15 @@ trait Trees extends api.Trees { self: SymbolTable => def withPosition(flag: Long, position: Position) = copy() setPositions positions + (flag -> position) - override def hasModifier(mod: Modifier) = - hasFlag(flagOfModifier(mod)) - override def modifiers: Set[Modifier] = - Modifier.values filter hasModifier override def mapAnnotations(f: List[Tree] => List[Tree]): Modifiers = Modifiers(flags, privateWithin, f(annotations)) setPositions positions override def toString = "Modifiers(%s, %s, %s)".format(flagString, annotations mkString ", ", positions) } - def Modifiers(flags: Long, privateWithin: Name): Modifiers = Modifiers(flags, privateWithin, List()) - def Modifiers(flags: Long): Modifiers = Modifiers(flags, tpnme.EMPTY) + object Modifiers extends ModifiersCreator - def Modifiers(mods: Set[Modifier], - privateWithin: Name, - annotations: List[Tree]): Modifiers = { - val flagSet = mods map flagOfModifier - Modifiers((0L /: flagSet)(_ | _), privateWithin, annotations) - } - - lazy val NoMods = Modifiers(0) - - // --- extension methods -------------------------------------------------------- - - implicit class TreeOps(tree: Tree) { - def isErroneous = (tree.tpe ne null) && tree.tpe.isErroneous - def isTyped = (tree.tpe ne null) && !tree.tpe.isErroneous - - /** Sets the tree's type to the result of the given function. - * If the type is null, it remains null - the function is not called. - */ - def modifyType(f: Type => Type): Tree = - if (tree.tpe eq null) tree - else tree setType f(tree.tpe) - - /** If `pf` is defined for a given subtree, call super.traverse(pf(tree)), - * otherwise super.traverse(tree). - */ - def foreachPartial(pf: PartialFunction[Tree, Tree]) { - new ForeachPartialTreeTraverser(pf).traverse(tree) - } - - def changeOwner(pairs: (Symbol, Symbol)*): Tree = { - pairs.foldLeft(tree) { case (t, (oldOwner, newOwner)) => - new ChangeOwnerTraverser(oldOwner, newOwner) apply t - } - } - - def substTreeSyms(pairs: (Symbol, Symbol)*): Tree = - substTreeSyms(pairs.map(_._1).toList, pairs.map(_._2).toList) - - def substTreeSyms(from: List[Symbol], to: List[Symbol]): Tree = - new TreeSymSubstituter(from, to)(tree) - - def substTreeThis(clazz: Symbol, to: Tree): Tree = new ThisSubstituter(clazz, to) transform tree - - def shallowDuplicate: Tree = new ShallowDuplicator(tree) transform tree - def shortClass: String = tree.getClass.getName split "[.$]" last - - def isErrorTyped = (tree.tpe ne null) && tree.tpe.isError - - /** When you want to know a little more than the class, but a lot - * less than the whole tree. - */ - def summaryString: String = tree match { - case Literal(const) => "Literal(" + const + ")" - case Ident(name) => "Ident(%s)".format(name.decode) - case Select(qual, name) => "Select(%s, %s)".format(qual.summaryString, name.decode) - case t: NameTree => t.name.longString - case t => - t.shortClass + ( - if (t.symbol != null && t.symbol != NoSymbol) "(" + t.symbol + ")" - else "" - ) - } - } + implicit val ModifiersTag = ClassTag[Modifiers](classOf[Modifiers]) // ---- values and creators --------------------------------------- @@ -251,14 +982,19 @@ trait Trees extends api.Trees { self: SymbolTable => * A `New(t, as)` is expanded to: `(new t).<init>(as)` */ def New(tpt: Tree, argss: List[List[Tree]]): Tree = argss match { - case Nil => new ApplyConstructor(tpt, Nil) - case xs :: rest => rest.foldLeft(new ApplyConstructor(tpt, xs): Tree)(Apply) + case Nil => ApplyConstructor(tpt, Nil) + case xs :: rest => { + def mkApply(fun: Tree, args: List[Tree]) = Apply(fun, args) + rest.foldLeft(ApplyConstructor(tpt, xs): Tree)(mkApply) + // [Eugene++] no longer compiles after I moved the `Apply` case class here + // rest.foldLeft(ApplyConstructor(tpt, xs): Tree)(Apply) + } } /** 0-1 argument list new, based on a type. */ def New(tpe: Type, args: Tree*): Tree = - new ApplyConstructor(TypeTree(tpe), args.toList) + ApplyConstructor(TypeTree(tpe), args.toList) def New(sym: Symbol, args: Tree*): Tree = New(sym.tpe, args: _*) @@ -292,20 +1028,244 @@ trait Trees extends api.Trees { self: SymbolTable => } } - // --- specific traversers and transformers - // todo. move these into scala.reflect.api - - protected[scala] def duplicateTree(tree: Tree): Tree = duplicator transform tree + // --- generic traversers and transformers + + override protected def itraverse(traverser: Traverser, tree: Tree): Unit = { + import traverser._ + tree match { + case EmptyTree => + ; + case PackageDef(pid, stats) => + traverse(pid) + atOwner(mclass(tree.symbol)) { + traverseTrees(stats) + } + case ClassDef(mods, name, tparams, impl) => + atOwner(tree.symbol) { + traverseTrees(mods.annotations); traverseTrees(tparams); traverse(impl) + } + case ModuleDef(mods, name, impl) => + atOwner(mclass(tree.symbol)) { + traverseTrees(mods.annotations); traverse(impl) + } + case ValDef(mods, name, tpt, rhs) => + atOwner(tree.symbol) { + traverseTrees(mods.annotations); traverse(tpt); traverse(rhs) + } + case DefDef(mods, name, tparams, vparamss, tpt, rhs) => + atOwner(tree.symbol) { + traverseTrees(mods.annotations); traverseTrees(tparams); traverseTreess(vparamss); traverse(tpt); traverse(rhs) + } + case TypeDef(mods, name, tparams, rhs) => + atOwner(tree.symbol) { + traverseTrees(mods.annotations); traverseTrees(tparams); traverse(rhs) + } + case LabelDef(name, params, rhs) => + traverseTrees(params); traverse(rhs) + case Import(expr, selectors) => + traverse(expr) + case Annotated(annot, arg) => + traverse(annot); traverse(arg) + case Template(parents, self, body) => + traverseTrees(parents) + if (!self.isEmpty) traverse(self) + traverseStats(body, tree.symbol) + case Block(stats, expr) => + traverseTrees(stats); traverse(expr) + case CaseDef(pat, guard, body) => + traverse(pat); traverse(guard); traverse(body) + case Alternative(trees) => + traverseTrees(trees) + case Star(elem) => + traverse(elem) + case Bind(name, body) => + traverse(body) + case UnApply(fun, args) => + traverse(fun); traverseTrees(args) + case ArrayValue(elemtpt, trees) => + traverse(elemtpt); traverseTrees(trees) + case Function(vparams, body) => + atOwner(tree.symbol) { + traverseTrees(vparams); traverse(body) + } + case Assign(lhs, rhs) => + traverse(lhs); traverse(rhs) + case AssignOrNamedArg(lhs, rhs) => + traverse(lhs); traverse(rhs) + case If(cond, thenp, elsep) => + traverse(cond); traverse(thenp); traverse(elsep) + case Match(selector, cases) => + traverse(selector); traverseTrees(cases) + case Return(expr) => + traverse(expr) + case Try(block, catches, finalizer) => + traverse(block); traverseTrees(catches); traverse(finalizer) + case Throw(expr) => + traverse(expr) + case New(tpt) => + traverse(tpt) + case Typed(expr, tpt) => + traverse(expr); traverse(tpt) + case TypeApply(fun, args) => + traverse(fun); traverseTrees(args) + case Apply(fun, args) => + traverse(fun); traverseTrees(args) + case ApplyDynamic(qual, args) => + traverse(qual); traverseTrees(args) + case Super(qual, _) => + traverse(qual) + case This(_) => + ; + case Select(qualifier, selector) => + traverse(qualifier) + case Ident(_) => + ; + case ReferenceToBoxed(idt) => + traverse(idt) + case Literal(_) => + ; + case TypeTree() => + ; + case SingletonTypeTree(ref) => + traverse(ref) + case SelectFromTypeTree(qualifier, selector) => + traverse(qualifier) + case CompoundTypeTree(templ) => + traverse(templ) + case AppliedTypeTree(tpt, args) => + traverse(tpt); traverseTrees(args) + case TypeBoundsTree(lo, hi) => + traverse(lo); traverse(hi) + case ExistentialTypeTree(tpt, whereClauses) => + traverse(tpt); traverseTrees(whereClauses) + case _ => xtraverse(traverser, tree) + } + } - private lazy val duplicator = new Transformer { - override val treeCopy = newStrictTreeCopier - override def transform(t: Tree) = { - val t1 = super.transform(t) - if ((t1 ne t) && t1.pos.isRange) t1 setPos t.pos.focus - t1 + override protected def itransform(transformer: Transformer, tree: Tree): Tree = { + import transformer._ + val treeCopy = transformer.treeCopy + tree match { + case EmptyTree => + tree + case PackageDef(pid, stats) => + treeCopy.PackageDef( + tree, transform(pid).asInstanceOf[RefTree], + atOwner(mclass(tree.symbol)) { + transformStats(stats, currentOwner) + } + ) + case ClassDef(mods, name, tparams, impl) => + atOwner(tree.symbol) { + treeCopy.ClassDef(tree, transformModifiers(mods), name, + transformTypeDefs(tparams), transformTemplate(impl)) + } + case ModuleDef(mods, name, impl) => + atOwner(mclass(tree.symbol)) { + treeCopy.ModuleDef(tree, transformModifiers(mods), + name, transformTemplate(impl)) + } + case ValDef(mods, name, tpt, rhs) => + atOwner(tree.symbol) { + treeCopy.ValDef(tree, transformModifiers(mods), + name, transform(tpt), transform(rhs)) + } + case DefDef(mods, name, tparams, vparamss, tpt, rhs) => + atOwner(tree.symbol) { + treeCopy.DefDef(tree, transformModifiers(mods), name, + transformTypeDefs(tparams), transformValDefss(vparamss), + transform(tpt), transform(rhs)) + } + case TypeDef(mods, name, tparams, rhs) => + atOwner(tree.symbol) { + treeCopy.TypeDef(tree, transformModifiers(mods), name, + transformTypeDefs(tparams), transform(rhs)) + } + case LabelDef(name, params, rhs) => + treeCopy.LabelDef(tree, name, transformIdents(params), transform(rhs)) //bq: Martin, once, atOwner(...) works, also change `LamdaLifter.proxy' + case Import(expr, selectors) => + treeCopy.Import(tree, transform(expr), selectors) + case Template(parents, self, body) => + treeCopy.Template(tree, transformTrees(parents), transformValDef(self), transformStats(body, tree.symbol)) + case Block(stats, expr) => + treeCopy.Block(tree, transformStats(stats, currentOwner), transform(expr)) + case CaseDef(pat, guard, body) => + treeCopy.CaseDef(tree, transform(pat), transform(guard), transform(body)) + case Alternative(trees) => + treeCopy.Alternative(tree, transformTrees(trees)) + case Star(elem) => + treeCopy.Star(tree, transform(elem)) + case Bind(name, body) => + treeCopy.Bind(tree, name, transform(body)) + case UnApply(fun, args) => + treeCopy.UnApply(tree, fun, transformTrees(args)) // bq: see test/.../unapplyContexts2.scala + case ArrayValue(elemtpt, trees) => + treeCopy.ArrayValue(tree, transform(elemtpt), transformTrees(trees)) + case Function(vparams, body) => + atOwner(tree.symbol) { + treeCopy.Function(tree, transformValDefs(vparams), transform(body)) + } + case Assign(lhs, rhs) => + treeCopy.Assign(tree, transform(lhs), transform(rhs)) + case AssignOrNamedArg(lhs, rhs) => + treeCopy.AssignOrNamedArg(tree, transform(lhs), transform(rhs)) + case If(cond, thenp, elsep) => + treeCopy.If(tree, transform(cond), transform(thenp), transform(elsep)) + case Match(selector, cases) => + treeCopy.Match(tree, transform(selector), transformCaseDefs(cases)) + case Return(expr) => + treeCopy.Return(tree, transform(expr)) + case Try(block, catches, finalizer) => + treeCopy.Try(tree, transform(block), transformCaseDefs(catches), transform(finalizer)) + case Throw(expr) => + treeCopy.Throw(tree, transform(expr)) + case New(tpt) => + treeCopy.New(tree, transform(tpt)) + case Typed(expr, tpt) => + treeCopy.Typed(tree, transform(expr), transform(tpt)) + case TypeApply(fun, args) => + treeCopy.TypeApply(tree, transform(fun), transformTrees(args)) + case Apply(fun, args) => + treeCopy.Apply(tree, transform(fun), transformTrees(args)) + case ApplyDynamic(qual, args) => + treeCopy.ApplyDynamic(tree, transform(qual), transformTrees(args)) + case Super(qual, mix) => + treeCopy.Super(tree, transform(qual), mix) + case This(qual) => + treeCopy.This(tree, qual) + case Select(qualifier, selector) => + treeCopy.Select(tree, transform(qualifier), selector) + case Ident(name) => + treeCopy.Ident(tree, name) + case ReferenceToBoxed(idt) => + treeCopy.ReferenceToBoxed(tree, transform(idt) match { case idt1: Ident => idt1 }) + case Literal(value) => + treeCopy.Literal(tree, value) + case TypeTree() => + treeCopy.TypeTree(tree) + case Annotated(annot, arg) => + treeCopy.Annotated(tree, transform(annot), transform(arg)) + case SingletonTypeTree(ref) => + treeCopy.SingletonTypeTree(tree, transform(ref)) + case SelectFromTypeTree(qualifier, selector) => + treeCopy.SelectFromTypeTree(tree, transform(qualifier), selector) + case CompoundTypeTree(templ) => + treeCopy.CompoundTypeTree(tree, transformTemplate(templ)) + case AppliedTypeTree(tpt, args) => + treeCopy.AppliedTypeTree(tree, transform(tpt), transformTrees(args)) + case TypeBoundsTree(lo, hi) => + treeCopy.TypeBoundsTree(tree, transform(lo), transform(hi)) + case ExistentialTypeTree(tpt, whereClauses) => + treeCopy.ExistentialTypeTree(tree, transform(tpt), transformTrees(whereClauses)) + case _ => + xtransform(transformer, tree) } } + private def mclass(sym: Symbol) = sym map (_.asModuleSymbol.moduleClass) + + // --- specific traversers and transformers + class ForeachPartialTreeTraverser(pf: PartialFunction[Tree, Tree]) extends Traverser { override def traverse(tree: Tree) { val t = if (pf isDefinedAt tree) pf(tree) else tree @@ -432,4 +1392,201 @@ trait Trees extends api.Trees { self: SymbolTable => def apply[T <: Tree](tree: T): T = transform(tree).asInstanceOf[T] override def toString() = "TreeSymSubstituter/" + substituterString("Symbol", "Symbol", from, to) } + + + class ForeachTreeTraverser(f: Tree => Unit) extends Traverser { + override def traverse(t: Tree) { + f(t) + super.traverse(t) + } + } + + class FilterTreeTraverser(p: Tree => Boolean) extends Traverser { + val hits = new ListBuffer[Tree] + override def traverse(t: Tree) { + if (p(t)) hits += t + super.traverse(t) + } + } + + class CollectTreeTraverser[T](pf: PartialFunction[Tree, T]) extends Traverser { + val results = new ListBuffer[T] + override def traverse(t: Tree) { + if (pf.isDefinedAt(t)) results += pf(t) + super.traverse(t) + } + } + + class FindTreeTraverser(p: Tree => Boolean) extends Traverser { + var result: Option[Tree] = None + override def traverse(t: Tree) { + if (result.isEmpty) { + if (p(t)) result = Some(t) + super.traverse(t) + } + } + } + + private lazy val duplicator = new Transformer { + override val treeCopy = newStrictTreeCopier + override def transform(t: Tree) = { + val t1 = super.transform(t) + if ((t1 ne t) && t1.pos.isRange) t1 setPos t.pos.focus + t1 + } + } + + // ------ copiers ------------------------------------------- + + def copyDefDef(tree: Tree)( + mods: Modifiers = null, + name: Name = null, + tparams: List[TypeDef] = null, + vparamss: List[List[ValDef]] = null, + tpt: Tree = null, + rhs: Tree = null + ): DefDef = tree match { + case DefDef(mods0, name0, tparams0, vparamss0, tpt0, rhs0) => + treeCopy.DefDef(tree, + if (mods eq null) mods0 else mods, + if (name eq null) name0 else name, + if (tparams eq null) tparams0 else tparams, + if (vparamss eq null) vparamss0 else vparamss, + if (tpt eq null) tpt0 else tpt, + if (rhs eq null) rhs0 else rhs + ) + case t => + sys.error("Not a DefDef: " + t + "/" + t.getClass) + } + def copyValDef(tree: Tree)( + mods: Modifiers = null, + name: Name = null, + tpt: Tree = null, + rhs: Tree = null + ): ValDef = tree match { + case ValDef(mods0, name0, tpt0, rhs0) => + treeCopy.ValDef(tree, + if (mods eq null) mods0 else mods, + if (name eq null) name0 else name, + if (tpt eq null) tpt0 else tpt, + if (rhs eq null) rhs0 else rhs + ) + case t => + sys.error("Not a ValDef: " + t + "/" + t.getClass) + } + def copyClassDef(tree: Tree)( + mods: Modifiers = null, + name: Name = null, + tparams: List[TypeDef] = null, + impl: Template = null + ): ClassDef = tree match { + case ClassDef(mods0, name0, tparams0, impl0) => + treeCopy.ClassDef(tree, + if (mods eq null) mods0 else mods, + if (name eq null) name0 else name, + if (tparams eq null) tparams0 else tparams, + if (impl eq null) impl0 else impl + ) + case t => + sys.error("Not a ClassDef: " + t + "/" + t.getClass) + } + + def deriveDefDef(ddef: Tree)(applyToRhs: Tree => Tree): DefDef = ddef match { + case DefDef(mods0, name0, tparams0, vparamss0, tpt0, rhs0) => + treeCopy.DefDef(ddef, mods0, name0, tparams0, vparamss0, tpt0, applyToRhs(rhs0)) + case t => + sys.error("Not a DefDef: " + t + "/" + t.getClass) + } + def deriveValDef(vdef: Tree)(applyToRhs: Tree => Tree): ValDef = vdef match { + case ValDef(mods0, name0, tpt0, rhs0) => + treeCopy.ValDef(vdef, mods0, name0, tpt0, applyToRhs(rhs0)) + case t => + sys.error("Not a ValDef: " + t + "/" + t.getClass) + } + def deriveTemplate(templ: Tree)(applyToBody: List[Tree] => List[Tree]): Template = templ match { + case Template(parents0, self0, body0) => + treeCopy.Template(templ, parents0, self0, applyToBody(body0)) + case t => + sys.error("Not a Template: " + t + "/" + t.getClass) + } + def deriveClassDef(cdef: Tree)(applyToImpl: Template => Template): ClassDef = cdef match { + case ClassDef(mods0, name0, tparams0, impl0) => + treeCopy.ClassDef(cdef, mods0, name0, tparams0, applyToImpl(impl0)) + case t => + sys.error("Not a ClassDef: " + t + "/" + t.getClass) + } + def deriveModuleDef(mdef: Tree)(applyToImpl: Template => Template): ModuleDef = mdef match { + case ModuleDef(mods0, name0, impl0) => + treeCopy.ModuleDef(mdef, mods0, name0, applyToImpl(impl0)) + case t => + sys.error("Not a ModuleDef: " + t + "/" + t.getClass) + } + def deriveCaseDef(cdef: Tree)(applyToBody: Tree => Tree): CaseDef = cdef match { + case CaseDef(pat0, guard0, body0) => + treeCopy.CaseDef(cdef, pat0, guard0, applyToBody(body0)) + case t => + sys.error("Not a CaseDef: " + t + "/" + t.getClass) + } + def deriveLabelDef(ldef: Tree)(applyToRhs: Tree => Tree): LabelDef = ldef match { + case LabelDef(name0, params0, rhs0) => + treeCopy.LabelDef(ldef, name0, params0, applyToRhs(rhs0)) + case t => + sys.error("Not a LabelDef: " + t + "/" + t.getClass) + } + + implicit val TreeTag = ClassTag[Tree](classOf[Tree]) + implicit val TermTreeTag = ClassTag[TermTree](classOf[TermTree]) + implicit val TypTreeTag = ClassTag[TypTree](classOf[TypTree]) + implicit val SymTreeTag = ClassTag[SymTree](classOf[SymTree]) + implicit val NameTreeTag = ClassTag[NameTree](classOf[NameTree]) + implicit val RefTreeTag = ClassTag[RefTree](classOf[RefTree]) + implicit val DefTreeTag = ClassTag[DefTree](classOf[DefTree]) + implicit val MemberDefTag = ClassTag[MemberDef](classOf[MemberDef]) + implicit val PackageDefTag = ClassTag[PackageDef](classOf[PackageDef]) + implicit val ImplDefTag = ClassTag[ImplDef](classOf[ImplDef]) + implicit val ClassDefTag = ClassTag[ClassDef](classOf[ClassDef]) + implicit val ModuleDefTag = ClassTag[ModuleDef](classOf[ModuleDef]) + implicit val ValOrDefDefTag = ClassTag[ValOrDefDef](classOf[ValOrDefDef]) + implicit val ValDefTag = ClassTag[ValDef](classOf[ValDef]) + implicit val DefDefTag = ClassTag[DefDef](classOf[DefDef]) + implicit val TypeDefTag = ClassTag[TypeDef](classOf[TypeDef]) + implicit val LabelDefTag = ClassTag[LabelDef](classOf[LabelDef]) + implicit val ImportSelectorTag = ClassTag[ImportSelector](classOf[ImportSelector]) + implicit val ImportTag = ClassTag[Import](classOf[Import]) + implicit val TemplateTag = ClassTag[Template](classOf[Template]) + implicit val BlockTag = ClassTag[Block](classOf[Block]) + implicit val CaseDefTag = ClassTag[CaseDef](classOf[CaseDef]) + implicit val AlternativeTag = ClassTag[Alternative](classOf[Alternative]) + implicit val StarTag = ClassTag[Star](classOf[Star]) + implicit val BindTag = ClassTag[Bind](classOf[Bind]) + implicit val UnApplyTag = ClassTag[UnApply](classOf[UnApply]) + implicit val ArrayValueTag = ClassTag[ArrayValue](classOf[ArrayValue]) + implicit val FunctionTag = ClassTag[Function](classOf[Function]) + implicit val AssignTag = ClassTag[Assign](classOf[Assign]) + implicit val AssignOrNamedArgTag = ClassTag[AssignOrNamedArg](classOf[AssignOrNamedArg]) + implicit val IfTag = ClassTag[If](classOf[If]) + implicit val MatchTag = ClassTag[Match](classOf[Match]) + implicit val ReturnTag = ClassTag[Return](classOf[Return]) + implicit val TryTag = ClassTag[Try](classOf[Try]) + implicit val ThrowTag = ClassTag[Throw](classOf[Throw]) + implicit val NewTag = ClassTag[New](classOf[New]) + implicit val TypedTag = ClassTag[Typed](classOf[Typed]) + implicit val GenericApplyTag = ClassTag[GenericApply](classOf[GenericApply]) + implicit val TypeApplyTag = ClassTag[TypeApply](classOf[TypeApply]) + implicit val ApplyTag = ClassTag[Apply](classOf[Apply]) + implicit val ApplyDynamicTag = ClassTag[ApplyDynamic](classOf[ApplyDynamic]) + implicit val SuperTag = ClassTag[Super](classOf[Super]) + implicit val ThisTag = ClassTag[This](classOf[This]) + implicit val SelectTag = ClassTag[Select](classOf[Select]) + implicit val IdentTag = ClassTag[Ident](classOf[Ident]) + implicit val ReferenceToBoxedTag = ClassTag[ReferenceToBoxed](classOf[ReferenceToBoxed]) + implicit val LiteralTag = ClassTag[Literal](classOf[Literal]) + implicit val AnnotatedTag = ClassTag[Annotated](classOf[Annotated]) + implicit val SingletonTypeTreeTag = ClassTag[SingletonTypeTree](classOf[SingletonTypeTree]) + implicit val SelectFromTypeTreeTag = ClassTag[SelectFromTypeTree](classOf[SelectFromTypeTree]) + implicit val CompoundTypeTreeTag = ClassTag[CompoundTypeTree](classOf[CompoundTypeTree]) + implicit val AppliedTypeTreeTag = ClassTag[AppliedTypeTree](classOf[AppliedTypeTree]) + implicit val TypeBoundsTreeTag = ClassTag[TypeBoundsTree](classOf[TypeBoundsTree]) + implicit val ExistentialTypeTreeTag = ClassTag[ExistentialTypeTree](classOf[ExistentialTypeTree]) + implicit val TypeTreeTag = ClassTag[TypeTree](classOf[TypeTree]) } |