All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scala.reflect.generic.Trees.scala Maven / Gradle / Ivy

package scala.reflect
package generic

import java.io.{PrintWriter, StringWriter}
import Flags._

trait Trees { self: Universe =>

  abstract class AbsTreePrinter(out: PrintWriter) {
    def print(tree: Tree)
    def flush()
  }

  def newTreePrinter(out: PrintWriter): AbsTreePrinter

  private[scala] var nodeCount = 0

  /** @param privateWithin the qualifier for a private (a type name)
   *    or nme.EMPTY.toTypeName, 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]) {
    def isAbstract      = hasFlag(ABSTRACT )
    def isAccessor      = hasFlag(ACCESSOR )
    def isArgument      = hasFlag(PARAM    )
    def isCase          = hasFlag(CASE     )
    def isContravariant = hasFlag(CONTRAVARIANT)  // marked with `-'
    def isCovariant     = hasFlag(COVARIANT    )  // marked with `+'
    def isDeferred      = hasFlag(DEFERRED )
    def isFinal         = hasFlag(FINAL    )
    def isImplicit      = hasFlag(IMPLICIT )
    def isLazy          = hasFlag(LAZY     )
    def isOverride      = hasFlag(OVERRIDE )
    def isPrivate       = hasFlag(PRIVATE  )
    def isProtected     = hasFlag(PROTECTED)
    def isPublic        = !isPrivate && !isProtected
    def isSealed        = hasFlag(SEALED   )
    def isSynthetic     = hasFlag(SYNTHETIC)
    def isTrait         = hasFlag(TRAIT    )
    def isVariable      = hasFlag(MUTABLE  )
    
    def hasFlag(flag: Long) = (flag & flags) != 0L
    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))
  }

  def Modifiers(flags: Long, privateWithin: Name): Modifiers = Modifiers(flags, privateWithin, List(), Map.empty)
  def Modifiers(flags: Long): Modifiers = Modifiers(flags, mkTypeName(nme.EMPTY))

  lazy val NoMods = Modifiers(0)

  abstract class Tree extends Product {
    val id = nodeCount
    nodeCount += 1

    private[this] var rawpos: Position = NoPosition

    def pos = rawpos
    def pos_=(pos: Position) = rawpos = pos
    def setPos(pos: Position): this.type = { rawpos = pos; this }

    private[this] var rawtpe: Type = _

    def tpe = rawtpe
    def tpe_=(t: Type) = rawtpe = t

    /** Set tpe to give `tp` and return this.
     */
    def setType(tp: Type): this.type = { rawtpe = tp; this } 

    /** Like `setType`, but if this is a previously empty TypeTree
     *  that fact is remembered so that resetType will snap back.
     */
    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 direct child trees of this tree
     *  EmptyTrees are always omitted. Lists are collapsed.
     */
    def children: List[Tree] = {
      def subtrees(x: Any): List[Tree] = x match {
        case EmptyTree => List()
        case t: Tree => List(t)
        case xs: List[_] => xs flatMap subtrees
        case _ => List()
      }
      productIterator.toList flatMap subtrees
    }

    /** In compiler: Make a copy of this tree, keeping all attributes,
     *  except that all positions are focussed (so nothing
     *  in this tree will be found when searching by position).
     *  If not in compiler may also return tree unchanged.
     */
    private[scala] def duplicate: this.type = 
      duplicateTree(this).asInstanceOf[this.type]

    private[scala] def copyAttrs(tree: Tree): this.type = {
      pos = tree.pos
      tpe = tree.tpe
      if (hasSymbol) symbol = tree.symbol
      this
    }

    override def toString(): String = {
      val buffer = new StringWriter()
      val printer = newTreePrinter(new PrintWriter(buffer))
      printer.print(this)
      printer.flush()
      buffer.toString     
    }

    override def hashCode(): Int = super.hashCode()

