/* NSC -- new Scala compiler * Copyright 2005-2011 LAMP/EPFL * @author Martin Odersky */ package scala.reflect package internal import java.io.{PrintWriter, StringWriter} import scala.collection.mutable.ListBuffer import Flags._ import api.Modifier //import scala.tools.nsc.util.{ FreshNameCreator, HashSet, SourceFile } trait Trees extends api.Trees { self: SymbolTable => // --- modifiers implementation --------------------------------------- /** @param privateWithin the qualifier for a private (a type name) * or tpnme.EMPTY, if none is given. * @param annotations the annotations for the definition. * '''Note:''' the typechecker drops these annotations, * use the AnnotationInfo's (Symbol.annotations) in later phases. */ case class Modifiers(flags: Long, privateWithin: Name, annotations: List[Tree], positions: Map[Long, Position]) extends AbsModifiers with HasFlags { /* Abstract types from HasFlags. */ type FlagsType = Long type AccessBoundaryType = Name type AnnotationType = Tree def hasAccessBoundary = privateWithin != tpnme.EMPTY def hasAllFlags(mask: Long): Boolean = (flags & mask) == mask def hasFlag(flag: Long) = (flag & flags) != 0L def hasFlagsToString(mask: Long): String = flagsToString( flags & mask, if (hasAccessBoundary) privateWithin.toString else "" ) def & (flag: Long): Modifiers = { val flags1 = flags & flag if (flags1 == flags) this else Modifiers(flags1, privateWithin, annotations, positions) } def &~ (flag: Long): Modifiers = { val flags1 = flags & (~flag) if (flags1 == flags) this else Modifiers(flags1, privateWithin, annotations, positions) } def | (flag: Long): Modifiers = { val flags1 = flags | flag if (flags1 == flags) this else Modifiers(flags1, privateWithin, annotations, positions) } def withAnnotations(annots: List[Tree]) = if (annots.isEmpty) this else copy(annotations = annotations ::: annots) def withPosition(flag: Long, position: Position) = copy(positions = positions + (flag -> position)) override def hasModifier(mod: Modifier.Value) = hasFlag(flagOfModifier(mod)) override def allModifiers: Set[Modifier.Value] = Modifier.values filter hasModifier override def mapAnnotations(f: List[Tree] => List[Tree]): Modifiers = Modifiers(flags, privateWithin, f(annotations), positions) override def toString = "Modifiers(%s, %s, %s)".format(hasFlagsToString(-1L), annotations mkString ", ", positions) } def Modifiers(flags: Long, privateWithin: Name): Modifiers = Modifiers(flags, privateWithin, List(), Map.empty) def Modifiers(flags: Long): Modifiers = Modifiers(flags, tpnme.EMPTY) def Modifiers(mods: Set[Modifier.Value], privateWithin: Name, annotations: List[Tree]): Modifiers = { val flagSet = mods map flagOfModifier Modifiers((0L /: flagSet)(_ | _), privateWithin, annotations, Map.empty) } lazy val NoMods = Modifiers(0) // --- extension methods -------------------------------------------------------- override def show(tree: Tree): String = { val buffer = new StringWriter() val printer = newTreePrinter(new PrintWriter(buffer)) printer.print(tree) printer.flush() buffer.toString } implicit def treeOps(tree: Tree): TreeOps = new TreeOps(tree) class TreeOps(tree: Tree) { def isErroneous = (tree.tpe ne null) && tree.tpe.isErroneous def isTyped = (tree.tpe ne null) && !tree.tpe.isErroneous /** 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 shallowDuplicate: Tree = new ShallowDuplicator(tree) transform tree def shortClass: String = this.getClass.getName split "[.$]" last } // ---- values and creators --------------------------------------- /** @param sym the class symbol * @return the implementation template */ def ClassDef(sym: Symbol, impl: Template): ClassDef = atPos(sym.pos) { ClassDef(Modifiers(sym.flags), sym.name.toTypeName, sym.typeParams map TypeDef, impl) setSymbol sym } /** * @param sym the class symbol * @param impl the implementation template */ def ModuleDef(sym: Symbol, impl: Template): ModuleDef = atPos(sym.pos) { ModuleDef(Modifiers(sym.flags), sym.name, impl) setSymbol sym } def ValDef(sym: Symbol, rhs: Tree): ValDef = atPos(sym.pos) { ValDef(Modifiers(sym.flags), sym.name, TypeTree(sym.tpe) setPos focusPos(sym.pos), rhs) setSymbol sym } def ValDef(sym: Symbol): ValDef = ValDef(sym, EmptyTree) object emptyValDef extends ValDef(Modifiers(PRIVATE), nme.WILDCARD, TypeTree(NoType), EmptyTree) { override def isEmpty = true super.setPos(NoPosition) override def setPos(pos: Position) = { assert(false); this } } def DefDef(sym: Symbol, mods: Modifiers, vparamss: List[List[ValDef]], rhs: Tree): DefDef = atPos(sym.pos) { assert(sym != NoSymbol) DefDef(Modifiers(sym.flags), sym.name, sym.typeParams map TypeDef, vparamss, TypeTree(sym.tpe.finalResultType) setPos focusPos(sym.pos), rhs) setSymbol sym } def DefDef(sym: Symbol, vparamss: List[List[ValDef]], rhs: Tree): DefDef = DefDef(sym, Modifiers(sym.flags), vparamss, rhs) def DefDef(sym: Symbol, mods: Modifiers, rhs: Tree): DefDef = DefDef(sym, mods, sym.paramss map (_.map(ValDef)), rhs) def DefDef(sym: Symbol, rhs: Tree): DefDef = DefDef(sym, Modifiers(sym.flags), rhs) def DefDef(sym: Symbol, rhs: List[List[Symbol]] => Tree): DefDef = { DefDef(sym, rhs(sym.info.paramss)) } /** A TypeDef node which defines given `sym` with given tight hand side `rhs`. */ def TypeDef(sym: Symbol, rhs: Tree): TypeDef = atPos(sym.pos) { TypeDef(Modifiers(sym.flags), sym.name.toTypeName, sym.typeParams map TypeDef, rhs) setSymbol sym } /** A TypeDef node which defines abstract type or type parameter for given `sym` */ def TypeDef(sym: Symbol): TypeDef = TypeDef(sym, TypeBoundsTree(TypeTree(sym.info.bounds.lo), TypeTree(sym.info.bounds.hi))) def LabelDef(sym: Symbol, params: List[Symbol], rhs: Tree): LabelDef = atPos(sym.pos) { LabelDef(sym.name, params map Ident, rhs) setSymbol sym } /** casedef shorthand */ def CaseDef(pat: Tree, body: Tree): CaseDef = CaseDef(pat, EmptyTree, body) def Bind(sym: Symbol, body: Tree): Bind = Bind(sym.name, body) setSymbol sym /** Factory method for object creation `new tpt(args_1)...(args_n)` * A `New(t, as)` is expanded to: `(new t).(as)` */ def New(tpt: Tree, argss: List[List[Tree]]): Tree = { assert(!argss.isEmpty) val superRef: Tree = Select(New(tpt), nme.CONSTRUCTOR) (superRef /: argss) (Apply) } def Apply(sym: Symbol, args: Tree*): Tree = Apply(Ident(sym), args.toList) def Super(sym: Symbol, mix: TypeName): Tree = Super(This(sym), mix) def This(sym: Symbol): Tree = This(sym.name.toTypeName) setSymbol sym def Select(qualifier: Tree, sym: Symbol): Select = Select(qualifier, sym.name) setSymbol sym def Ident(sym: Symbol): Ident = Ident(sym.name) setSymbol sym /** Block factory that flattens directly nested blocks. */ def Block(stats: Tree*): Block = stats match { case Seq(b @ Block(_, _)) => b case Seq(stat) => Block(stats.toList, Literal(Constant(()))) case Seq(_, rest @ _*) => Block(stats.init.toList, stats.last) } // --- specific traversers and transformers protected[scala] def duplicateTree(tree: Tree): Tree = duplicator transform 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) && isRangePos(t1.pos)) t1 setPos focusPos(t.pos) t1 } } private object posAssigner extends Traverser { var pos: Position = _ override def traverse(t: Tree) { if (t != EmptyTree && t.pos == NoPosition) { t.setPos(pos) super.traverse(t) } } } def atPos[T <: Tree](pos: Position)(tree: T): T = { posAssigner.pos = pos posAssigner.traverse(tree) tree } class ForeachPartialTreeTraverser(pf: PartialFunction[Tree, Tree]) extends Traverser { override def traverse(tree: Tree) { val t = if (pf isDefinedAt tree) pf(tree) else tree super.traverse(t) } } class ChangeOwnerTraverser(val oldowner: Symbol, val newowner: Symbol) extends Traverser { def changeOwner(tree: Tree) = { if ((tree.isDef || tree.isInstanceOf[Function]) && tree.symbol != NoSymbol && tree.symbol.owner == oldowner) tree.symbol.owner = newowner } override def traverse(tree: Tree) { changeOwner(tree) super.traverse(tree) } } private class ShallowDuplicator(orig: Tree) extends Transformer { override val treeCopy = newStrictTreeCopier override def transform(tree: Tree) = if (tree eq orig) super.transform(tree) else tree } // Create a readable string describing a substitution. private def substituterString(fromStr: String, toStr: String, from: List[Any], to: List[Any]): String = { "subst[%s, %s](%s)".format(fromStr, toStr, (from, to).zipped map (_ + " -> " + _) mkString ", ") } class TreeSubstituter(from: List[Symbol], to: List[Tree]) extends Transformer { override def transform(tree: Tree): Tree = tree match { case Ident(_) => def subst(from: List[Symbol], to: List[Tree]): Tree = if (from.isEmpty) tree else if (tree.symbol == from.head) to.head else subst(from.tail, to.tail); subst(from, to) case _ => super.transform(tree) } override def toString = substituterString("Symbol", "Tree", from, to) } class TreeTypeSubstituter(val from: List[Symbol], val to: List[Type]) extends Traverser { val typeSubst = new SubstTypeMap(from, to) def fromContains = typeSubst.fromContains def isEmpty = from.isEmpty && to.isEmpty override def traverse(tree: Tree) { if (tree.tpe ne null) tree.tpe = typeSubst(tree.tpe) if (tree.isDef) { val sym = tree.symbol val info1 = typeSubst(sym.info) if (info1 ne sym.info) sym.setInfo(info1) } super.traverse(tree) } override def apply[T <: Tree](tree: T): T = super.apply(tree.duplicate) override def toString() = "TreeTypeSubstituter("+from+","+to+")" } lazy val EmptyTreeTypeSubstituter = new TreeTypeSubstituter(List(), List()) class TreeSymSubstTraverser(val from: List[Symbol], val to: List[Symbol]) extends Traverser { val subst = new SubstSymMap(from, to) override def traverse(tree: Tree) { if (tree.tpe ne null) tree.tpe = subst(tree.tpe) if (tree.isDef) { val sym = tree.symbol val info1 = subst(sym.info) if (info1 ne sym.info) sym.setInfo(info1) } super.traverse(tree) } override def apply[T <: Tree](tree: T): T = super.apply(tree.duplicate) override def toString() = "TreeSymSubstTraverser/" + substituterString("Symbol", "Symbol", from, to) } /** Substitute symbols in `from` with symbols in `to`. Returns a new * tree using the new symbols and whose Ident and Select nodes are * name-consistent with the new symbols. */ class TreeSymSubstituter(from: List[Symbol], to: List[Symbol]) extends Transformer { val symSubst = new SubstSymMap(from, to) override def transform(tree: Tree): Tree = { def subst(from: List[Symbol], to: List[Symbol]) { if (!from.isEmpty) if (tree.symbol == from.head) tree setSymbol to.head else subst(from.tail, to.tail) } if (tree.tpe ne null) tree.tpe = symSubst(tree.tpe) if (tree.hasSymbol) { subst(from, to) tree match { case Ident(name0) if tree.symbol != NoSymbol => treeCopy.Ident(tree, tree.symbol.name) case Select(qual, name0) => treeCopy.Select(tree, transform(qual), tree.symbol.name) case _ => super.transform(tree) } } else super.transform(tree) } def apply[T <: Tree](tree: T): T = transform(tree).asInstanceOf[T] override def toString() = "TreeSymSubstituter/" + substituterString("Symbol", "Symbol", from, to) } }