From 943d2cfb07cb978e096eead09dc24581a0974333 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 19 Nov 2011 18:41:06 +0000 Subject: Partial cleanup and generalization of tree prin... Partial cleanup and generalization of tree printing. You can now print a tree in direct case class form with `showRaw(tree)`. Should make NodePrinters redundant. --- .../scala/reflect/internal/TreePrinters.scala | 141 +++++++++------------ src/compiler/scala/reflect/internal/Trees.scala | 9 -- src/compiler/scala/tools/nsc/Global.scala | 2 +- .../scala/tools/nsc/ast/TreePrinters.scala | 120 ++++++++---------- 4 files changed, 116 insertions(+), 156 deletions(-) (limited to 'src/compiler') diff --git a/src/compiler/scala/reflect/internal/TreePrinters.scala b/src/compiler/scala/reflect/internal/TreePrinters.scala index e5b9fafa00..c86cd9b29c 100644 --- a/src/compiler/scala/reflect/internal/TreePrinters.scala +++ b/src/compiler/scala/reflect/internal/TreePrinters.scala @@ -9,7 +9,7 @@ package internal import java.io.{ OutputStream, PrintWriter, StringWriter, Writer } import Flags._ -trait TreePrinters { self: SymbolTable => +trait TreePrinters extends api.TreePrinters { self: SymbolTable => //nsc import treeInfo.{ IsTrue, IsFalse } @@ -33,17 +33,18 @@ trait TreePrinters { self: SymbolTable => case _ => t.toString } - class TreePrinter(out: PrintWriter) { + class TreePrinter(out: PrintWriter) extends super.TreePrinter { protected var indentMargin = 0 protected val indentStep = 2 protected var indentString = " " // 40 - def flush() = out.flush() + typesPrinted = settings.printtypes.value + uniqueIds = settings.uniqid.value + protected def doPrintPositions = settings.Xprintpos.value def indent() = indentMargin += indentStep def undent() = indentMargin -= indentStep - protected def doPrintPositions = settings.Xprintpos.value def printPosition(tree: Tree) = if (doPrintPositions) print(showPos(tree.pos)) def println() { @@ -64,11 +65,11 @@ trait TreePrinters { self: SymbolTable => def printColumn(ts: List[Tree], start: String, sep: String, end: String) { print(start); indent; println() - printSeq(ts){print}{print(sep); println()}; undent; println(); print(end) + printSeq(ts){print(_)}{print(sep); println()}; undent; println(); print(end) } def printRow(ts: List[Tree], start: String, sep: String, end: String) { - print(start); printSeq(ts){print}{print(sep)}; print(end) + print(start); printSeq(ts){print(_)}{print(sep)}; print(end) } def printRow(ts: List[Tree], sep: String) { printRow(ts, "", sep, "") } @@ -120,7 +121,8 @@ trait TreePrinters { self: SymbolTable => private def symNameInternal(tree: Tree, name: Name, decoded: Boolean): String = { def nameFn(sym: Symbol) = { val prefix = if (sym.isMixinConstructor) "/*%s*/".format(quotedName(sym.owner.name, decoded)) else "" - prefix + tree.symbol.nameString + val suffix = if (uniqueIds) "#"+sym.id else "" + prefix + tree.symbol.decodedName + suffix } symFn(tree, nameFn, quotedName(name, decoded)) } @@ -129,7 +131,7 @@ trait TreePrinters { self: SymbolTable => def symName(tree: Tree, name: Name) = symNameInternal(tree, name, false) def printOpt(prefix: String, tree: Tree) { - if (!tree.isEmpty) { print(prefix); print(tree) } + if (!tree.isEmpty) { print(prefix, tree) } } def printModifiers(tree: Tree, mods: Modifiers): Unit = printFlags( @@ -154,13 +156,10 @@ trait TreePrinters { self: SymbolTable => annots foreach (annot => print("@"+annot+" ")) } - def print(str: String) { out.print(str) } - def print(name: Name) { print(quotedName(name)) } - private var currentOwner: Symbol = NoSymbol private var selectorType: Type = NoType - def printRaw(tree: Tree) { + def printTree(tree: Tree) { tree match { case EmptyTree => print("") @@ -173,29 +172,26 @@ trait TreePrinters { self: SymbolTable => else if (ifSym(tree, _.isModuleClass)) "object" else "class" - print(word + " " + symName(tree, name)) + print(word, " ", symName(tree, name)) printTypeParams(tparams) - print(if (mods.isDeferred) " <: " else " extends "); print(impl) + print(if (mods.isDeferred) " <: " else " extends ", impl) case PackageDef(packaged, stats) => printAnnotations(tree) - print("package "); print(packaged); printColumn(stats, " {", ";", "}") + print("package ", packaged); printColumn(stats, " {", ";", "}") case ModuleDef(mods, name, impl) => printAnnotations(tree) - printModifiers(tree, mods); print("object " + symName(tree, name)) - print(" extends "); print(impl) + printModifiers(tree, mods); + print("object " + symName(tree, name), " extends ", impl) case ValDef(mods, name, tp, rhs) => printAnnotations(tree) printModifiers(tree, mods) - print(if (mods.isMutable) "var " else "val ") - print(symName(tree, name)) + print(if (mods.isMutable) "var " else "val ", symName(tree, name)) printOpt(": ", tp) - if (!mods.isDeferred) { - print(" = ") - if (rhs.isEmpty) print("_") else print(rhs) - } + if (!mods.isDeferred) + print(" = ", if (rhs.isEmpty) "_" else rhs) case DefDef(mods, name, tparams, vparamss, tp, rhs) => printAnnotations(tree) @@ -225,16 +221,12 @@ trait TreePrinters { self: SymbolTable => if (isNotRemap(s)) from else from + "=>" + quotedName(s.rename) } - print("import "); print(backquotedPath(expr)) - print(".") + print("import ", backquotedPath(expr), ".") selectors match { case List(s) => // If there is just one selector and it is not remapping a name, no braces are needed - if (isNotRemap(s)) { - print(selectorToString(s)) - } else { - print("{"); print(selectorToString(s)); print("}") - } + if (isNotRemap(s)) print(selectorToString(s)) + else print("{", selectorToString(s), "}") // If there is more than one selector braces are always needed case many => print(many.map(selectorToString).mkString("{", ", ", "}")) @@ -246,9 +238,9 @@ trait TreePrinters { self: SymbolTable => printRow(parents, " with ") if (!body.isEmpty) { if (self.name != nme.WILDCARD) { - print(" { "); print(self.name); printOpt(": ", self.tpt); print(" => ") + print(" { ", self.name); printOpt(": ", self.tpt); print(" => ") } else if (!self.tpt.isEmpty) { - print(" { _ : "); print(self.tpt); print(" => ") + print(" { _ : ", self.tpt, " => ") } else { print(" {") } @@ -276,39 +268,39 @@ trait TreePrinters { self: SymbolTable => patConstr(pat).tpe.finalResultType, selectorType, currentOwner)) print("???") print(pat); printOpt(" if ", guard) - print(" => "); print(body) + print(" => ", body) case Alternative(trees) => printRow(trees, "(", "| ", ")") case Star(elem) => - print("("); print(elem); print(")*") + print("(", elem, ")*") case Bind(name, t) => - print("("); print(symName(tree, name)); print(" @ "); print(t); print(")") + print("(", symName(tree, name), " @ ", t, ")") case UnApply(fun, args) => - print(fun); print(" "); printRow(args, "(", ", ", ")") + print(fun, " "); printRow(args, "(", ", ", ")") case ArrayValue(elemtpt, trees) => - print("Array["); print(elemtpt); printRow(trees, "]{", ", ", "}") + print("Array[", elemtpt); printRow(trees, "]{", ", ", "}") case Function(vparams, body) => - print("("); printValueParams(vparams); print(" => "); print(body); print(")") - if (settings.uniqid.value && tree.symbol != null) print("#"+tree.symbol.id) + print("("); printValueParams(vparams); print(" => ", body, ")") + if (uniqueIds && tree.symbol != null) print("#"+tree.symbol.id) case Assign(lhs, rhs) => - print(lhs); print(" = "); print(rhs) + print(lhs, " = ", rhs) case If(cond, thenp, elsep) => - print("if ("); print(cond); print(")"); indent; println() + print("if (", cond, ")"); indent; println() print(thenp); undent if (!elsep.isEmpty) { println(); print("else"); indent; println(); print(elsep); undent } case Return(expr) => - print("return "); print(expr) + print("return ", expr) case Try(block, catches, finalizer) => print("try "); printBlock(block) @@ -316,13 +308,13 @@ trait TreePrinters { self: SymbolTable => printOpt(" finally ", finalizer) case Throw(expr) => - print("throw "); print(expr) + print("throw ", expr) case New(tpe) => - print("new "); print(tpe) + print("new ", tpe) case Typed(expr, tp) => - print("("); print(expr); print(": "); print(tp); print(")") + print("(", expr, ": ", tp, ")") case TypeApply(fun, targs) => print(fun); printRow(targs, "[", ", ", "]") @@ -331,7 +323,7 @@ trait TreePrinters { self: SymbolTable => print(fun); printRow(vargs, "(", ", ", ")") case ApplyDynamic(qual, vargs) => - print("("); print(qual); print("#"); print(tree.symbol.nameString) + print("(", qual, "#", tree.symbol.nameString) printRow(vargs, ", (", ", ", "))") case Super(This(qual), mix) => @@ -341,8 +333,7 @@ trait TreePrinters { self: SymbolTable => print("[" + mix + "]") case Super(qual, mix) => - print(qual) - print(".super") + print(qual, ".super") if (!mix.isEmpty) print("[" + mix + "]") @@ -354,7 +345,7 @@ trait TreePrinters { self: SymbolTable => print(qual) case Select(qualifier, name) => - print(backquotedPath(qualifier)); print("."); print(symName(tree, name)) + print(backquotedPath(qualifier), ".", symName(tree, name)) case Ident(name) => print(symName(tree, name)) @@ -363,29 +354,29 @@ trait TreePrinters { self: SymbolTable => print(x.escapedStringValue) case tt: TypeTree => - if ((tree.tpe eq null) || (settings.Xprintpos.value && tt.original != null)) { - if (tt.original != null) { print("") } + if ((tree.tpe eq null) || (doPrintPositions && tt.original != null)) { + if (tt.original != null) print("") else print("") } else if ((tree.tpe.typeSymbol ne null) && tree.tpe.typeSymbol.isAnonymousClass) { - print(tree.tpe.typeSymbol.toString()) + print(tree.tpe.typeSymbol.toString) } else { - print(tree.tpe.toString()) + print(tree.tpe.toString) } case Annotated(Apply(Select(New(tpt), nme.CONSTRUCTOR), args), tree) => def printAnnot() { - print("@"); print(tpt) + print("@", tpt) if (!args.isEmpty) printRow(args, "(", ",", ")") } - if (tree.isType) { print(tree); print(" "); printAnnot() } - else { print(tree); print(": "); printAnnot() } + print(tree, if (tree.isType) " " else ": ") + printAnnot() case SingletonTypeTree(ref) => - print(ref); print(".type") + print(ref, ".type") case SelectFromTypeTree(qualifier, selector) => - print(qualifier); print("#"); print(symName(tree, selector)) + print(qualifier, "#", symName(tree, selector)) case CompoundTypeTree(templ) => print(templ) @@ -408,34 +399,26 @@ trait TreePrinters { self: SymbolTable => case tree => - xprintRaw(this, tree) + xprintTree(this, tree) } - if (settings.printtypes.value && tree.isTerm && !tree.isEmpty) { - print("{"); print(if (tree.tpe eq null) "" else tree.tpe.toString()); print("}") + if (typesPrinted && tree.isTerm && !tree.isEmpty) { + print("{", if (tree.tpe eq null) "" else tree.tpe.toString, "}") } } - def print(tree: Tree) { - printPosition(tree) - printRaw( - //nsc if (tree.isDef && tree.symbol != NoSymbol && tree.symbol.isInitialized) { - //nsc tree match { - //nsc case ClassDef(_, _, _, impl @ Template(ps, emptyValDef, body)) - //nsc if (tree.symbol.thisSym != tree.symbol) => - //nsc ClassDef(tree.symbol, Template(ps, ValDef(tree.symbol.thisSym), body)) - //nsc case ClassDef(_, _, _, impl) => ClassDef(tree.symbol, impl) - //nsc case ModuleDef(_, _, impl) => ModuleDef(tree.symbol, impl) - //nsc case ValDef(_, _, _, rhs) => ValDef(tree.symbol, rhs) - //nsc case DefDef(_, _, _, vparamss, _, rhs) => DefDef(tree.symbol, vparamss, rhs) - //nsc case TypeDef(_, _, _, rhs) => TypeDef(tree.symbol, rhs) - //nsc case _ => tree - //nsc } - //nsc } else - tree) + def print(args: Any*): Unit = args foreach { + case tree: Tree => + printPosition(tree) + printTree(tree) + case name: Name => + print(quotedName(name)) + case arg => + out.print(arg.toString) } } - def xprintRaw(treePrinter: TreePrinter, tree: Tree) = + /** Hook for extensions */ + def xprintTree(treePrinter: TreePrinter, tree: Tree) = treePrinter.print(tree.productPrefix+tree.productIterator.mkString("(", ", ", ")")) def newTreePrinter(writer: PrintWriter): TreePrinter = new TreePrinter(writer) diff --git a/src/compiler/scala/reflect/internal/Trees.scala b/src/compiler/scala/reflect/internal/Trees.scala index ff1b759290..9a9b34a391 100644 --- a/src/compiler/scala/reflect/internal/Trees.scala +++ b/src/compiler/scala/reflect/internal/Trees.scala @@ -6,7 +6,6 @@ package scala.reflect package internal -import java.io.{ PrintWriter, StringWriter } import Flags._ import api.Modifier @@ -97,14 +96,6 @@ trait Trees extends api.Trees { self: SymbolTable => // --- 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) { diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index fcbcb94e94..947a31cd7a 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -1290,7 +1290,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb def printAllUnits() { print("[[syntax trees at end of " + phase + "]]") - atPhase(phase.next) { currentRun.units foreach treePrinter.print } + atPhase(phase.next) { currentRun.units foreach (treePrinter.print(_)) } } private def findMemberFromRoot(fullName: Name): Symbol = { diff --git a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala index 34f8cdc626..5c3071739c 100644 --- a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala +++ b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala @@ -16,56 +16,52 @@ trait TreePrinters extends reflect.internal.TreePrinters { this: Global => class TreePrinter(out: PrintWriter) extends super.TreePrinter(out) { - override def print(tree: Tree) { - printPosition(tree) - printRaw( - if (tree.isDef && tree.symbol != NoSymbol && tree.symbol.isInitialized) { - tree match { - case ClassDef(_, _, _, impl @ Template(ps, emptyValDef, body)) - if (tree.symbol.thisSym != tree.symbol) => - ClassDef(tree.symbol, Template(ps, ValDef(tree.symbol.thisSym), body)) - case ClassDef(_, _, _, impl) => ClassDef(tree.symbol, impl) - case ModuleDef(_, _, impl) => ModuleDef(tree.symbol, impl) - case ValDef(_, _, _, rhs) => ValDef(tree.symbol, rhs) - case DefDef(_, _, _, vparamss, _, rhs) => DefDef(tree.symbol, vparamss, rhs) - case TypeDef(_, _, _, rhs) => TypeDef(tree.symbol, rhs) - case _ => tree - } - } else tree) - } - - def print(unit: CompilationUnit) { - print("// Scala source: " + unit.source + "\n") - if (unit.body == null) print("") - else { print(unit.body); println() } - - println() - flush() + override def print(args: Any*): Unit = args foreach { + case tree: Tree => + printPosition(tree) + printTree( + if (tree.isDef && tree.symbol != NoSymbol && tree.symbol.isInitialized) { + tree match { + case ClassDef(_, _, _, impl @ Template(ps, emptyValDef, body)) + if (tree.symbol.thisSym != tree.symbol) => + ClassDef(tree.symbol, Template(ps, ValDef(tree.symbol.thisSym), body)) + case ClassDef(_, _, _, impl) => ClassDef(tree.symbol, impl) + case ModuleDef(_, _, impl) => ModuleDef(tree.symbol, impl) + case ValDef(_, _, _, rhs) => ValDef(tree.symbol, rhs) + case DefDef(_, _, _, vparamss, _, rhs) => DefDef(tree.symbol, vparamss, rhs) + case TypeDef(_, _, _, rhs) => TypeDef(tree.symbol, rhs) + case _ => tree + } + } else tree) + case unit: CompilationUnit => + print("// Scala source: " + unit.source + "\n") + if (unit.body == null) print("") + else { print(unit.body); println() } + println() + out.flush() + case arg => + super.print(arg) } } // overflow cases missing from TreePrinter in reflect.api - override def xprintRaw(treePrinter: super.TreePrinter, tree: Tree) = tree match { + override def xprintTree(treePrinter: super.TreePrinter, tree: Tree) = tree match { case DocDef(comment, definition) => treePrinter.print(comment.raw) treePrinter.println() treePrinter.print(definition) case AssignOrNamedArg(lhs, rhs) => - treePrinter.print(lhs) - treePrinter.print(" = ") - treePrinter.print(rhs) + treePrinter.print(lhs, " = ", rhs) case TypeTreeWithDeferredRefCheck() => treePrinter.print("") case SelectFromArray(qualifier, name, _) => - treePrinter.print(qualifier) - treePrinter.print(".") - treePrinter.print(treePrinter.symName(tree, name)) + treePrinter.print(qualifier, ".", treePrinter.symName(tree, name)) case _ => - super.xprintRaw(treePrinter, tree) + super.xprintTree(treePrinter, tree) } /** A tree printer which is stingier about vertical whitespace and unnecessary @@ -74,7 +70,7 @@ trait TreePrinters extends reflect.internal.TreePrinters { this: Global => class CompactTreePrinter(out: PrintWriter) extends TreePrinter(out) { override def printRow(ts: List[Tree], start: String, sep: String, end: String) { print(start) - printSeq(ts)(print)(print(sep)) + printSeq(ts)(print(_))(print(sep)) print(end) } @@ -94,21 +90,21 @@ trait TreePrinters extends reflect.internal.TreePrinters { this: Global => def maybenot(tvalue: Boolean) = if (tvalue) "" else "!" print("%s(" format maybenot(t1._2)) - printRaw(t1._1) + printTree(t1._1) print(") %s %s(".format(op, maybenot(t2._2))) - printRaw(t2._1) + printTree(t2._1) print(")") } - override def printRaw(tree: Tree): Unit = { + override def printTree(tree: Tree): Unit = { // routing supercalls through this for debugging ease - def s() = super.printRaw(tree) + def s() = super.printTree(tree) tree match { // labels used for jumps - does not map to valid scala code case LabelDef(name, params, rhs) => print("labeldef %s(%s) = ".format(name, params mkString ",")) - printRaw(rhs) + printTree(rhs) case Ident(name) => print(decodedSymName(tree, name)) @@ -121,37 +117,37 @@ trait TreePrinters extends reflect.internal.TreePrinters { this: Global => printLogicalAnd(target -> true, arg -> true) else (target, arg) match { case (_: Ident, _: Literal | _: Ident) => - printRaw(target) + printTree(target) print(" ") - printRaw(Ident(method)) + printTree(Ident(method)) print(" ") - printRaw(arg) + printTree(arg) case _ => s() } // target.unary_! ==> !target case Select(qualifier, name) if (name.decode startsWith "unary_") => print(name.decode drop 6) - printRaw(qualifier) + printTree(qualifier) case Select(qualifier, name) => - printRaw(qualifier) + printTree(qualifier) print(".") print(quotedName(name, true)) // target.toString() ==> target.toString - case Apply(fn, Nil) => printRaw(fn) + case Apply(fn, Nil) => printTree(fn) // if a Block only continues one actual statement, just print it. case Block(stats, expr) => allStatements(tree) match { - case List(x) => printRaw(x) + case List(x) => printTree(x) case xs => s() } // We get a lot of this stuff - case If( IsTrue(), x, _) => printRaw(x) - case If(IsFalse(), _, x) => printRaw(x) + case If( IsTrue(), x, _) => printTree(x) + case If(IsFalse(), _, x) => printTree(x) case If(cond, IsTrue(), elsep) => printLogicalOr(cond -> true, elsep -> true) case If(cond, IsFalse(), elsep) => printLogicalAnd(cond -> false, elsep -> true) @@ -161,7 +157,7 @@ trait TreePrinters extends reflect.internal.TreePrinters { this: Global => // If thenp or elsep has only one statement, it doesn't need more than one line. case If(cond, thenp, elsep) => def ifIndented(x: Tree) = { - indent ; println() ; printRaw(x) ; undent + indent ; println() ; printTree(x) ; undent } val List(thenStmts, elseStmts) = List(thenp, elsep) map allStatements @@ -169,16 +165,16 @@ trait TreePrinters extends reflect.internal.TreePrinters { this: Global => thenStmts match { case List(x: If) => ifIndented(x) - case List(x) => printRaw(x) - case _ => printRaw(thenp) + case List(x) => printTree(x) + case _ => printTree(thenp) } if (elseStmts.nonEmpty) { print(" else") indent ; println() elseStmts match { - case List(x) => printRaw(x) - case _ => printRaw(elsep) + case List(x) => printTree(x) + case _ => printTree(elsep) } undent ; println() } @@ -192,10 +188,7 @@ trait TreePrinters extends reflect.internal.TreePrinters { this: Global => * the natural course of events. */ class SafeTreePrinter(out: PrintWriter) extends TreePrinter(out) { - override def print(tree: Tree) { - printPosition(tree) - printRaw(tree) - } + private def default(t: Tree) = t.getClass.getName.reverse.takeWhile(_ != '.').reverse private def params(trees: List[Tree]): String = trees map safe mkString ", " @@ -209,7 +202,7 @@ trait TreePrinters extends reflect.internal.TreePrinters { this: Global => case _ => "(?: %s)".format(default(tree)) } - override def printRaw(tree: Tree) { print(safe(tree)) } + override def printTree(tree: Tree) { print(safe(tree)) } } class TreeMatchTemplate { @@ -286,15 +279,8 @@ trait TreePrinters extends reflect.internal.TreePrinters { this: Global => } } - private def asStringInternal(t: Tree, f: PrintWriter => TreePrinter): String = { - val buffer = new StringWriter() - val printer = f(new PrintWriter(buffer)) - printer.print(t) - printer.flush() - buffer.toString - } - def asString(t: Tree): String = asStringInternal(t, newStandardTreePrinter) - def asCompactString(t: Tree): String = asStringInternal(t, newCompactTreePrinter) + def asString(t: Tree): String = show(t, newStandardTreePrinter) + def asCompactString(t: Tree): String = show(t, newCompactTreePrinter) def newStandardTreePrinter(writer: PrintWriter): TreePrinter = new TreePrinter(writer) def newStandardTreePrinter(stream: OutputStream): TreePrinter = newStandardTreePrinter(new PrintWriter(stream)) -- cgit v1.2.3