    override def equals(that: Any): Boolean = that match {
      case t: Tree => this eq t
      case _ => false
    }
  }

  private[scala] def duplicateTree(tree: Tree): Tree = tree

  trait SymTree extends Tree {
    override def hasSymbol = true
    override var symbol: Symbol = NoSymbol
  }

  trait RefTree extends SymTree {
    def name: Name
  }

  abstract class DefTree extends SymTree {
    def name: Name
    override def isDef = true
  }

  trait TermTree extends Tree 

  /** A tree for a type.  Note that not all type trees implement
    * this trait; in particular, Ident's are an exception. */
  trait TypTree extends Tree 

// ----- tree node alternatives --------------------------------------

  /** The empty tree */
  case object EmptyTree extends TermTree {
    super.tpe_=(NoType)
    override def tpe_=(t: Type) = 
      if (t != NoType) throw new UnsupportedOperationException("tpe_=("+t+") inapplicable for ")
    override def isEmpty = true
  }

  abstract class MemberDef extends DefTree {
    def mods: Modifiers
    def keyword: String = this match {
      case TypeDef(_, _, _, _)      => "type"
      case ClassDef(mods, _, _, _)  => if (mods.isTrait) "trait" else "class"
      case DefDef(_, _, _, _, _, _) => "def"
      case ModuleDef(_, _, _)       => "object"
      case PackageDef(_, _)         => "package"
      case ValDef(mods, _, _, _)    => if (mods.isVariable) "var" else "val"
      case _ => ""
    }
    final def hasFlag(mask: Long): Boolean = (mods.flags & mask) != 0L
  }

  /** Package clause
   */
  case class PackageDef(pid: RefTree, stats: List[Tree])
       extends MemberDef {
    def name = pid.name
    def mods = NoMods
  }

  abstract class ImplDef extends MemberDef {
    def impl: Template
  }

  /** Class definition */
  case class ClassDef(mods: Modifiers, name: Name, tparams: List[TypeDef], impl: Template)
       extends ImplDef

  /** Singleton object definition
   */
  case class ModuleDef(mods: Modifiers, name: Name, impl: Template)
       extends ImplDef

  abstract class ValOrDefDef extends MemberDef {
    def tpt: Tree
    def rhs: Tree
  }

  /** Value definition
   */
  case class ValDef(mods: Modifiers, name: Name, tpt: Tree, rhs: Tree) extends ValOrDefDef

  /** Method definition
   */
  case class DefDef(mods: Modifiers, name: Name, tparams: List[TypeDef],
                    vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree) extends ValOrDefDef

  /** Abstract type, type parameter, or type alias */
  case class TypeDef(mods: Modifiers, name: Name, tparams: List[TypeDef], rhs: Tree) 
       extends MemberDef 

  /** 

* Labelled expression - the symbols in the array (must be Idents!) * are those the label takes as argument *

*

* The symbol that is given to the labeldef should have a MethodType * (as if it were a nested function) *

*

* Jumps are apply nodes attributed with label symbol, the arguments * will get assigned to the idents. *

*

* Note: on 2005-06-09 Martin, Iuli, Burak agreed to have forward * jumps within a Block. *

*/ case class LabelDef(name: Name, params: List[Ident], rhs: Tree) extends DefTree with TermTree /** Import selector * * Representation of an imported name its optional rename and their optional positions * * @param name the imported name * @param namePos its position or -1 if undefined * @param rename the name the import is renamed to (== name if no renaming) * @param renamePos the position of the rename or -1 if undefined */ case class ImportSelector(name: Name, namePos: Int, rename: Name, renamePos: Int) /** Import clause * * @param expr * @param selectors */ case class Import(expr: Tree, selectors: List[ImportSelector]) extends SymTree // The symbol of an Import is an import symbol @see Symbol.newImport // It's used primarily as a marker to check that the import has been typechecked. /** Instantiation template of a class or trait * * @param parents * @param body */ case class Template(parents: List[Tree], self: ValDef, body: List[Tree]) extends SymTree { // the symbol of a template is a local dummy. @see Symbol.newLocalDummy // the owner of the local dummy is the enclosing trait or class. // the local dummy is itself the owner of any local blocks // For example: // // class C { // def foo // owner is C // { // def bar // owner is local dummy // } // System.err.println("TEMPLATE: " + parents) } /** Block of expressions (semicolon separated expressions) */ case class Block(stats: List[Tree], expr: Tree) extends TermTree /** Case clause in a pattern match, eliminated by TransMatch * (except for occurrences in switch statements) */ case class CaseDef(pat: Tree, guard: Tree, body: Tree) extends Tree /** Alternatives of patterns, eliminated by TransMatch, except for * occurrences in encoded Switch stmt (=remaining Match(CaseDef(...)) */ case class Alternative(trees: List[Tree]) extends TermTree /** Repetition of pattern, eliminated by TransMatch */ case class Star(elem: Tree) extends TermTree /** Bind of a variable to a rhs pattern, eliminated by TransMatch * * @param name * @param body */ case class Bind(name: Name, body: Tree) extends DefTree case class UnApply(fun: Tree, args: List[Tree]) extends TermTree /** Array of expressions, needs to be translated in backend, */ case class ArrayValue(elemtpt: Tree, elems: List[Tree]) extends TermTree /** Anonymous function, eliminated by analyzer */ case class Function(vparams: List[ValDef], body: Tree) extends TermTree with SymTree // The symbol of a Function is a synthetic value of name nme.ANON_FUN_NAME // It is the owner of the function's parameters. /** Assignment */ case class Assign(lhs: Tree, rhs: Tree) extends TermTree /** Conditional expression */ case class If(cond: Tree, thenp: Tree, elsep: Tree) extends TermTree /**

