treebuilder.scala

来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 458 行 · 第 1/2 页

SCALA
458
字号
/* NSC -- new Scala compiler * Copyright 2005-2007 LAMP/EPFL * @author  Martin Odersky */// $Id: TreeBuilder.scala 13940 2008-02-10 11:24:46Z odersky $package scala.tools.nsc.ast.parserimport symtab.Flags._import scala.collection.mutable.ListBufferimport scala.tools.nsc.util.Positionabstract class TreeBuilder {  val global: Global  import global._  import posAssigner.atPos;  def freshName(pos : Position, prefix: String): Name  def freshName(pos : Position): Name = freshName(pos, "x$")  def scalaDot(name: Name): Tree =    Select(Ident(nme.scala_) setSymbol definitions.ScalaPackage, name)  def scalaAnyRefConstr: Tree =    scalaDot(nme.AnyRef.toTypeName)  def scalaUnitConstr: Tree =    scalaDot(nme.Unit.toTypeName)  def scalaScalaObjectConstr: Tree =    scalaDot(nme.ScalaObject.toTypeName)  def productConstr: Tree =     scalaDot(nme.Product.toTypeName)  /** Convert all occurrences of (lower-case) variables in a pattern as follows:   *    x                  becomes      x @ _   *    x: T               becomes      x @ (_: T)   */  private object patvarTransformer extends Transformer {    override def transform(tree: Tree): Tree = tree match {      case Ident(name) if (treeInfo.isVarPattern(tree) && name != nme.WILDCARD) =>        atPos(tree.pos)(Bind(name, Ident(nme.WILDCARD)))      case Typed(id @ Ident(name), tpt) if (treeInfo.isVarPattern(id) && name != nme.WILDCARD) =>        Bind(name, atPos(tree.pos)(Typed(Ident(nme.WILDCARD), tpt))) setPos id.pos      case Apply(fn @ Apply(_, _), args) =>        copy.Apply(tree, transform(fn), transformTrees(args))      case Apply(fn, args) =>        copy.Apply(tree, fn, transformTrees(args))      case Typed(expr, tpt) =>        copy.Typed(tree, transform(expr), tpt)      case Bind(name, body) =>        copy.Bind(tree, name, transform(body))      case Sequence(_) | Alternative(_) | Star(_) =>        super.transform(tree)      case _ =>        tree    }  }  /** Traverse pattern and collect all variable names with their types in buffer */   private object getvarTraverser extends Traverser {    val buf = new ListBuffer[(Name, Tree, Position)]    def init: Traverser = { buf.clear; this }    override def traverse(tree: Tree): Unit = tree match {      case Bind(name, Typed(tree1, tpt)) =>        if ((name != nme.WILDCARD) && (buf.elements forall (name !=)))          buf += (name, if (treeInfo.mayBeTypePat(tpt)) TypeTree() else tpt, tree.pos)        traverse(tree1)      case Bind(name, tree1) =>        if ((name != nme.WILDCARD) && (buf.elements forall (name !=)))          buf += (name, TypeTree(), tree.pos)        traverse(tree1)      case _ =>        super.traverse(tree)    }  }  /** Returns list of all pattern variables, possibly with their types,   *  without duplicates   */  private def getVariables(tree: Tree): List[(Name, Tree,Position)] = {    getvarTraverser.init.traverse(tree)    getvarTraverser.buf.toList  }  private def makeTuple(trees: List[Tree], isType: Boolean): Tree = {    val tupString = "Tuple" + trees.length    Apply(scalaDot(if (isType) newTypeName(tupString) else newTermName(tupString)), trees)  }  def makeTupleTerm(trees: List[Tree], flattenUnary: Boolean): Tree = trees match {    case List() => Literal(())    case List(tree) if flattenUnary => tree    case _ => makeTuple(trees, false)  }  def makeTupleType(trees: List[Tree], flattenUnary: Boolean): Tree = trees match {    case List() => scalaUnitConstr    case List(tree) if flattenUnary => tree    case _ => AppliedTypeTree(scalaDot(newTypeName("Tuple" + trees.length)), trees)  }  def stripParens(t: Tree) = t match {    case Parens(ts) => atPos(t.pos) { makeTupleTerm(ts, true) }    case _ => t  }  def makeAnnotated(t: Tree, annot: Annotation): Tree = Annotated(annot, t) setPos annot.pos  def makeSelfDef(name: Name, tpt: Tree): ValDef =    ValDef(Modifiers(PRIVATE), name, tpt, EmptyTree)  /** If tree is a variable pattern, return Some("its name and type").   *  Otherwise return none */  private def matchVarPattern(tree: Tree): Option[(Name, Tree)] = tree match {    case Ident(name) => Some((name, TypeTree()))    case Bind(name, Ident(nme.WILDCARD)) => Some((name, TypeTree()))    case Typed(Ident(name), tpt) => Some((name, tpt))    case Bind(name, Typed(Ident(nme.WILDCARD), tpt)) => Some((name, tpt))    case _ => None  }  /** Create tree representing (unencoded) binary operation expression or pattern. */  def makeBinop(isExpr: Boolean, left: Tree, op: Name, right: Tree): Tree = {    val arguments = right match {      case Parens(args) => args      case _ => List(right)    }    if (isExpr) {      if (treeInfo.isLeftAssoc(op)) {        Apply(Select(stripParens(left), op.encode), arguments)      } else {        val x = freshName(posAssigner.pos);        Block(          List(ValDef(Modifiers(SYNTHETIC), x, TypeTree(), stripParens(left))),          Apply(Select(stripParens(right), op.encode), List(Ident(x))))      }    } else {      Apply(Ident(op.encode), stripParens(left) :: arguments)    }  }  /** Create tree representing an object creation <new parents { stats }> */  def makeNew(parents: List[Tree], self: ValDef, stats: List[Tree], argss: List[List[Tree]]): Tree =    if (parents.isEmpty)      makeNew(List(scalaAnyRefConstr), self, stats, argss)    else if (parents.tail.isEmpty && stats.isEmpty)      New(parents.head, argss)    else {      val x = nme.ANON_CLASS_NAME.toTypeName      Block(        List(ClassDef(          Modifiers(FINAL | SYNTHETIC), x, List(),          Template(parents, self, NoMods, List(List()), argss, stats))),        New(Ident(x), List(List())))    }  /** Create a tree represeting an assignment &lt;lhs = rhs&gt; */  def makeAssign(lhs: Tree, rhs: Tree): Tree = lhs match {    case Apply(fn, args) => Apply(Select(fn, nme.update), args ::: List(rhs))    case _ => Assign(lhs, rhs)  }  /** A type tree corresponding to (possibly unary) intersection type */  def makeIntersectionTypeTree(tps: List[Tree]): Tree =    if (tps.tail.isEmpty) tps.head    else CompoundTypeTree(Template(tps, emptyValDef, List()))  /** Create tree representing a while loop */  def makeWhile(lname: Name, cond: Tree, body: Tree): Tree = {    val continu = Apply(Ident(lname), List())    val rhs = If(cond, Block(List(body), continu), Literal(()))    LabelDef(lname, Nil, rhs)  }  /** Create tree representing a do-while loop */  def makeDoWhile(lname: Name, body: Tree, cond: Tree): Tree = {    val continu = Apply(Ident(lname), List())    val rhs = Block(List(body), If(cond, continu, Literal(())))    LabelDef(lname, Nil, rhs)  }  /** Create block of statements `stats'  */  def makeBlock(stats: List[Tree]): Tree =    if (stats.isEmpty) Literal(())    else if (!stats.last.isTerm) Block(stats, Literal(()))    else if (stats.length == 1) stats.head     else Block(stats.init, stats.last)  /** Create tree for for-comprehension generator &lt;val pat0 &lt;- rhs0&gt; */  def makeGenerator(pos: Position, pat: Tree, valeq: Boolean, rhs: Tree): Enumerator = {    val pat1 = patvarTransformer.transform(pat);    val rhs1 =      if (valeq) rhs      else matchVarPattern(pat1) match {        case Some(_) =>          rhs        case None =>          atPos(pos) {            Apply(              Select(rhs, nme.filter),              List(                makeVisitor(                  List(                    CaseDef(pat1.duplicate, EmptyTree, Literal(true)),                    CaseDef(Ident(nme.WILDCARD), EmptyTree, Literal(false))),                  false,                  nme.CHECK_IF_REFUTABLE_STRING                )))          }      }    if (valeq) ValEq(pos, pat1, rhs1) else ValFrom(pos, pat1, rhs1)  }  def makeSyntheticParam(pname: Name) =     ValDef(Modifiers(PARAM | SYNTHETIC), pname, TypeTree(), EmptyTree)  def makeSyntheticTypeParam(pname: Name, bounds: Tree) =     TypeDef(Modifiers(DEFERRED | SYNTHETIC), pname, List(), bounds)  abstract class Enumerator  case class ValFrom(pos: Position, pat: Tree, rhs: Tree) extends Enumerator  case class ValEq(pos: Position, pat: Tree, rhs: Tree) extends Enumerator  case class Filter(test: Tree) extends Enumerator  /** Create tree for for-comprehension &lt;for (enums) do body&gt; or  *   &lt;for (enums) yield body&gt; where mapName and flatMapName are chosen  *  corresponding to whether this is a for-do or a for-yield.  *  The creation performs the following rewrite rules:  *  *  1.  *

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?