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 <lhs = rhs> */ 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 <val pat0 <- rhs0> */ 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 <for (enums) do body> or * <for (enums) yield body> 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 + -
显示快捷键?