* Pattern matching expression (before TransMatch) * Switch statements (after TransMatch) *

*

* After TransMatch, cases will satisfy the following * constraints: *

*
    *
  • all guards are EmptyTree,
  • *
  • all patterns will be either Literal(Constant(x:Int)) * or Alternative(lit|...|lit)
  • *
  • except for an "otherwise" branch, which has pattern * Ident(nme.WILDCARD)
  • *
*/ case class Match(selector: Tree, cases: List[CaseDef]) extends TermTree /** Return expression */ case class Return(expr: Tree) extends TermTree with SymTree // The symbol of a Return node is the enclosing method. case class Try(block: Tree, catches: List[CaseDef], finalizer: Tree) extends TermTree /** Throw expression */ case class Throw(expr: Tree) extends TermTree /** Object instantiation * One should always use factory method below to build a user level new. * * @param tpt a class type */ case class New(tpt: Tree) extends TermTree /** Type annotation, eliminated by explicit outer */ case class Typed(expr: Tree, tpt: Tree) extends TermTree // Martin to Sean: Should GenericApply/TypeApply/Apply not be SymTree's? After all, // ApplyDynamic is a SymTree. abstract class GenericApply extends TermTree { val fun: Tree val args: List[Tree] } /** Type application */ case class TypeApply(fun: Tree, args: List[Tree]) extends GenericApply { override def symbol: Symbol = fun.symbol override def symbol_=(sym: Symbol) { fun.symbol = sym } } /** Value application */ case class Apply(fun: Tree, args: List[Tree]) extends GenericApply { override def symbol: Symbol = fun.symbol override def symbol_=(sym: Symbol) { fun.symbol = sym } } /** Dynamic value application. * In a dynamic application q.f(as) * - q is stored in qual * - as is stored in args * - f is stored as the node's symbol field. */ case class ApplyDynamic(qual: Tree, args: List[Tree]) extends TermTree with SymTree // The symbol of an ApplyDynamic is the function symbol of `qual', or NoSymbol, if there is none. /** Super reference */ case class Super(qual: Name, mix: Name) extends TermTree with SymTree // The symbol of a Super is the class _from_ which the super reference is made. // For instance in C.super(...), it would be C. /** Self reference */ case class This(qual: Name) extends TermTree with SymTree // The symbol of a This is the class to which the this refers. // For instance in C.this, it would be C. /** Designator . */ case class Select(qualifier: Tree, name: Name) extends RefTree /** Identifier */ case class Ident(name: Name) extends RefTree class BackQuotedIdent(name: Name) extends Ident(name) /** Literal */ case class Literal(value: Constant) extends TermTree { assert(value ne null) } def Literal(value: Any): Literal = Literal(Constant(value)) type TypeTree <: AbsTypeTree val TypeTree: TypeTreeExtractor abstract class TypeTreeExtractor { def apply(): TypeTree def unapply(tree: TypeTree): Boolean } class Traverser { protected var currentOwner: Symbol = definitions.RootClass def traverse(tree: Tree): Unit = tree match { case EmptyTree => ; case PackageDef(pid, stats) => traverse(pid) atOwner(tree.symbol.moduleClass) { traverseTrees(stats) } case ClassDef(mods, name, tparams, impl) => atOwner(tree.symbol) { traverseTrees(mods.annotations); traverseTrees(tparams); traverse(impl) } case ModuleDef(mods, name, impl) => atOwner(tree.symbol.moduleClass) { 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 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(_, _) => ; case This(_) => ; case Select(qualifier, selector) => traverse(qualifier) case Ident(_) => ; 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 SelectFromArray(qualifier, selector, erasure) => traverse(qualifier) } def traverseTrees(trees: List[Tree]) { trees foreach traverse } def traverseTreess(treess: List[List[Tree]]) { treess foreach traverseTrees } def traverseStats(stats: List[Tree], exprOwner: Symbol) { stats foreach (stat => if (exprOwner != currentOwner) atOwner(exprOwner)(traverse(stat)) else traverse(stat) ) } def atOwner(owner: Symbol)(traverse: => Unit) { val prevOwner = currentOwner currentOwner = owner traverse currentOwner = prevOwner } } /** A synthetic term holding an arbitrary type. Not to be confused with * with TypTree, the trait for trees that are only used for type trees. * TypeTree's are inserted in several places, but most notably in * RefCheck, where the arbitrary type trees are all replaced by * TypeTree's. */ abstract class AbsTypeTree extends TypTree { override def symbol = if (tpe == null) null else tpe.typeSymbol override def isEmpty = (tpe eq null) || tpe == NoType } /** A tree that has an annotation attached to it. Only used for annotated types and * annotation ascriptions, annotations on definitions are stored in the Modifiers. * Eliminated by typechecker (typedAnnotated), the annotations are then stored in * an AnnotatedType. */ case class Annotated(annot: Tree, arg: Tree) extends Tree /** Singleton type, eliminated by RefCheck */ case class SingletonTypeTree(ref: Tree) extends TypTree /** Type selection # , eliminated by RefCheck */ case class SelectFromTypeTree(qualifier: Tree, name: Name) extends TypTree with RefTree /** Intersection type with ... with { }, eliminated by RefCheck */ case class CompoundTypeTree(templ: Template) extends TypTree /** Applied type [ ], eliminated by RefCheck */ case class AppliedTypeTree(tpt: Tree, args: List[Tree]) extends TypTree { override def symbol: Symbol = tpt.symbol override def symbol_=(sym: Symbol) { tpt.symbol = sym } } case class TypeBoundsTree(lo: Tree, hi: Tree) extends TypTree case class ExistentialTypeTree(tpt: Tree, whereClauses: List[Tree]) extends TypTree /** Array selection . only used during erasure */ case class SelectFromArray(qualifier: Tree, name: Name, erasure: Type) extends TermTree with RefTree { } /* A standard pattern match case EmptyTree => case PackageDef(pid, stats) => // package pid { stats } case ClassDef(mods, name, tparams, impl) => // mods class name [tparams] impl where impl = extends parents { defs } case ModuleDef(mods, name, impl) => (eliminated by refcheck) // mods object name impl where impl = extends parents { defs } case ValDef(mods, name, tpt, rhs) => // mods val name: tpt = rhs // note missing type information is expressed by tpt = TypeTree() case DefDef(mods, name, tparams, vparamss, tpt, rhs) => // mods def name[tparams](vparams_1)...(vparams_n): tpt = rhs // note missing type information is expressed by tpt = TypeTree() case TypeDef(mods, name, tparams, rhs) => (eliminated by erasure) // mods type name[tparams] = rhs // mods type name[tparams] >: lo <: hi, where lo, hi are in a TypeBoundsTree, and DEFERRED is set in mods case LabelDef(name, params, rhs) => // used for tailcalls and like // while/do are desugared to label defs as follows: // while (cond) body ==> LabelDef($L, List(), if (cond) { body; L$() } else ()) // do body while (cond) ==> LabelDef($L, List(), body; if (cond) L$() else ()) case Import(expr, selectors) => (eliminated by typecheck) // import expr.{selectors} // Selectors are a list of pairs of names (from, to). // The last (and maybe only name) may be a nme.WILDCARD // for instance // import qual.{x, y => z, _} would be represented as // Import(qual, List(("x", "x"), ("y", "z"), (WILDCARD, null))) case Template(parents, self, body) => // extends parents { self => body } // if self is missing it is represented as emptyValDef case Block(stats, expr) => // { stats; expr } case CaseDef(pat, guard, body) => (eliminated by transmatch/explicitouter) // case pat if guard => body case Alternative(trees) => (eliminated by transmatch/explicitouter) // pat1 | ... | patn case Star(elem) => (eliminated by transmatch/explicitouter) // pat* case Bind(name, body) => (eliminated by transmatch/explicitouter) // name @ pat case UnApply(fun: Tree, args) (introduced by typer, eliminated by transmatch/explicitouter) // used for unapply's case ArrayValue(elemtpt, trees) => (introduced by uncurry) // used to pass arguments to vararg arguments // for instance, printf("%s%d", foo, 42) is translated to after uncurry to: // Apply( // Ident("printf"), // Literal("%s%d"), // ArrayValue(, List(Ident("foo"), Literal(42)))) case Function(vparams, body) => (eliminated by lambdaLift) // vparams => body where vparams:List[ValDef] case Assign(lhs, rhs) => // lhs = rhs case If(cond, thenp, elsep) => // if (cond) thenp else elsep case Match(selector, cases) => // selector match { cases } case Return(expr) => // return expr case Try(block, catches, finalizer) => // try block catch { catches } finally finalizer where catches: List[CaseDef] case Throw(expr) => // throw expr case New(tpt) => // new tpt always in the context: (new tpt).[targs](args) case Typed(expr, tpt) => (eliminated by erasure) // expr: tpt case TypeApply(fun, args) => // fun[args] case Apply(fun, args) => // fun(args) // for instance fun[targs](args) is expressed as Apply(TypeApply(fun, targs), args) case ApplyDynamic(qual, args) (introduced by erasure, eliminated by cleanup) // fun(args) case Super(qual, mix) => // qual.super[mix] if qual and/or mix is empty, ther are nme.EMPTY.toTypeName case This(qual) => // qual.this case Select(qualifier, selector) => // qualifier.selector case Ident(name) => // name // note: type checker converts idents that refer to enclosing fields or methods // to selects; name ==> this.name case Literal(value) => // value case TypeTree() => (introduced by refcheck) // a type that's not written out, but given in the tpe attribute case Annotated(annot, arg) => (eliminated by typer) // arg @annot for types, arg: @annot for exprs case SingletonTypeTree(ref) => (eliminated by uncurry) // ref.type case SelectFromTypeTree(qualifier, selector) => (eliminated by uncurry) // qualifier # selector, a path-dependent type p.T is expressed as p.type # T case CompoundTypeTree(templ: Template) => (eliminated by uncurry) // parent1 with ... with parentN { refinement } case AppliedTypeTree(tpt, args) => (eliminated by uncurry) // tpt[args] case TypeBoundsTree(lo, hi) => (eliminated by uncurry) // >: lo <: hi case ExistentialTypeTree(tpt, whereClauses) => (eliminated by uncurry) // tpt forSome { whereClauses } */ }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy