From 3be520bcfc84f207d172934f9b147e31355cd877 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Fri, 15 Jun 2012 13:35:54 +0200 Subject: improves showRaw addresses concerns raised in http://groups.google.com/group/scala-user/browse_thread/thread/de5a5be2e083cf8e --- .../scala/reflect/reify/utils/NodePrinters.scala | 39 +- src/compiler/scala/tools/nsc/Global.scala | 2 +- .../scala/tools/nsc/ast/NodePrinters.scala | 2 +- src/compiler/scala/tools/nsc/ast/Printers.scala | 295 ++++++++++ .../scala/tools/nsc/ast/TreePrinters.scala | 295 ---------- .../scala/tools/nsc/matching/MatchSupport.scala | 2 +- src/library/scala/reflect/base/Base.scala | 2 +- src/library/scala/reflect/base/Trees.scala | 4 +- src/reflect/scala/reflect/api/Printers.scala | 94 +++ src/reflect/scala/reflect/api/Symbols.scala | 19 + src/reflect/scala/reflect/api/TreePrinters.scala | 87 --- src/reflect/scala/reflect/api/Universe.scala | 2 +- src/reflect/scala/reflect/internal/Printers.scala | 642 +++++++++++++++++++++ .../scala/reflect/internal/SymbolTable.scala | 2 +- .../scala/reflect/internal/TreePrinters.scala | 478 --------------- src/reflect/scala/reflect/internal/Trees.scala | 2 +- src/reflect/scala/reflect/makro/Universe.scala | 19 - test/files/run/showraw_mods.check | 1 + test/files/run/showraw_mods.scala | 6 + test/files/run/showraw_tree.check | 2 + test/files/run/showraw_tree.scala | 8 + test/files/run/showraw_tree_ids.check | 2 + test/files/run/showraw_tree_ids.scala | 8 + test/files/run/showraw_tree_kinds.check | 2 + test/files/run/showraw_tree_kinds.scala | 8 + test/files/run/showraw_tree_types_ids.check | 10 + test/files/run/showraw_tree_types_ids.scala | 10 + test/files/run/showraw_tree_types_typed.check | 10 + test/files/run/showraw_tree_types_typed.scala | 10 + test/files/run/showraw_tree_types_untyped.check | 2 + test/files/run/showraw_tree_types_untyped.scala | 8 + test/files/run/showraw_tree_ultimate.check | 10 + test/files/run/showraw_tree_ultimate.scala | 10 + 33 files changed, 1168 insertions(+), 925 deletions(-) create mode 100644 src/compiler/scala/tools/nsc/ast/Printers.scala delete mode 100644 src/compiler/scala/tools/nsc/ast/TreePrinters.scala create mode 100644 src/reflect/scala/reflect/api/Printers.scala delete mode 100644 src/reflect/scala/reflect/api/TreePrinters.scala create mode 100644 src/reflect/scala/reflect/internal/Printers.scala delete mode 100644 src/reflect/scala/reflect/internal/TreePrinters.scala create mode 100644 test/files/run/showraw_mods.check create mode 100644 test/files/run/showraw_mods.scala create mode 100644 test/files/run/showraw_tree.check create mode 100644 test/files/run/showraw_tree.scala create mode 100644 test/files/run/showraw_tree_ids.check create mode 100644 test/files/run/showraw_tree_ids.scala create mode 100644 test/files/run/showraw_tree_kinds.check create mode 100644 test/files/run/showraw_tree_kinds.scala create mode 100644 test/files/run/showraw_tree_types_ids.check create mode 100644 test/files/run/showraw_tree_types_ids.scala create mode 100644 test/files/run/showraw_tree_types_typed.check create mode 100644 test/files/run/showraw_tree_types_typed.scala create mode 100644 test/files/run/showraw_tree_types_untyped.check create mode 100644 test/files/run/showraw_tree_types_untyped.scala create mode 100644 test/files/run/showraw_tree_ultimate.check create mode 100644 test/files/run/showraw_tree_ultimate.scala diff --git a/src/compiler/scala/reflect/reify/utils/NodePrinters.scala b/src/compiler/scala/reflect/reify/utils/NodePrinters.scala index ce0ab2196a..7214da597e 100644 --- a/src/compiler/scala/reflect/reify/utils/NodePrinters.scala +++ b/src/compiler/scala/reflect/reify/utils/NodePrinters.scala @@ -15,41 +15,6 @@ trait NodePrinters { import Flag._ object reifiedNodeToString extends (Tree => String) { - // [Eugene++ to Martin] can we do better? - // didn't want to invent anything myself in order not to interfere with your line of thought - def bitsToFlags(bits: String): String = { - val flags = bits.toLong - if (flags == NoFlags) nme.NoFlags.toString - else { - val s_flags = new collection.mutable.ListBuffer[String] - if (flags containsAll TRAIT) s_flags += "TRAIT" - if (flags containsAll MODULE) s_flags += "MODULE" - if (flags containsAll MUTABLE) s_flags += "MUTABLE" - if (flags containsAll PACKAGE) s_flags += "PACKAGE" - if (flags containsAll METHOD) s_flags += "METHOD" - if (flags containsAll DEFERRED) s_flags += "DEFERRED" - if (flags containsAll ABSTRACT) s_flags += "ABSTRACT" - if (flags containsAll FINAL) s_flags += "FINAL" - if (flags containsAll SEALED) s_flags += "SEALED" - if (flags containsAll IMPLICIT) s_flags += "IMPLICIT" - if (flags containsAll LAZY) s_flags += "LAZY" - if (flags containsAll OVERRIDE) s_flags += "OVERRIDE" - if (flags containsAll PRIVATE) s_flags += "PRIVATE" - if (flags containsAll PROTECTED) s_flags += "PROTECTED" - if (flags containsAll CASE) s_flags += "CASE" - if (flags containsAll ABSOVERRIDE) s_flags += "ABSOVERRIDE" - if (flags containsAll BYNAMEPARAM) s_flags += "BYNAMEPARAM" - if (flags containsAll PARAM) s_flags += "PARAM" - if (flags containsAll PARAMACCESSOR) s_flags += "PARAMACCESSOR" - if (flags containsAll CASEACCESSOR) s_flags += "CASEACCESSOR" - if (flags containsAll COVARIANT) s_flags += "COVARIANT" - if (flags containsAll CONTRAVARIANT) s_flags += "CONTRAVARIANT" - if (flags containsAll DEFAULTPARAM) s_flags += "DEFAULTPARAM" - if (flags containsAll INTERFACE) s_flags += "INTERFACE" - s_flags mkString " | " - } - } - def apply(tree: Tree): String = { var mirrorIsUsed = false var flagsAreUsed = false @@ -70,7 +35,7 @@ trait NodePrinters { s = s.replace("immutable.this.Nil", "List()") s = """build\.flagsFromBits\((\d+)[lL]\)""".r.replaceAllIn(s, m => { flagsAreUsed = true - bitsToFlags(m.group(1)) + show(m.group(1).toLong) }) s = s.replace("Modifiers(0L, newTypeName(\"\"), List())", "Modifiers()") s = """Modifiers\((\d+)[lL], newTypeName\("(.*?)"\), List\((.*?)\)\)""".r.replaceAllIn(s, m => { @@ -87,7 +52,7 @@ trait NodePrinters { val bits = m.group(1) if (buf.nonEmpty || bits != "0L") { flagsAreUsed = true - buf.append(bitsToFlags(bits)) + buf.append(show(bits.toLong)) } val replacement = "Modifiers(" + buf.reverse.mkString(", ") + ")" diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 787c9c7f57..38a08bbd60 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -39,7 +39,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) with Plugins with PhaseAssembly with Trees - with TreePrinters + with Printers with DocComments with Positions { self => diff --git a/src/compiler/scala/tools/nsc/ast/NodePrinters.scala b/src/compiler/scala/tools/nsc/ast/NodePrinters.scala index ba1f3b2e3c..4afd3545b9 100644 --- a/src/compiler/scala/tools/nsc/ast/NodePrinters.scala +++ b/src/compiler/scala/tools/nsc/ast/NodePrinters.scala @@ -146,7 +146,7 @@ abstract class NodePrinters { } def printModifiers(tree: MemberDef) { // [Eugene++] there's most likely a bug here (?) - // see `TreePrinters.printAnnotations` for more information + // see `Printers.printAnnotations` for more information val annots0 = tree.symbol.annotations match { case Nil => tree.mods.annotations case xs => xs map annotationInfoToString diff --git a/src/compiler/scala/tools/nsc/ast/Printers.scala b/src/compiler/scala/tools/nsc/ast/Printers.scala new file mode 100644 index 0000000000..94d0c4f45e --- /dev/null +++ b/src/compiler/scala/tools/nsc/ast/Printers.scala @@ -0,0 +1,295 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2011 LAMP/EPFL + * @author Martin Odersky + */ + +package scala.tools.nsc +package ast + +import java.io.{ OutputStream, PrintWriter, StringWriter, Writer } +import symtab.Flags._ +import symtab.SymbolTable + +trait Printers extends reflect.internal.Printers { this: Global => + + import treeInfo.{ IsTrue, IsFalse } + + class TreePrinter(out: PrintWriter) extends super.TreePrinter(out) { + + 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 xprintTree(treePrinter: super.TreePrinter, tree: Tree) = tree match { + case DocDef(comment, definition) => + treePrinter.print(comment.raw) + treePrinter.println() + treePrinter.print(definition) + + case TypeTreeWithDeferredRefCheck() => + treePrinter.print("") + + case SelectFromArray(qualifier, name, _) => + treePrinter.print(qualifier, ".", symName(tree, name)) + + case _ => + super.xprintTree(treePrinter, tree) + } + + /** A tree printer which is stingier about vertical whitespace and unnecessary + * punctuation than the standard one. + */ + 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)) + print(end) + } + + // drill down through Blocks and pull out the real statements. + def allStatements(t: Tree): List[Tree] = t match { + case Block(stmts, expr) => (stmts flatMap allStatements) ::: List(expr) + case _ => List(t) + } + + def printLogicalOr(t1: (Tree, Boolean), t2: (Tree, Boolean)) = + printLogicalOp(t1, t2, "||") + + def printLogicalAnd(t1: (Tree, Boolean), t2: (Tree, Boolean)) = + printLogicalOp(t1, t2, "&&") + + def printLogicalOp(t1: (Tree, Boolean), t2: (Tree, Boolean), op: String) = { + def maybenot(tvalue: Boolean) = if (tvalue) "" else "!" + + print("%s(" format maybenot(t1._2)) + printTree(t1._1) + print(") %s %s(".format(op, maybenot(t2._2))) + printTree(t2._1) + print(")") + } + + override def printTree(tree: Tree): Unit = { + // routing supercalls through this for debugging ease + 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 ",")) + printTree(rhs) + + case Ident(name) => + print(decodedSymName(tree, name)) + + // target.method(arg) ==> target method arg + case Apply(Select(target, method), List(arg)) => + if (method.decode.toString == "||") + printLogicalOr(target -> true, arg -> true) + else if (method.decode.toString == "&&") + printLogicalAnd(target -> true, arg -> true) + else (target, arg) match { + case (_: Ident, _: Literal | _: Ident) => + printTree(target) + print(" ") + printTree(Ident(method)) + print(" ") + printTree(arg) + case _ => s() + } + + // target.unary_! ==> !target + case Select(qualifier, name) if (name.decode startsWith "unary_") => + print(name.decode drop 6) + printTree(qualifier) + + case Select(qualifier, name) => + printTree(qualifier) + print(".") + print(quotedName(name, true)) + + // target.toString() ==> target.toString + 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) => printTree(x) + case xs => s() + } + + // We get a lot of this stuff + 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) + case If(cond, thenp, IsTrue()) => printLogicalOr(cond -> false, thenp -> true) + case If(cond, thenp, IsFalse()) => printLogicalAnd(cond -> true, thenp -> true) + + // 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() ; printTree(x) ; undent + } + + val List(thenStmts, elseStmts) = List(thenp, elsep) map allStatements + print("if ("); print(cond); print(") ") + + thenStmts match { + case List(x: If) => ifIndented(x) + case List(x) => printTree(x) + case _ => printTree(thenp) + } + + if (elseStmts.nonEmpty) { + print(" else") + indent ; println() + elseStmts match { + case List(x) => printTree(x) + case _ => printTree(elsep) + } + undent ; println() + } + case _ => s() + } + } + } + + /** This must guarantee not to force any evaluation, so we can learn + * a little bit about trees in the midst of compilation without altering + * the natural course of events. + */ + class SafeTreePrinter(out: PrintWriter) extends TreePrinter(out) { + + private def default(t: Tree) = t.getClass.getName.reverse.takeWhile(_ != '.').reverse + private def params(trees: List[Tree]): String = trees map safe mkString ", " + + private def safe(name: Name): String = name.decode + private def safe(tree: Tree): String = tree match { + case Apply(fn, args) => "%s(%s)".format(safe(fn), params(args)) + case Select(qual, name) => safe(qual) + "." + safe(name) + case This(qual) => safe(qual) + ".this" + case Ident(name) => safe(name) + case Literal(value) => value.stringValue + case _ => "(?: %s)".format(default(tree)) + } + + override def printTree(tree: Tree) { print(safe(tree)) } + } + + class TreeMatchTemplate { + // non-trees defined in Trees + // + // case class ImportSelector(name: Name, namePos: Int, rename: Name, renamePos: Int) + // case class Modifiers(flags: Long, privateWithin: Name, annotations: List[Tree], positions: Map[Long, Position]) + // + def apply(t: Tree): Unit = t match { + // eliminated by typer + case Annotated(annot, arg) => + case AssignOrNamedArg(lhs, rhs) => + case DocDef(comment, definition) => + case Import(expr, selectors) => + + // eliminated by refchecks + case ModuleDef(mods, name, impl) => + case TypeTreeWithDeferredRefCheck() => + + // eliminated by erasure + case TypeDef(mods, name, tparams, rhs) => + case Typed(expr, tpt) => + + // eliminated by cleanup + case ApplyDynamic(qual, args) => + + // eliminated by explicitouter + case Alternative(trees) => + case Bind(name, body) => + case CaseDef(pat, guard, body) => + case Star(elem) => + case UnApply(fun, args) => + + // eliminated by lambdalift + case Function(vparams, body) => + + // eliminated by uncurry + case AppliedTypeTree(tpt, args) => + case CompoundTypeTree(templ) => + case ExistentialTypeTree(tpt, whereClauses) => + case SelectFromTypeTree(qual, selector) => + case SingletonTypeTree(ref) => + case TypeBoundsTree(lo, hi) => + + // survivors + case Apply(fun, args) => + case ArrayValue(elemtpt, trees) => + case Assign(lhs, rhs) => + case Block(stats, expr) => + case ClassDef(mods, name, tparams, impl) => + case DefDef(mods, name, tparams, vparamss, tpt, rhs) => + case EmptyTree => + case Ident(name) => + case If(cond, thenp, elsep) => + case LabelDef(name, params, rhs) => + case Literal(value) => + case Match(selector, cases) => + case New(tpt) => + case PackageDef(pid, stats) => + case Return(expr) => + case Select(qualifier, selector) => + case Super(qual, mix) => + case Template(parents, self, body) => + case This(qual) => + case Throw(expr) => + case Try(block, catches, finalizer) => + case TypeApply(fun, args) => + case TypeTree() => + case ValDef(mods, name, tpt, rhs) => + + // missing from the Trees comment + case Parens(args) => // only used during parsing + case SelectFromArray(qual, name, erasure) => // only used during erasure + } + } + + def asString(t: Tree): String = render(t, newStandardTreePrinter, settings.printtypes.value, settings.uniqid.value, settings.Yshowsymkinds.value) + def asCompactString(t: Tree): String = render(t, newCompactTreePrinter, settings.printtypes.value, settings.uniqid.value, settings.Yshowsymkinds.value) + + def newStandardTreePrinter(writer: PrintWriter): TreePrinter = new TreePrinter(writer) + def newStandardTreePrinter(stream: OutputStream): TreePrinter = newStandardTreePrinter(new PrintWriter(stream)) + def newStandardTreePrinter(): TreePrinter = newStandardTreePrinter(new PrintWriter(ConsoleWriter)) + + def newCompactTreePrinter(writer: PrintWriter): CompactTreePrinter = new CompactTreePrinter(writer) + def newCompactTreePrinter(stream: OutputStream): CompactTreePrinter = newCompactTreePrinter(new PrintWriter(stream)) + def newCompactTreePrinter(): CompactTreePrinter = newCompactTreePrinter(new PrintWriter(ConsoleWriter)) + + override def newTreePrinter(writer: PrintWriter): TreePrinter = + if (settings.Ycompacttrees.value) newCompactTreePrinter(writer) + else newStandardTreePrinter(writer) + override def newTreePrinter(stream: OutputStream): TreePrinter = newTreePrinter(new PrintWriter(stream)) + override def newTreePrinter(): TreePrinter = newTreePrinter(new PrintWriter(ConsoleWriter)) +} diff --git a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala deleted file mode 100644 index 3371353f25..0000000000 --- a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala +++ /dev/null @@ -1,295 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2005-2011 LAMP/EPFL - * @author Martin Odersky - */ - -package scala.tools.nsc -package ast - -import java.io.{ OutputStream, PrintWriter, StringWriter, Writer } -import symtab.Flags._ -import symtab.SymbolTable - -trait TreePrinters extends reflect.internal.TreePrinters { this: Global => - - import treeInfo.{ IsTrue, IsFalse } - - class TreePrinter(out: PrintWriter) extends super.TreePrinter(out) { - - 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 xprintTree(treePrinter: super.TreePrinter, tree: Tree) = tree match { - case DocDef(comment, definition) => - treePrinter.print(comment.raw) - treePrinter.println() - treePrinter.print(definition) - - case TypeTreeWithDeferredRefCheck() => - treePrinter.print("") - - case SelectFromArray(qualifier, name, _) => - treePrinter.print(qualifier, ".", symName(tree, name)) - - case _ => - super.xprintTree(treePrinter, tree) - } - - /** A tree printer which is stingier about vertical whitespace and unnecessary - * punctuation than the standard one. - */ - 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)) - print(end) - } - - // drill down through Blocks and pull out the real statements. - def allStatements(t: Tree): List[Tree] = t match { - case Block(stmts, expr) => (stmts flatMap allStatements) ::: List(expr) - case _ => List(t) - } - - def printLogicalOr(t1: (Tree, Boolean), t2: (Tree, Boolean)) = - printLogicalOp(t1, t2, "||") - - def printLogicalAnd(t1: (Tree, Boolean), t2: (Tree, Boolean)) = - printLogicalOp(t1, t2, "&&") - - def printLogicalOp(t1: (Tree, Boolean), t2: (Tree, Boolean), op: String) = { - def maybenot(tvalue: Boolean) = if (tvalue) "" else "!" - - print("%s(" format maybenot(t1._2)) - printTree(t1._1) - print(") %s %s(".format(op, maybenot(t2._2))) - printTree(t2._1) - print(")") - } - - override def printTree(tree: Tree): Unit = { - // routing supercalls through this for debugging ease - 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 ",")) - printTree(rhs) - - case Ident(name) => - print(decodedSymName(tree, name)) - - // target.method(arg) ==> target method arg - case Apply(Select(target, method), List(arg)) => - if (method.decode.toString == "||") - printLogicalOr(target -> true, arg -> true) - else if (method.decode.toString == "&&") - printLogicalAnd(target -> true, arg -> true) - else (target, arg) match { - case (_: Ident, _: Literal | _: Ident) => - printTree(target) - print(" ") - printTree(Ident(method)) - print(" ") - printTree(arg) - case _ => s() - } - - // target.unary_! ==> !target - case Select(qualifier, name) if (name.decode startsWith "unary_") => - print(name.decode drop 6) - printTree(qualifier) - - case Select(qualifier, name) => - printTree(qualifier) - print(".") - print(quotedName(name, true)) - - // target.toString() ==> target.toString - 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) => printTree(x) - case xs => s() - } - - // We get a lot of this stuff - 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) - case If(cond, thenp, IsTrue()) => printLogicalOr(cond -> false, thenp -> true) - case If(cond, thenp, IsFalse()) => printLogicalAnd(cond -> true, thenp -> true) - - // 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() ; printTree(x) ; undent - } - - val List(thenStmts, elseStmts) = List(thenp, elsep) map allStatements - print("if ("); print(cond); print(") ") - - thenStmts match { - case List(x: If) => ifIndented(x) - case List(x) => printTree(x) - case _ => printTree(thenp) - } - - if (elseStmts.nonEmpty) { - print(" else") - indent ; println() - elseStmts match { - case List(x) => printTree(x) - case _ => printTree(elsep) - } - undent ; println() - } - case _ => s() - } - } - } - - /** This must guarantee not to force any evaluation, so we can learn - * a little bit about trees in the midst of compilation without altering - * the natural course of events. - */ - class SafeTreePrinter(out: PrintWriter) extends TreePrinter(out) { - - private def default(t: Tree) = t.getClass.getName.reverse.takeWhile(_ != '.').reverse - private def params(trees: List[Tree]): String = trees map safe mkString ", " - - private def safe(name: Name): String = name.decode - private def safe(tree: Tree): String = tree match { - case Apply(fn, args) => "%s(%s)".format(safe(fn), params(args)) - case Select(qual, name) => safe(qual) + "." + safe(name) - case This(qual) => safe(qual) + ".this" - case Ident(name) => safe(name) - case Literal(value) => value.stringValue - case _ => "(?: %s)".format(default(tree)) - } - - override def printTree(tree: Tree) { print(safe(tree)) } - } - - class TreeMatchTemplate { - // non-trees defined in Trees - // - // case class ImportSelector(name: Name, namePos: Int, rename: Name, renamePos: Int) - // case class Modifiers(flags: Long, privateWithin: Name, annotations: List[Tree], positions: Map[Long, Position]) - // - def apply(t: Tree): Unit = t match { - // eliminated by typer - case Annotated(annot, arg) => - case AssignOrNamedArg(lhs, rhs) => - case DocDef(comment, definition) => - case Import(expr, selectors) => - - // eliminated by refchecks - case ModuleDef(mods, name, impl) => - case TypeTreeWithDeferredRefCheck() => - - // eliminated by erasure - case TypeDef(mods, name, tparams, rhs) => - case Typed(expr, tpt) => - - // eliminated by cleanup - case ApplyDynamic(qual, args) => - - // eliminated by explicitouter - case Alternative(trees) => - case Bind(name, body) => - case CaseDef(pat, guard, body) => - case Star(elem) => - case UnApply(fun, args) => - - // eliminated by lambdalift - case Function(vparams, body) => - - // eliminated by uncurry - case AppliedTypeTree(tpt, args) => - case CompoundTypeTree(templ) => - case ExistentialTypeTree(tpt, whereClauses) => - case SelectFromTypeTree(qual, selector) => - case SingletonTypeTree(ref) => - case TypeBoundsTree(lo, hi) => - - // survivors - case Apply(fun, args) => - case ArrayValue(elemtpt, trees) => - case Assign(lhs, rhs) => - case Block(stats, expr) => - case ClassDef(mods, name, tparams, impl) => - case DefDef(mods, name, tparams, vparamss, tpt, rhs) => - case EmptyTree => - case Ident(name) => - case If(cond, thenp, elsep) => - case LabelDef(name, params, rhs) => - case Literal(value) => - case Match(selector, cases) => - case New(tpt) => - case PackageDef(pid, stats) => - case Return(expr) => - case Select(qualifier, selector) => - case Super(qual, mix) => - case Template(parents, self, body) => - case This(qual) => - case Throw(expr) => - case Try(block, catches, finalizer) => - case TypeApply(fun, args) => - case TypeTree() => - case ValDef(mods, name, tpt, rhs) => - - // missing from the Trees comment - case Parens(args) => // only used during parsing - case SelectFromArray(qual, name, erasure) => // only used during erasure - } - } - - 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)) - def newStandardTreePrinter(): TreePrinter = newStandardTreePrinter(new PrintWriter(ConsoleWriter)) - - def newCompactTreePrinter(writer: PrintWriter): CompactTreePrinter = new CompactTreePrinter(writer) - def newCompactTreePrinter(stream: OutputStream): CompactTreePrinter = newCompactTreePrinter(new PrintWriter(stream)) - def newCompactTreePrinter(): CompactTreePrinter = newCompactTreePrinter(new PrintWriter(ConsoleWriter)) - - override def newTreePrinter(writer: PrintWriter): TreePrinter = - if (settings.Ycompacttrees.value) newCompactTreePrinter(writer) - else newStandardTreePrinter(writer) - override def newTreePrinter(stream: OutputStream): TreePrinter = newTreePrinter(new PrintWriter(stream)) - override def newTreePrinter(): TreePrinter = newTreePrinter(new PrintWriter(ConsoleWriter)) -} diff --git a/src/compiler/scala/tools/nsc/matching/MatchSupport.scala b/src/compiler/scala/tools/nsc/matching/MatchSupport.scala index 72e6f32af1..16761144d7 100644 --- a/src/compiler/scala/tools/nsc/matching/MatchSupport.scala +++ b/src/compiler/scala/tools/nsc/matching/MatchSupport.scala @@ -7,7 +7,7 @@ package scala.tools.nsc package matching import transform.ExplicitOuter -import ast.{ TreePrinters, Trees } +import ast.{ Printers, Trees } import java.io.{ StringWriter, PrintWriter } import annotation.elidable import language.postfixOps diff --git a/src/library/scala/reflect/base/Base.scala b/src/library/scala/reflect/base/Base.scala index 461eaa2e9e..490a9e8c03 100644 --- a/src/library/scala/reflect/base/Base.scala +++ b/src/library/scala/reflect/base/Base.scala @@ -451,7 +451,7 @@ class Base extends Universe { self => } } - def show(tree: Tree) = s"" + def treeToString(tree: Tree) = s"" trait TermTree extends Tree diff --git a/src/library/scala/reflect/base/Trees.scala b/src/library/scala/reflect/base/Trees.scala index 298d229570..2814450ae3 100644 --- a/src/library/scala/reflect/base/Trees.scala +++ b/src/library/scala/reflect/base/Trees.scala @@ -28,11 +28,11 @@ trait Trees { self: Universe => def isType: Boolean /** Obtains string representation of a tree */ - override def toString: String = show(this) + override def toString: String = treeToString(this) } /** Obtains string representation of a tree */ - def show(tree: Tree): String + protected def treeToString(tree: Tree): String /** Tree is the basis for scala's abstract syntax. The nodes are * implemented as case classes, and the parameters which initialize diff --git a/src/reflect/scala/reflect/api/Printers.scala b/src/reflect/scala/reflect/api/Printers.scala new file mode 100644 index 0000000000..7f4ff8a7fb --- /dev/null +++ b/src/reflect/scala/reflect/api/Printers.scala @@ -0,0 +1,94 @@ +package scala.reflect +package api + +import java.io.{ PrintWriter, StringWriter } + +trait Printers { self: Universe => + + trait TreePrinter { + def print(args: Any*) + protected var printTypes = false + protected var printIds = false + protected var printKinds = false + def withTypes: this.type = { printTypes = true; this } + def withoutTypes: this.type = { printTypes = false; this } + def withIds: this.type = { printIds = true; this } + def withoutIds: this.type = { printIds = false; this } + def withKinds: this.type = { printKinds = true; this } + def withoutKinds: this.type = { printKinds = false; this } + } + + case class BooleanFlag(val value: Option[Boolean]) + object BooleanFlag { + import language.implicitConversions + implicit def booleanToBooleanFlag(value: Boolean): BooleanFlag = BooleanFlag(Some(value)) + implicit def optionToBooleanFlag(value: Option[Boolean]): BooleanFlag = BooleanFlag(value) + } + + protected def render(what: Any, mkPrinter: PrintWriter => TreePrinter, printTypes: BooleanFlag = None, printIds: BooleanFlag = None, printKinds: BooleanFlag = None): String = { + val buffer = new StringWriter() + val writer = new PrintWriter(buffer) + var printer = mkPrinter(writer) + printTypes.value.map(printTypes => if (printTypes) printer.withTypes else printer.withoutTypes) + printIds.value.map(printIds => if (printIds) printer.withIds else printer.withoutIds) + printKinds.value.map(printKinds => if (printKinds) printer.withKinds else printer.withoutKinds) + printer.print(what) + writer.flush() + buffer.toString + } + + /** By default trees are printed with `show` */ + override protected def treeToString(tree: Tree) = show(tree) + + /** Renders a prettified representation of a tree. + * Typically it looks very close to the Scala code it represents. + * This function is used in Tree.toString. + */ + def show(tree: Tree, printTypes: BooleanFlag = None, printIds: BooleanFlag = None, printKinds: BooleanFlag = None): String = + render(tree, newTreePrinter(_), printTypes, printIds, printKinds) + + /** Hook to define what `show(tree)` means. + */ + def newTreePrinter(out: PrintWriter): TreePrinter + + /** Renders internal structure of a tree. + */ + def showRaw(tree: Tree, printTypes: BooleanFlag = None, printIds: BooleanFlag = None, printKinds: BooleanFlag = None): String = + render(tree, newRawTreePrinter(_), printTypes, printIds, printKinds) + + /** Hook to define what `showRaw(tree)` means. + */ + def newRawTreePrinter(out: PrintWriter): TreePrinter + + /** Renders a prettified representation of a symbol. + */ + def show(sym: Symbol): String = sym.toString + + /** Renders internal structure of a symbol. + */ + def showRaw(sym: Symbol): String = render(sym, newRawTreePrinter(_)) + + /** Renders a prettified representation of a type. + */ + def show(tpe: Type): String = tpe.toString + + /** Renders internal structure of a type. + */ + def showRaw(tpe: Type): String = render(tpe, newRawTreePrinter(_)) + + /** Renders a prettified representation of a name. + */ + def show(name: Name): String + + /** Renders internal structure of a name. + */ + def showRaw(name: Name): String = name.toString + + /** Renders a prettified representation of a flag set. + */ + def show(flags: FlagSet): String + + /** Renders internal structure of a flag set. + */ + def showRaw(flags: FlagSet): String = flags.toString +} diff --git a/src/reflect/scala/reflect/api/Symbols.scala b/src/reflect/scala/reflect/api/Symbols.scala index 1d266dc778..130f9e612a 100644 --- a/src/reflect/scala/reflect/api/Symbols.scala +++ b/src/reflect/scala/reflect/api/Symbols.scala @@ -177,6 +177,25 @@ trait Symbols extends base.Symbols { self: Universe => */ def isErroneous : Boolean + /** Can this symbol be loaded by a reflective mirror? + * + * Scalac relies on `ScalaSignature' annotation to retain symbols across compilation runs. + * Such annotations (also called "pickles") are applied on top-level classes and include information + * about all symbols reachable from the annotee. However, local symbols (e.g. classes or definitions local to a block) + * are typically unreachable and information about them gets lost. + * + * This method is useful for macro writers who wish to save certain ASTs to be used at runtime. + * With `isLocatable' it's possible to check whether a tree can be retained as is, or it needs special treatment. + */ + def isLocatable: Boolean + + /** Is this symbol static (i.e. with no outer instance)? + * Q: When exactly is a sym marked as STATIC? + * A: If it's a member of a toplevel object, or of an object contained in a toplevel object, or any number of levels deep. + * http://groups.google.com/group/scala-internals/browse_thread/thread/d385bcd60b08faf6 + */ + def isStatic: Boolean + /** The type signature of this symbol seen as a member of given type `site`. */ def typeSignatureIn(site: Type): Type diff --git a/src/reflect/scala/reflect/api/TreePrinters.scala b/src/reflect/scala/reflect/api/TreePrinters.scala deleted file mode 100644 index 08a08e7b90..0000000000 --- a/src/reflect/scala/reflect/api/TreePrinters.scala +++ /dev/null @@ -1,87 +0,0 @@ -package scala.reflect -package api - -import java.io.{ PrintWriter, StringWriter } - -trait TreePrinters { self: Universe => - - trait TreePrinter { - def print(args: Any*) - protected var typesPrinted = false - protected var uniqueIds = false - def withTypesPrinted: this.type = { typesPrinted = true; this } - def withUniqueIds: this.type = { uniqueIds = true; this } - } - - def show(tree: Tree): String = show(tree, newTreePrinter) - - def show(tree: Tree, mkPrinter: PrintWriter => TreePrinter): String = { - val buffer = new StringWriter() - val writer = new PrintWriter(buffer) - val printer = mkPrinter(writer) - printer.print(tree) - writer.flush() - buffer.toString - } - - def showRaw(tree: Tree): String = show(tree, new RawTreePrinter(_)) - - /** Hook to define what `show(tree)` means. - */ - def newTreePrinter(out: PrintWriter): TreePrinter - - // emits more or less verbatim representation of the provided tree - // [Eugene] todo. needs to be refined - // http://groups.google.com/group/scala-user/browse_thread/thread/de5a5be2e083cf8e - class RawTreePrinter(out: PrintWriter) extends TreePrinter { - def print(args: Any*): Unit = args foreach { - case EmptyTree => - print("EmptyTree") - case tree @ TypeTree() => - print("TypeTree()") - if (tree.tpe != null) - print(".setType(", tree.tpe, ")") - else if (tree.original != null) - print(".setOriginal(", tree.original, ")") - case Literal(Constant(s: String)) => - print("Literal(Constant(\"" + s + "\"))") - case tree: Tree => - print(tree.productPrefix+"(") - val it = tree.productIterator - while (it.hasNext) { - it.next() match { - case name: Name if uniqueIds && tree.hasSymbol && tree.symbol != NoSymbol => - print(tree.symbol.name, "#", tree.symbol.id) - case arg => - print(arg) - } - print(if (it.hasNext) ", " else "") - } - print(")") - if (typesPrinted) - print(".setType(", tree.tpe, ")") - case list: List[_] => - print("List(") - val it = list.iterator - while (it.hasNext) { - print(it.next()) - print(if (it.hasNext) ", " else "") - } - print(")") - case mods: Modifiers => - val parts = collection.mutable.ListBuffer[String]() - parts += mods.flagString - if (mods.privateWithin.toString.nonEmpty) - parts += "newTypeName(\"" + mods.privateWithin.toString + "\")" - if (mods.annotations.nonEmpty) - parts += mods.annotations map showRaw mkString ("List(", ", ", ")") - print(parts mkString ("Modifiers(", ", ", ")")) - case name: Name => - if (name.isTermName) print("newTermName(\"") else print("newTypeName(\"") - print(name.toString) - print("\")") - case arg => - out.print(arg) - } - } -} diff --git a/src/reflect/scala/reflect/api/Universe.scala b/src/reflect/scala/reflect/api/Universe.scala index 002cd2e673..85d8adc44f 100644 --- a/src/reflect/scala/reflect/api/Universe.scala +++ b/src/reflect/scala/reflect/api/Universe.scala @@ -9,7 +9,7 @@ abstract class Universe extends base.Universe with FlagSets with Names with Trees - with TreePrinters + with Printers with Constants with Positions with Mirrors diff --git a/src/reflect/scala/reflect/internal/Printers.scala b/src/reflect/scala/reflect/internal/Printers.scala new file mode 100644 index 0000000000..82a8c42f7c --- /dev/null +++ b/src/reflect/scala/reflect/internal/Printers.scala @@ -0,0 +1,642 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2011 LAMP/EPFL + * @author Martin Odersky + */ + +// [Eugene++ to Martin] we need to unify this prettyprinter with NodePrinters + +package scala.reflect +package internal + +import java.io.{ OutputStream, PrintWriter, StringWriter, Writer } +import Flags._ + +trait Printers extends api.Printers { self: SymbolTable => + + //nsc import treeInfo.{ IsTrue, IsFalse } + + final val showOuterTests = false + + /** Adds backticks if the name is a scala keyword. */ + def quotedName(name: Name, decode: Boolean): String = { + val s = if (decode) name.decode else name.toString + val term = name.toTermName + if (nme.keywords(term) && term != nme.USCOREkw) "`%s`" format s + else s + } + def quotedName(name: Name): String = quotedName(name, false) + def quotedName(name: String): String = quotedName(newTermName(name), false) + + private def symNameInternal(tree: Tree, name: Name, decoded: Boolean): String = { + val sym = tree.symbol + if (sym.name.toString == nme.ERROR.toString) { + "<" + quotedName(name, decoded) + ": error>" + } else if (sym != null && sym != NoSymbol) { + val prefix = if (sym.isMixinConstructor) "/*%s*/".format(quotedName(sym.owner.name, decoded)) else "" + var suffix = "" + if (settings.uniqid.value) suffix += ("#" + sym.id) + if (settings.Yshowsymkinds.value) suffix += ("#" + sym.abbreviatedKindString) + prefix + quotedName(tree.symbol.decodedName) + suffix + } else { + quotedName(name, decoded) + } + } + + def decodedSymName(tree: Tree, name: Name) = symNameInternal(tree, name, true) + def symName(tree: Tree, name: Name) = symNameInternal(tree, name, false) + + /** Turns a path into a String, introducing backquotes + * as necessary. + */ + def backquotedPath(t: Tree): String = { + t match { + case Select(qual, name) if name.isTermName => "%s.%s".format(backquotedPath(qual), symName(t, name)) + case Select(qual, name) if name.isTypeName => "%s#%s".format(backquotedPath(qual), symName(t, name)) + case Ident(name) => symName(t, name) + case _ => t.toString + } + } + + class TreePrinter(out: PrintWriter) extends super.TreePrinter { + protected var indentMargin = 0 + protected val indentStep = 2 + protected var indentString = " " // 40 + + printTypes = settings.printtypes.value + printIds = settings.uniqid.value + printKinds = settings.Yshowsymkinds.value + protected def doPrintPositions = settings.Xprintpos.value + + def indent() = indentMargin += indentStep + def undent() = indentMargin -= indentStep + + def printPosition(tree: Tree) = if (doPrintPositions) print(tree.pos.show) + + def println() { + out.println() + while (indentMargin > indentString.length()) + indentString += indentString + if (indentMargin > 0) + out.write(indentString, 0, indentMargin) + } + + def printSeq[a](ls: List[a])(printelem: a => Unit)(printsep: => Unit) { + ls match { + case List() => + case List(x) => printelem(x) + case x :: rest => printelem(x); printsep; printSeq(rest)(printelem)(printsep) + } + } + + 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) + } + + def printRow(ts: List[Tree], start: String, sep: String, end: String) { + print(start); printSeq(ts){print(_)}{print(sep)}; print(end) + } + + def printRow(ts: List[Tree], sep: String) { printRow(ts, "", sep, "") } + + def printTypeParams(ts: List[TypeDef]) { + if (!ts.isEmpty) { + print("["); printSeq(ts){ t => + printAnnotations(t) + printParam(t) + }{print(", ")}; print("]") + } + } + + def printLabelParams(ps: List[Ident]) { + print("(") + printSeq(ps){printLabelParam}{print(", ")} + print(")") + } + + def printLabelParam(p: Ident) { + print(symName(p, p.name)); printOpt(": ", TypeTree() setType p.tpe) + } + + def printValueParams(ts: List[ValDef]) { + print("(") + if (!ts.isEmpty) printFlags(ts.head.mods.flags & IMPLICIT, "") + printSeq(ts){printParam}{print(", ")} + print(")") + } + + def printParam(tree: Tree) { + tree match { + case ValDef(mods, name, tp, rhs) => + printPosition(tree) + printAnnotations(tree) + print(symName(tree, name)); printOpt(": ", tp); printOpt(" = ", rhs) + case TypeDef(mods, name, tparams, rhs) => + printPosition(tree) + print(symName(tree, name)) + printTypeParams(tparams); print(rhs) + } + } + + def printBlock(tree: Tree) { + tree match { + case Block(_, _) => + print(tree) + case _ => + printColumn(List(tree), "{", ";", "}") + } + } + + private def symFn[T](tree: Tree, f: Symbol => T, orElse: => T): T = tree.symbol match { + case null | NoSymbol => orElse + case sym => f(sym) + } + private def ifSym(tree: Tree, p: Symbol => Boolean) = symFn(tree, p, false) + + def printOpt(prefix: String, tree: Tree) { + if (!tree.isEmpty) { print(prefix, tree) } + } + + def printModifiers(tree: Tree, mods: Modifiers): Unit = printFlags( + if (tree.symbol == NoSymbol) mods.flags else tree.symbol.flags, "" + ( + if (tree.symbol == NoSymbol) mods.privateWithin + else if (tree.symbol.hasAccessBoundary) tree.symbol.privateWithin.name + else "" + ) + ) + + def printFlags(flags: Long, privateWithin: String) { + var mask: Long = if (settings.debug.value) -1L else PrintableFlags + val s = flagsToString(flags & mask, privateWithin) + if (s != "") print(s + " ") + } + + def printAnnotations(tree: Tree) { + if (!isCompilerUniverse && tree.symbol != null && tree.symbol != NoSymbol) + // [Eugene++] todo. this is not 100% correct, but is necessary for sane printing + // the problem is that getting annotations doesn't automatically initialize the symbol + // so we might easily print something as if it doesn't have annotations, whereas it does + tree.symbol.initialize + + val annots = tree.symbol.annotations match { + case Nil => tree.asInstanceOf[MemberDef].mods.annotations + case anns => anns + } + annots foreach (annot => print("@"+annot+" ")) + } + + private var currentOwner: Symbol = NoSymbol + private var selectorType: Type = NoType + + def printTree(tree: Tree) { + tree match { + case EmptyTree => + print("") + + case ClassDef(mods, name, tparams, impl) => + printAnnotations(tree) + printModifiers(tree, mods) + val word = + if (mods.isTrait) "trait" + else if (ifSym(tree, _.isModuleClass)) "object" + else "class" + + print(word, " ", symName(tree, name)) + printTypeParams(tparams) + print(if (mods.isDeferred) " <: " else " extends ", impl) + + case PackageDef(packaged, stats) => + printAnnotations(tree) + print("package ", packaged); printColumn(stats, " {", ";", "}") + + case ModuleDef(mods, name, impl) => + printAnnotations(tree) + 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 ", symName(tree, name)) + printOpt(": ", tp) + if (!mods.isDeferred) + print(" = ", if (rhs.isEmpty) "_" else rhs) + + case DefDef(mods, name, tparams, vparamss, tp, rhs) => + printAnnotations(tree) + printModifiers(tree, mods) + print("def " + symName(tree, name)) + printTypeParams(tparams); vparamss foreach printValueParams + printOpt(": ", tp); printOpt(" = ", rhs) + + case TypeDef(mods, name, tparams, rhs) => + if (mods hasFlag (PARAM | DEFERRED)) { + printAnnotations(tree) + printModifiers(tree, mods); print("type "); printParam(tree) + } else { + printAnnotations(tree) + printModifiers(tree, mods); print("type " + symName(tree, name)) + printTypeParams(tparams); printOpt(" = ", rhs) + } + + case LabelDef(name, params, rhs) => + print(symName(tree, name)); printLabelParams(params); printBlock(rhs) + + case Import(expr, selectors) => + // Is this selector remapping a name (i.e, {name1 => name2}) + def isNotRemap(s: ImportSelector) : Boolean = (s.name == nme.WILDCARD || s.name == s.rename) + def selectorToString(s: ImportSelector): String = { + val from = quotedName(s.name) + if (isNotRemap(s)) from + else from + "=>" + quotedName(s.rename) + } + 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("{", selectorToString(s), "}") + // If there is more than one selector braces are always needed + case many => + print(many.map(selectorToString).mkString("{", ", ", "}")) + } + + case Template(parents, self, body) => + val currentOwner1 = currentOwner + if (tree.symbol != NoSymbol) currentOwner = tree.symbol.owner +// if (parents exists isReferenceToAnyVal) { +// print("AnyVal") +// } +// else { + printRow(parents, " with ") + if (!body.isEmpty) { + if (self.name != nme.WILDCARD) { + print(" { ", self.name); printOpt(": ", self.tpt); print(" => ") + } else if (!self.tpt.isEmpty) { + print(" { _ : ", self.tpt, " => ") + } else { + print(" {") + } + printColumn(body, "", ";", "}") + } +// } + currentOwner = currentOwner1 + + case Block(stats, expr) => + printColumn(stats ::: List(expr), "{", ";", "}") + + case Match(selector, cases) => + val selectorType1 = selectorType + selectorType = selector.tpe + print(selector); printColumn(cases, " match {", "", "}") + selectorType = selectorType1 + + case CaseDef(pat, guard, body) => + print("case ") + def patConstr(pat: Tree): Tree = pat match { + case Apply(fn, args) => patConstr(fn) + case _ => pat + } + if (showOuterTests && + needsOuterTest( + patConstr(pat).tpe.finalResultType, selectorType, currentOwner)) + print("???") + print(pat); printOpt(" if ", guard) + print(" => ", body) + + case Alternative(trees) => + printRow(trees, "(", "| ", ")") + + case Star(elem) => + print("(", elem, ")*") + + case Bind(name, t) => + print("(", symName(tree, name), " @ ", t, ")") + + case UnApply(fun, args) => + print(fun, " "); printRow(args, "(", ", ", ")") + + case ArrayValue(elemtpt, trees) => + print("Array[", elemtpt); printRow(trees, "]{", ", ", "}") + + case Function(vparams, body) => + print("("); printValueParams(vparams); print(" => ", body, ")") + if (printIds && tree.symbol != null) print("#"+tree.symbol.id) + + case Assign(lhs, rhs) => + print(lhs, " = ", rhs) + + case AssignOrNamedArg(lhs, rhs) => + print(lhs, " = ", rhs) + + case If(cond, thenp, elsep) => + print("if (", cond, ")"); indent; println() + print(thenp); undent + if (!elsep.isEmpty) { + println(); print("else"); indent; println(); print(elsep); undent + } + + case Return(expr) => + print("return ", expr) + + case Try(block, catches, finalizer) => + print("try "); printBlock(block) + if (!catches.isEmpty) printColumn(catches, " catch {", "", "}") + printOpt(" finally ", finalizer) + + case Throw(expr) => + print("throw ", expr) + + case New(tpe) => + print("new ", tpe) + + case Typed(expr, tp) => + print("(", expr, ": ", tp, ")") + + case TypeApply(fun, targs) => + print(fun); printRow(targs, "[", ", ", "]") + + case Apply(fun, vargs) => + print(fun); printRow(vargs, "(", ", ", ")") + + case ApplyDynamic(qual, vargs) => + print("(", qual, "#", tree.symbol.nameString) + printRow(vargs, ", (", ", ", "))") + + case Super(This(qual), mix) => + if (!qual.isEmpty || tree.symbol != NoSymbol) print(symName(tree, qual) + ".") + print("super") + if (!mix.isEmpty) + print("[" + mix + "]") + + case Super(qual, mix) => + print(qual, ".super") + if (!mix.isEmpty) + print("[" + mix + "]") + + case This(qual) => + if (!qual.isEmpty) print(symName(tree, qual) + ".") + print("this") + + case Select(qual @ New(tpe), name) if (!settings.debug.value) => + print(qual) + + case Select(qualifier, name) => + print(backquotedPath(qualifier), ".", symName(tree, name)) + + case id @ Ident(name) => + val str = symName(tree, name) + print( if (id.isBackquoted) "`" + str + "`" else str ) + + case Literal(x) => + print(x.escapedStringValue) + + case tt: TypeTree => + 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) + } else { + print(tree.tpe.toString) + } + + case Annotated(Apply(Select(New(tpt), nme.CONSTRUCTOR), args), tree) => + def printAnnot() { + print("@", tpt) + if (!args.isEmpty) + printRow(args, "(", ",", ")") + } + print(tree, if (tree.isType) " " else ": ") + printAnnot() + + case SingletonTypeTree(ref) => + print(ref, ".type") + + case SelectFromTypeTree(qualifier, selector) => + print(qualifier, "#", symName(tree, selector)) + + case CompoundTypeTree(templ) => + print(templ) + + case AppliedTypeTree(tp, args) => + print(tp); printRow(args, "[", ", ", "]") + + case TypeBoundsTree(lo, hi) => + printOpt(" >: ", lo); printOpt(" <: ", hi) + + case ExistentialTypeTree(tpt, whereClauses) => + print(tpt); + printColumn(whereClauses, " forSome { ", ";", "}") + +// SelectFromArray is no longer visible in reflect.internal. +// eliminated until we figure out what we will do with both Printers and +// SelectFromArray. +// case SelectFromArray(qualifier, name, _) => +// print(qualifier); print("."); print(symName(tree, name)) + + case tree => + xprintTree(this, tree) + } + if (printTypes && tree.isTerm && !tree.isEmpty) { + print("{", if (tree.tpe eq null) "" else tree.tpe.toString, "}") + } + } + + def print(args: Any*): Unit = args foreach { + case tree: Tree => + printPosition(tree) + printTree(tree) + case name: Name => + print(quotedName(name)) + case arg => + out.print(if (arg == null) "null" else arg.toString) + } + } + + /** Hook for extensions */ + def xprintTree(treePrinter: TreePrinter, tree: Tree) = + treePrinter.print(tree.productPrefix+tree.productIterator.mkString("(", ", ", ")")) + + def newTreePrinter(writer: PrintWriter): TreePrinter = new TreePrinter(writer) + def newTreePrinter(stream: OutputStream): TreePrinter = newTreePrinter(new PrintWriter(stream)) + def newTreePrinter(): TreePrinter = newTreePrinter(new PrintWriter(ConsoleWriter)) + + /** A writer that writes to the current Console and + * is sensitive to replacement of the Console's + * output stream. + */ + object ConsoleWriter extends Writer { + override def write(str: String) { Console.print(str) } + + def write(cbuf: Array[Char], off: Int, len: Int) { + write(new String(cbuf, off, len)) + } + + def close = { /* do nothing */ } + def flush = { /* do nothing */ } + } + + // provides footnotes for types + private var typeCounter = 0 + private val typeMap = collection.mutable.WeakHashMap[Type, Int]() + + def newRawTreePrinter(writer: PrintWriter): RawTreePrinter = new RawTreePrinter(writer) + def newRawTreePrinter(stream: OutputStream): RawTreePrinter = newRawTreePrinter(new PrintWriter(stream)) + def newRawTreePrinter(): RawTreePrinter = newRawTreePrinter(new PrintWriter(ConsoleWriter)) + + // emits more or less verbatim representation of the provided tree + class RawTreePrinter(out: PrintWriter) extends super.TreePrinter { + private var depth = 0 + private var footnotes = collection.mutable.Map[Int, Type]() + private var printingFootnotes = false + private var printTypesInFootnotes = true + + def print(args: Any*): Unit = { + if (depth == 0 && args.length == 1 && args(0) != null && args(0).isInstanceOf[Type]) + printTypesInFootnotes = false + + depth += 1 + args foreach { + case EmptyTree => + print("EmptyTree") + case emptyValDef: AnyRef if emptyValDef eq self.emptyValDef => + print("emptyValDef") + case Literal(Constant(value)) => + def print(s: String) = this.print("Literal(Constant(" + s + "))") + value match { + case s: String => print("\"" + s + "\"") + case null => print(null) + case _ => print(value.toString) + } + case tree: Tree => + val hasSymbol = tree.hasSymbol && tree.symbol != NoSymbol + val isError = hasSymbol && tree.symbol.name.toString == nme.ERROR.toString + printProduct( + tree, + preamble = _ => { + print(tree.productPrefix) + if (printTypes && tree.tpe != null) print(tree.tpe) + }, + body = { + case name: Name => + if (isError) { + if (isError) print("<") + print(name) + if (isError) print(": error>") + } else if (hasSymbol) { + tree match { + case _: Ident | _: Select | _: SelectFromTypeTree => print(tree.symbol) + case _ => print(tree.symbol.name) + } + } else { + print(name) + } + case arg => + print(arg) + }, + postamble = { + case tree @ TypeTree() if tree.original != null => print(".setOriginal(", tree.original, ")") + case _ => // do nothing + }) + case sym: Symbol => + if (sym.isStatic && (sym.isClass || sym.isModule)) print(sym.fullName) + else print(sym.name) + if (printIds) print("#", sym.id) + if (printKinds) print("#", sym.abbreviatedKindString) + case NoType => + print("NoType") + case NoPrefix => + print("NoPrefix") + case tpe: Type if printTypesInFootnotes && !printingFootnotes => + val index = typeMap.getOrElseUpdate(tpe, { typeCounter += 1; typeCounter }) + footnotes(index) = tpe + print("[", index, "]") + case mods: Modifiers => + print("Modifiers(") + if (mods.flags != NoFlags || mods.privateWithin != tpnme.EMPTY || mods.annotations.nonEmpty) print(show(mods.flags)) + if (mods.privateWithin != tpnme.EMPTY || mods.annotations.nonEmpty) { print(", "); print(mods.privateWithin) } + if (mods.annotations.nonEmpty) { print(", "); print(mods.annotations); } + print(")") + case name: Name => + print(show(name)) + case list: List[_] => + print("List") + printIterable(list) + case product: Product => + printProduct(product) + case arg => + out.print(arg) + } + depth -= 1 + if (depth == 0 && footnotes.nonEmpty && !printingFootnotes) { + printingFootnotes = true + out.println() + val typeIndices = footnotes.keys.toList.sorted + typeIndices.zipWithIndex foreach { + case (typeIndex, i) => + print("[" + typeIndex + "] ") + print(footnotes(typeIndex)) + if (i < typeIndices.length - 1) out.println() + } + } + } + + def printProduct( + p: Product, + preamble: Product => Unit = p => print(p.productPrefix), + body: Any => Unit = print(_), + postamble: Product => Unit = p => print("")): Unit = + { + preamble(p) + printIterable(p.productIterator.toList, body = body) + postamble(p) + } + + def printIterable( + iterable: List[_], + preamble: => Unit = print(""), + body: Any => Unit = print(_), + postamble: => Unit = print("")): Unit = + { + preamble + print("(") + val it = iterable.iterator + while (it.hasNext) { + body(it.next) + print(if (it.hasNext) ", " else "") + } + print(")") + postamble + } + } + + def show(name: Name): String = name match { + // base.StandardNames + case tpnme.EMPTY => "tpnme.EMPTY" + case tpnme.ROOT => "tpnme.ROOT" + case tpnme.EMPTY_PACKAGE_NAME => "tpnme.EMPTY_PACKAGE_NAME" + case tpnme.WILDCARD => "tpnme.WILDCARD" + case nme.CONSTRUCTOR => "nme.CONSTRUCTOR" + case nme.NO_NAME => "nme.NO_NAME" + // api.StandardNames + case tpnme.ERROR => "tpnme.ERROR" + case nme.ERROR => "nme.ERROR" + case nme.EMPTY => "nme.EMPTY" + case tpnme.PACKAGE => "tpnme.PACKAGE" + case nme.PACKAGE => "nme.PACKAGE" + case _ => + val prefix = if (name.isTermName) "newTermName(\"" else "newTypeName(\"" + prefix + name.toString + "\")" + } + + def show(flags: FlagSet): String = { + if (flags == NoFlags) nme.NoFlags.toString + else { + val s_flags = new collection.mutable.ListBuffer[String] + for (i <- 0 to 63 if (flags containsAll (1L << i))) + s_flags += flagToString(1L << i).replace("<", "").replace(">", "").toUpperCase + s_flags mkString " | " + } + } +} diff --git a/src/reflect/scala/reflect/internal/SymbolTable.scala b/src/reflect/scala/reflect/internal/SymbolTable.scala index cadd76b1ba..6def4d9409 100644 --- a/src/reflect/scala/reflect/internal/SymbolTable.scala +++ b/src/reflect/scala/reflect/internal/SymbolTable.scala @@ -28,7 +28,7 @@ abstract class SymbolTable extends makro.Universe with AnnotationInfos with AnnotationCheckers with Trees - with TreePrinters + with Printers with Positions with TypeDebugging with Importers diff --git a/src/reflect/scala/reflect/internal/TreePrinters.scala b/src/reflect/scala/reflect/internal/TreePrinters.scala deleted file mode 100644 index 6d035c8b9d..0000000000 --- a/src/reflect/scala/reflect/internal/TreePrinters.scala +++ /dev/null @@ -1,478 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2005-2011 LAMP/EPFL - * @author Martin Odersky - */ - -// [Eugene++ to Martin] we need to unify this prettyprinter with NodePrinters - -package scala.reflect -package internal - -import java.io.{ OutputStream, PrintWriter, StringWriter, Writer } -import Flags._ - -trait TreePrinters extends api.TreePrinters { self: SymbolTable => - - //nsc import treeInfo.{ IsTrue, IsFalse } - - final val showOuterTests = false - - /** Adds backticks if the name is a scala keyword. */ - def quotedName(name: Name, decode: Boolean): String = { - val s = if (decode) name.decode else name.toString - val term = name.toTermName - if (nme.keywords(term) && term != nme.USCOREkw) "`%s`" format s - else s - } - def quotedName(name: Name): String = quotedName(name, false) - def quotedName(name: String): String = quotedName(newTermName(name), false) - - private def symNameInternal(tree: Tree, name: Name, decoded: Boolean): String = { - val sym = tree.symbol - if (sym.name.toString == nme.ERROR.toString) { - "<" + quotedName(name, decoded) + ": error>" - } else if (sym != null && sym != NoSymbol) { - val prefix = if (sym.isMixinConstructor) "/*%s*/".format(quotedName(sym.owner.name, decoded)) else "" - var suffix = "" - if (settings.uniqid.value) suffix += ("#" + sym.id) - if (settings.Yshowsymkinds.value) suffix += ("#" + sym.abbreviatedKindString) - prefix + quotedName(tree.symbol.decodedName) + suffix - } else { - quotedName(name, decoded) - } - } - - def decodedSymName(tree: Tree, name: Name) = symNameInternal(tree, name, true) - def symName(tree: Tree, name: Name) = symNameInternal(tree, name, false) - - /** Turns a path into a String, introducing backquotes - * as necessary. - */ - def backquotedPath(t: Tree): String = { - t match { - case Select(qual, name) if name.isTermName => "%s.%s".format(backquotedPath(qual), symName(t, name)) - case Select(qual, name) if name.isTypeName => "%s#%s".format(backquotedPath(qual), symName(t, name)) - case Ident(name) => symName(t, name) - case _ => t.toString - } - } - - class TreePrinter(out: PrintWriter) extends super.TreePrinter { - protected var indentMargin = 0 - protected val indentStep = 2 - protected var indentString = " " // 40 - - typesPrinted = settings.printtypes.value - uniqueIds = settings.uniqid.value - protected def doPrintPositions = settings.Xprintpos.value - - def indent() = indentMargin += indentStep - def undent() = indentMargin -= indentStep - - def printPosition(tree: Tree) = if (doPrintPositions) print(tree.pos.show) - - def println() { - out.println() - while (indentMargin > indentString.length()) - indentString += indentString - if (indentMargin > 0) - out.write(indentString, 0, indentMargin) - } - - def printSeq[a](ls: List[a])(printelem: a => Unit)(printsep: => Unit) { - ls match { - case List() => - case List(x) => printelem(x) - case x :: rest => printelem(x); printsep; printSeq(rest)(printelem)(printsep) - } - } - - 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) - } - - def printRow(ts: List[Tree], start: String, sep: String, end: String) { - print(start); printSeq(ts){print(_)}{print(sep)}; print(end) - } - - def printRow(ts: List[Tree], sep: String) { printRow(ts, "", sep, "") } - - def printTypeParams(ts: List[TypeDef]) { - if (!ts.isEmpty) { - print("["); printSeq(ts){ t => - printAnnotations(t) - printParam(t) - }{print(", ")}; print("]") - } - } - - def printLabelParams(ps: List[Ident]) { - print("(") - printSeq(ps){printLabelParam}{print(", ")} - print(")") - } - - def printLabelParam(p: Ident) { - print(symName(p, p.name)); printOpt(": ", TypeTree() setType p.tpe) - } - - def printValueParams(ts: List[ValDef]) { - print("(") - if (!ts.isEmpty) printFlags(ts.head.mods.flags & IMPLICIT, "") - printSeq(ts){printParam}{print(", ")} - print(")") - } - - def printParam(tree: Tree) { - tree match { - case ValDef(mods, name, tp, rhs) => - printPosition(tree) - printAnnotations(tree) - print(symName(tree, name)); printOpt(": ", tp); printOpt(" = ", rhs) - case TypeDef(mods, name, tparams, rhs) => - printPosition(tree) - print(symName(tree, name)) - printTypeParams(tparams); print(rhs) - } - } - - def printBlock(tree: Tree) { - tree match { - case Block(_, _) => - print(tree) - case _ => - printColumn(List(tree), "{", ";", "}") - } - } - - private def symFn[T](tree: Tree, f: Symbol => T, orElse: => T): T = tree.symbol match { - case null | NoSymbol => orElse - case sym => f(sym) - } - private def ifSym(tree: Tree, p: Symbol => Boolean) = symFn(tree, p, false) - - def printOpt(prefix: String, tree: Tree) { - if (!tree.isEmpty) { print(prefix, tree) } - } - - def printModifiers(tree: Tree, mods: Modifiers): Unit = printFlags( - if (tree.symbol == NoSymbol) mods.flags else tree.symbol.flags, "" + ( - if (tree.symbol == NoSymbol) mods.privateWithin - else if (tree.symbol.hasAccessBoundary) tree.symbol.privateWithin.name - else "" - ) - ) - - def printFlags(flags: Long, privateWithin: String) { - var mask: Long = if (settings.debug.value) -1L else PrintableFlags - val s = flagsToString(flags & mask, privateWithin) - if (s != "") print(s + " ") - } - - def printAnnotations(tree: Tree) { - if (!isCompilerUniverse && tree.symbol != null && tree.symbol != NoSymbol) - // [Eugene++] todo. this is not 100% correct, but is necessary for sane printing - // the problem is that getting annotations doesn't automatically initialize the symbol - // so we might easily print something as if it doesn't have annotations, whereas it does - tree.symbol.initialize - - val annots = tree.symbol.annotations match { - case Nil => tree.asInstanceOf[MemberDef].mods.annotations - case anns => anns - } - annots foreach (annot => print("@"+annot+" ")) - } - - private var currentOwner: Symbol = NoSymbol - private var selectorType: Type = NoType - - def printTree(tree: Tree) { - tree match { - case EmptyTree => - print("") - - case ClassDef(mods, name, tparams, impl) => - printAnnotations(tree) - printModifiers(tree, mods) - val word = - if (mods.isTrait) "trait" - else if (ifSym(tree, _.isModuleClass)) "object" - else "class" - - print(word, " ", symName(tree, name)) - printTypeParams(tparams) - print(if (mods.isDeferred) " <: " else " extends ", impl) - - case PackageDef(packaged, stats) => - printAnnotations(tree) - print("package ", packaged); printColumn(stats, " {", ";", "}") - - case ModuleDef(mods, name, impl) => - printAnnotations(tree) - 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 ", symName(tree, name)) - printOpt(": ", tp) - if (!mods.isDeferred) - print(" = ", if (rhs.isEmpty) "_" else rhs) - - case DefDef(mods, name, tparams, vparamss, tp, rhs) => - printAnnotations(tree) - printModifiers(tree, mods) - print("def " + symName(tree, name)) - printTypeParams(tparams); vparamss foreach printValueParams - printOpt(": ", tp); printOpt(" = ", rhs) - - case TypeDef(mods, name, tparams, rhs) => - if (mods hasFlag (PARAM | DEFERRED)) { - printAnnotations(tree) - printModifiers(tree, mods); print("type "); printParam(tree) - } else { - printAnnotations(tree) - printModifiers(tree, mods); print("type " + symName(tree, name)) - printTypeParams(tparams); printOpt(" = ", rhs) - } - - case LabelDef(name, params, rhs) => - print(symName(tree, name)); printLabelParams(params); printBlock(rhs) - - case Import(expr, selectors) => - // Is this selector remapping a name (i.e, {name1 => name2}) - def isNotRemap(s: ImportSelector) : Boolean = (s.name == nme.WILDCARD || s.name == s.rename) - def selectorToString(s: ImportSelector): String = { - val from = quotedName(s.name) - if (isNotRemap(s)) from - else from + "=>" + quotedName(s.rename) - } - 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("{", selectorToString(s), "}") - // If there is more than one selector braces are always needed - case many => - print(many.map(selectorToString).mkString("{", ", ", "}")) - } - - case Template(parents, self, body) => - val currentOwner1 = currentOwner - if (tree.symbol != NoSymbol) currentOwner = tree.symbol.owner -// if (parents exists isReferenceToAnyVal) { -// print("AnyVal") -// } -// else { - printRow(parents, " with ") - if (!body.isEmpty) { - if (self.name != nme.WILDCARD) { - print(" { ", self.name); printOpt(": ", self.tpt); print(" => ") - } else if (!self.tpt.isEmpty) { - print(" { _ : ", self.tpt, " => ") - } else { - print(" {") - } - printColumn(body, "", ";", "}") - } -// } - currentOwner = currentOwner1 - - case Block(stats, expr) => - printColumn(stats ::: List(expr), "{", ";", "}") - - case Match(selector, cases) => - val selectorType1 = selectorType - selectorType = selector.tpe - print(selector); printColumn(cases, " match {", "", "}") - selectorType = selectorType1 - - case CaseDef(pat, guard, body) => - print("case ") - def patConstr(pat: Tree): Tree = pat match { - case Apply(fn, args) => patConstr(fn) - case _ => pat - } - if (showOuterTests && - needsOuterTest( - patConstr(pat).tpe.finalResultType, selectorType, currentOwner)) - print("???") - print(pat); printOpt(" if ", guard) - print(" => ", body) - - case Alternative(trees) => - printRow(trees, "(", "| ", ")") - - case Star(elem) => - print("(", elem, ")*") - - case Bind(name, t) => - print("(", symName(tree, name), " @ ", t, ")") - - case UnApply(fun, args) => - print(fun, " "); printRow(args, "(", ", ", ")") - - case ArrayValue(elemtpt, trees) => - print("Array[", elemtpt); printRow(trees, "]{", ", ", "}") - - case Function(vparams, body) => - print("("); printValueParams(vparams); print(" => ", body, ")") - if (uniqueIds && tree.symbol != null) print("#"+tree.symbol.id) - - case Assign(lhs, rhs) => - print(lhs, " = ", rhs) - - case AssignOrNamedArg(lhs, rhs) => - print(lhs, " = ", rhs) - - case If(cond, thenp, elsep) => - print("if (", cond, ")"); indent; println() - print(thenp); undent - if (!elsep.isEmpty) { - println(); print("else"); indent; println(); print(elsep); undent - } - - case Return(expr) => - print("return ", expr) - - case Try(block, catches, finalizer) => - print("try "); printBlock(block) - if (!catches.isEmpty) printColumn(catches, " catch {", "", "}") - printOpt(" finally ", finalizer) - - case Throw(expr) => - print("throw ", expr) - - case New(tpe) => - print("new ", tpe) - - case Typed(expr, tp) => - print("(", expr, ": ", tp, ")") - - case TypeApply(fun, targs) => - print(fun); printRow(targs, "[", ", ", "]") - - case Apply(fun, vargs) => - print(fun); printRow(vargs, "(", ", ", ")") - - case ApplyDynamic(qual, vargs) => - print("(", qual, "#", tree.symbol.nameString) - printRow(vargs, ", (", ", ", "))") - - case Super(This(qual), mix) => - if (!qual.isEmpty || tree.symbol != NoSymbol) print(symName(tree, qual) + ".") - print("super") - if (!mix.isEmpty) - print("[" + mix + "]") - - case Super(qual, mix) => - print(qual, ".super") - if (!mix.isEmpty) - print("[" + mix + "]") - - case This(qual) => - if (!qual.isEmpty) print(symName(tree, qual) + ".") - print("this") - - case Select(qual @ New(tpe), name) if (!settings.debug.value) => - print(qual) - - case Select(qualifier, name) => - print(backquotedPath(qualifier), ".", symName(tree, name)) - - case id @ Ident(name) => - val str = symName(tree, name) - print( if (id.isBackquoted) "`" + str + "`" else str ) - - case Literal(x) => - print(x.escapedStringValue) - - case tt: TypeTree => - 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) - } else { - print(tree.tpe.toString) - } - - case Annotated(Apply(Select(New(tpt), nme.CONSTRUCTOR), args), tree) => - def printAnnot() { - print("@", tpt) - if (!args.isEmpty) - printRow(args, "(", ",", ")") - } - print(tree, if (tree.isType) " " else ": ") - printAnnot() - - case SingletonTypeTree(ref) => - print(ref, ".type") - - case SelectFromTypeTree(qualifier, selector) => - print(qualifier, "#", symName(tree, selector)) - - case CompoundTypeTree(templ) => - print(templ) - - case AppliedTypeTree(tp, args) => - print(tp); printRow(args, "[", ", ", "]") - - case TypeBoundsTree(lo, hi) => - printOpt(" >: ", lo); printOpt(" <: ", hi) - - case ExistentialTypeTree(tpt, whereClauses) => - print(tpt); - printColumn(whereClauses, " forSome { ", ";", "}") - -// SelectFromArray is no longer visible in reflect.internal. -// eliminated until we figure out what we will do with both TreePrinters and -// SelectFromArray. -// case SelectFromArray(qualifier, name, _) => -// print(qualifier); print("."); print(symName(tree, name)) - - case tree => - xprintTree(this, tree) - } - if (typesPrinted && tree.isTerm && !tree.isEmpty) { - print("{", if (tree.tpe eq null) "" else tree.tpe.toString, "}") - } - } - - def print(args: Any*): Unit = args foreach { - case tree: Tree => - printPosition(tree) - printTree(tree) - case name: Name => - print(quotedName(name)) - case arg => - out.print(if (arg == null) "null" else arg.toString) - } - } - - /** Hook for extensions */ - def xprintTree(treePrinter: TreePrinter, tree: Tree) = - treePrinter.print(tree.productPrefix+tree.productIterator.mkString("(", ", ", ")")) - - def newTreePrinter(writer: PrintWriter): TreePrinter = new TreePrinter(writer) - def newTreePrinter(stream: OutputStream): TreePrinter = newTreePrinter(new PrintWriter(stream)) - def newTreePrinter(): TreePrinter = newTreePrinter(new PrintWriter(ConsoleWriter)) - - /** A writer that writes to the current Console and - * is sensitive to replacement of the Console's - * output stream. - */ - object ConsoleWriter extends Writer { - override def write(str: String) { Console.print(str) } - - def write(cbuf: Array[Char], off: Int, len: Int) { - write(new String(cbuf, off, len)) - } - - def close = { /* do nothing */ } - def flush = { /* do nothing */ } - } -} diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala index 75bb0e6d49..562a49519f 100644 --- a/src/reflect/scala/reflect/internal/Trees.scala +++ b/src/reflect/scala/reflect/internal/Trees.scala @@ -809,7 +809,7 @@ trait Trees extends api.Trees { self: SymbolTable => } } - // Belongs in TreeInfo but then I can't reach it from TreePrinters. + // Belongs in TreeInfo but then I can't reach it from Printers. def isReferenceToScalaMember(t: Tree, Id: Name) = t match { case Ident(Id) => true case Select(Ident(nme.scala_), Id) => true diff --git a/src/reflect/scala/reflect/makro/Universe.scala b/src/reflect/scala/reflect/makro/Universe.scala index ffc4042a0a..98046be555 100644 --- a/src/reflect/scala/reflect/makro/Universe.scala +++ b/src/reflect/scala/reflect/makro/Universe.scala @@ -15,25 +15,6 @@ abstract class Universe extends scala.reflect.api.Universe { // [Eugene++ to Martin] should we also add mutability methods here (similarly to what's done below for trees)? // I'm talking about `setAnnotations` and friends - - /** Can this symbol be loaded by a reflective mirror? - * - * Scalac relies on `ScalaSignature' annotation to retain symbols across compilation runs. - * Such annotations (also called "pickles") are applied on top-level classes and include information - * about all symbols reachable from the annotee. However, local symbols (e.g. classes or definitions local to a block) - * are typically unreachable and information about them gets lost. - * - * This method is useful for macro writers who wish to save certain ASTs to be used at runtime. - * With `isLocatable' it's possible to check whether a tree can be retained as is, or it needs special treatment. - */ - def isLocatable: Boolean - - /** Is this symbol static (i.e. with no outer instance)? - * Q: When exactly is a sym marked as STATIC? - * A: If it's a member of a toplevel object, or of an object contained in a toplevel object, or any number of levels deep. - * http://groups.google.com/group/scala-internals/browse_thread/thread/d385bcd60b08faf6 - */ - def isStatic: Boolean } // Tree extensions --------------------------------------------------------------- diff --git a/test/files/run/showraw_mods.check b/test/files/run/showraw_mods.check new file mode 100644 index 0000000000..83055f2b70 --- /dev/null +++ b/test/files/run/showraw_mods.check @@ -0,0 +1 @@ +Block(List(ClassDef(Modifiers(ABSTRACT | DEFAULTPARAM/TRAIT), newTypeName("C"), List(), Template(List(Ident(java.lang.Object)), emptyValDef, List(DefDef(Modifiers(), newTermName("$init$"), List(), List(List()), TypeTree(), Block(List(), Literal(Constant(())))), ValDef(Modifiers(PRIVATE | LOCAL), newTermName("x"), TypeTree(), Literal(Constant(2))), ValDef(Modifiers(MUTABLE), newTermName("y"), TypeTree(), Select(This(newTypeName("C")), newTermName("x"))), ValDef(Modifiers(LAZY), newTermName("z"), TypeTree(), Select(This(newTypeName("C")), newTermName("y"))))))), Literal(Constant(()))) diff --git a/test/files/run/showraw_mods.scala b/test/files/run/showraw_mods.scala new file mode 100644 index 0000000000..a10e4821dc --- /dev/null +++ b/test/files/run/showraw_mods.scala @@ -0,0 +1,6 @@ +import scala.reflect.runtime.universe._ + +object Test extends App { + val tree = reify{trait C { private[this] val x = 2; var y = x; lazy val z = y }} + println(showRaw(tree.tree)) +} \ No newline at end of file diff --git a/test/files/run/showraw_tree.check b/test/files/run/showraw_tree.check new file mode 100644 index 0000000000..82724cae44 --- /dev/null +++ b/test/files/run/showraw_tree.check @@ -0,0 +1,2 @@ +Apply(Select(New(AppliedTypeTree(Ident(scala.collection.immutable.HashMap), List(Ident(java.lang.String), Ident(java.lang.String)))), nme.CONSTRUCTOR), List()) +Apply(Select(New(AppliedTypeTree(Ident(scala.collection.mutable.HashMap), List(Ident(java.lang.String), Ident(java.lang.String)))), nme.CONSTRUCTOR), List()) diff --git a/test/files/run/showraw_tree.scala b/test/files/run/showraw_tree.scala new file mode 100644 index 0000000000..3624a24d6a --- /dev/null +++ b/test/files/run/showraw_tree.scala @@ -0,0 +1,8 @@ +import scala.reflect.runtime.universe._ + +object Test extends App { + val tree1 = reify(new collection.immutable.HashMap[String, String]) + val tree2 = reify(new collection.mutable.HashMap[String, String]) + println(showRaw(tree1.tree)) + println(showRaw(tree2.tree)) +} \ No newline at end of file diff --git a/test/files/run/showraw_tree_ids.check b/test/files/run/showraw_tree_ids.check new file mode 100644 index 0000000000..c6dbd6f1ce --- /dev/null +++ b/test/files/run/showraw_tree_ids.check @@ -0,0 +1,2 @@ +Apply(Select(New(AppliedTypeTree(Ident(scala.collection.immutable.HashMap#1903), List(Ident(java.lang.String#129), Ident(java.lang.String#129)))), nme.CONSTRUCTOR), List()) +Apply(Select(New(AppliedTypeTree(Ident(scala.collection.mutable.HashMap#1908), List(Ident(java.lang.String#129), Ident(java.lang.String#129)))), nme.CONSTRUCTOR), List()) diff --git a/test/files/run/showraw_tree_ids.scala b/test/files/run/showraw_tree_ids.scala new file mode 100644 index 0000000000..b56b8b4476 --- /dev/null +++ b/test/files/run/showraw_tree_ids.scala @@ -0,0 +1,8 @@ +import scala.reflect.runtime.universe._ + +object Test extends App { + val tree1 = reify(new collection.immutable.HashMap[String, String]) + val tree2 = reify(new collection.mutable.HashMap[String, String]) + println(showRaw(tree1.tree, printIds = true)) + println(showRaw(tree2.tree, printIds = true)) +} \ No newline at end of file diff --git a/test/files/run/showraw_tree_kinds.check b/test/files/run/showraw_tree_kinds.check new file mode 100644 index 0000000000..a12e21c611 --- /dev/null +++ b/test/files/run/showraw_tree_kinds.check @@ -0,0 +1,2 @@ +Apply(Select(New(AppliedTypeTree(Ident(scala.collection.immutable.HashMap#CLS), List(Ident(java.lang.String#CLS), Ident(java.lang.String#CLS)))), nme.CONSTRUCTOR), List()) +Apply(Select(New(AppliedTypeTree(Ident(scala.collection.mutable.HashMap#CLS), List(Ident(java.lang.String#CLS), Ident(java.lang.String#CLS)))), nme.CONSTRUCTOR), List()) diff --git a/test/files/run/showraw_tree_kinds.scala b/test/files/run/showraw_tree_kinds.scala new file mode 100644 index 0000000000..0ca5a387da --- /dev/null +++ b/test/files/run/showraw_tree_kinds.scala @@ -0,0 +1,8 @@ +import scala.reflect.runtime.universe._ + +object Test extends App { + val tree1 = reify(new collection.immutable.HashMap[String, String]) + val tree2 = reify(new collection.mutable.HashMap[String, String]) + println(showRaw(tree1.tree, printKinds = true)) + println(showRaw(tree2.tree, printKinds = true)) +} \ No newline at end of file diff --git a/test/files/run/showraw_tree_types_ids.check b/test/files/run/showraw_tree_types_ids.check new file mode 100644 index 0000000000..02e7aeed7c --- /dev/null +++ b/test/files/run/showraw_tree_types_ids.check @@ -0,0 +1,10 @@ +Apply[1](Select[2](New[1](TypeTree[1]().setOriginal(AppliedTypeTree(Ident[3](scala.collection.immutable.HashMap#1903), List(TypeTree[4]().setOriginal(Ident[4](java.lang.String#129)), TypeTree[4]().setOriginal(Ident[4](java.lang.String#129)))))), nme.CONSTRUCTOR#1913), List()) +[1] TypeRef(ThisType(scala.collection.immutable#1898), scala.collection.immutable.HashMap#1903, List(TypeRef(ThisType(java.lang#128), java.lang.String#129, List()), TypeRef(ThisType(java.lang#128), java.lang.String#129, List()))) +[2] MethodType(List(), TypeRef(ThisType(scala.collection.immutable#1898), scala.collection.immutable.HashMap#1903, List(TypeRef(ThisType(java.lang#128), java.lang.String#129, List()), TypeRef(ThisType(java.lang#128), java.lang.String#129, List())))) +[3] TypeRef(ThisType(scala.collection.immutable#1898), scala.collection.immutable.HashMap#1903, List()) +[4] TypeRef(ThisType(java.lang#128), java.lang.String#129, List()) +Apply[5](Select[6](New[5](TypeTree[5]().setOriginal(AppliedTypeTree(Ident[7](scala.collection.mutable.HashMap#1908), List(TypeTree[4]().setOriginal(Ident[4](java.lang.String#129)), TypeTree[4]().setOriginal(Ident[4](java.lang.String#129)))))), nme.CONSTRUCTOR#2231), List()) +[4] TypeRef(ThisType(java.lang#128), java.lang.String#129, List()) +[5] TypeRef(ThisType(scala.collection.mutable#1907), scala.collection.mutable.HashMap#1908, List(TypeRef(ThisType(java.lang#128), java.lang.String#129, List()), TypeRef(ThisType(java.lang#128), java.lang.String#129, List()))) +[6] MethodType(List(), TypeRef(ThisType(scala.collection.mutable#1907), scala.collection.mutable.HashMap#1908, List(TypeRef(ThisType(java.lang#128), java.lang.String#129, List()), TypeRef(ThisType(java.lang#128), java.lang.String#129, List())))) +[7] TypeRef(ThisType(scala.collection.mutable#1907), scala.collection.mutable.HashMap#1908, List()) diff --git a/test/files/run/showraw_tree_types_ids.scala b/test/files/run/showraw_tree_types_ids.scala new file mode 100644 index 0000000000..cb2c2bfb0f --- /dev/null +++ b/test/files/run/showraw_tree_types_ids.scala @@ -0,0 +1,10 @@ +import scala.reflect.runtime.universe._ +import scala.tools.reflect.ToolBox + +object Test extends App { + val tb = runtimeMirror(getClass.getClassLoader).mkToolBox() + val tree1 = reify(new collection.immutable.HashMap[String, String]) + val tree2 = reify(new collection.mutable.HashMap[String, String]) + println(showRaw(tb.typeCheck(tree1.tree), printIds = true, printTypes = true)) + println(showRaw(tb.typeCheck(tree2.tree), printIds = true, printTypes = true)) +} \ No newline at end of file diff --git a/test/files/run/showraw_tree_types_typed.check b/test/files/run/showraw_tree_types_typed.check new file mode 100644 index 0000000000..60176c7192 --- /dev/null +++ b/test/files/run/showraw_tree_types_typed.check @@ -0,0 +1,10 @@ +Apply[1](Select[2](New[1](TypeTree[1]().setOriginal(AppliedTypeTree(Ident[3](scala.collection.immutable.HashMap), List(TypeTree[4]().setOriginal(Ident[4](java.lang.String)), TypeTree[4]().setOriginal(Ident[4](java.lang.String)))))), nme.CONSTRUCTOR), List()) +[1] TypeRef(ThisType(scala.collection.immutable), scala.collection.immutable.HashMap, List(TypeRef(ThisType(java.lang), java.lang.String, List()), TypeRef(ThisType(java.lang), java.lang.String, List()))) +[2] MethodType(List(), TypeRef(ThisType(scala.collection.immutable), scala.collection.immutable.HashMap, List(TypeRef(ThisType(java.lang), java.lang.String, List()), TypeRef(ThisType(java.lang), java.lang.String, List())))) +[3] TypeRef(ThisType(scala.collection.immutable), scala.collection.immutable.HashMap, List()) +[4] TypeRef(ThisType(java.lang), java.lang.String, List()) +Apply[5](Select[6](New[5](TypeTree[5]().setOriginal(AppliedTypeTree(Ident[7](scala.collection.mutable.HashMap), List(TypeTree[4]().setOriginal(Ident[4](java.lang.String)), TypeTree[4]().setOriginal(Ident[4](java.lang.String)))))), nme.CONSTRUCTOR), List()) +[4] TypeRef(ThisType(java.lang), java.lang.String, List()) +[5] TypeRef(ThisType(scala.collection.mutable), scala.collection.mutable.HashMap, List(TypeRef(ThisType(java.lang), java.lang.String, List()), TypeRef(ThisType(java.lang), java.lang.String, List()))) +[6] MethodType(List(), TypeRef(ThisType(scala.collection.mutable), scala.collection.mutable.HashMap, List(TypeRef(ThisType(java.lang), java.lang.String, List()), TypeRef(ThisType(java.lang), java.lang.String, List())))) +[7] TypeRef(ThisType(scala.collection.mutable), scala.collection.mutable.HashMap, List()) diff --git a/test/files/run/showraw_tree_types_typed.scala b/test/files/run/showraw_tree_types_typed.scala new file mode 100644 index 0000000000..d7ccc84ea3 --- /dev/null +++ b/test/files/run/showraw_tree_types_typed.scala @@ -0,0 +1,10 @@ +import scala.reflect.runtime.universe._ +import scala.tools.reflect.ToolBox + +object Test extends App { + val tb = runtimeMirror(getClass.getClassLoader).mkToolBox() + val tree1 = reify(new collection.immutable.HashMap[String, String]) + val tree2 = reify(new collection.mutable.HashMap[String, String]) + println(showRaw(tb.typeCheck(tree1.tree), printTypes = true)) + println(showRaw(tb.typeCheck(tree2.tree), printTypes = true)) +} \ No newline at end of file diff --git a/test/files/run/showraw_tree_types_untyped.check b/test/files/run/showraw_tree_types_untyped.check new file mode 100644 index 0000000000..82724cae44 --- /dev/null +++ b/test/files/run/showraw_tree_types_untyped.check @@ -0,0 +1,2 @@ +Apply(Select(New(AppliedTypeTree(Ident(scala.collection.immutable.HashMap), List(Ident(java.lang.String), Ident(java.lang.String)))), nme.CONSTRUCTOR), List()) +Apply(Select(New(AppliedTypeTree(Ident(scala.collection.mutable.HashMap), List(Ident(java.lang.String), Ident(java.lang.String)))), nme.CONSTRUCTOR), List()) diff --git a/test/files/run/showraw_tree_types_untyped.scala b/test/files/run/showraw_tree_types_untyped.scala new file mode 100644 index 0000000000..4df2eb66b2 --- /dev/null +++ b/test/files/run/showraw_tree_types_untyped.scala @@ -0,0 +1,8 @@ +import scala.reflect.runtime.universe._ + +object Test extends App { + val tree1 = reify(new collection.immutable.HashMap[String, String]) + val tree2 = reify(new collection.mutable.HashMap[String, String]) + println(showRaw(tree1.tree, printTypes = true)) + println(showRaw(tree2.tree, printTypes = true)) +} \ No newline at end of file diff --git a/test/files/run/showraw_tree_ultimate.check b/test/files/run/showraw_tree_ultimate.check new file mode 100644 index 0000000000..0b409554a0 --- /dev/null +++ b/test/files/run/showraw_tree_ultimate.check @@ -0,0 +1,10 @@ +Apply[1](Select[2](New[1](TypeTree[1]().setOriginal(AppliedTypeTree(Ident[3](scala.collection.immutable.HashMap#1903#CLS), List(TypeTree[4]().setOriginal(Ident[4](java.lang.String#129#CLS)), TypeTree[4]().setOriginal(Ident[4](java.lang.String#129#CLS)))))), nme.CONSTRUCTOR#1913#PCTOR), List()) +[1] TypeRef(ThisType(scala.collection.immutable#1898#PK), scala.collection.immutable.HashMap#1903#CLS, List(TypeRef(ThisType(java.lang#128#PK), java.lang.String#129#CLS, List()), TypeRef(ThisType(java.lang#128#PK), java.lang.String#129#CLS, List()))) +[2] MethodType(List(), TypeRef(ThisType(scala.collection.immutable#1898#PK), scala.collection.immutable.HashMap#1903#CLS, List(TypeRef(ThisType(java.lang#128#PK), java.lang.String#129#CLS, List()), TypeRef(ThisType(java.lang#128#PK), java.lang.String#129#CLS, List())))) +[3] TypeRef(ThisType(scala.collection.immutable#1898#PK), scala.collection.immutable.HashMap#1903#CLS, List()) +[4] TypeRef(ThisType(java.lang#128#PK), java.lang.String#129#CLS, List()) +Apply[5](Select[6](New[5](TypeTree[5]().setOriginal(AppliedTypeTree(Ident[7](scala.collection.mutable.HashMap#1908#CLS), List(TypeTree[4]().setOriginal(Ident[4](java.lang.String#129#CLS)), TypeTree[4]().setOriginal(Ident[4](java.lang.String#129#CLS)))))), nme.CONSTRUCTOR#2231#CTOR), List()) +[4] TypeRef(ThisType(java.lang#128#PK), java.lang.String#129#CLS, List()) +[5] TypeRef(ThisType(scala.collection.mutable#1907#PK), scala.collection.mutable.HashMap#1908#CLS, List(TypeRef(ThisType(java.lang#128#PK), java.lang.String#129#CLS, List()), TypeRef(ThisType(java.lang#128#PK), java.lang.String#129#CLS, List()))) +[6] MethodType(List(), TypeRef(ThisType(scala.collection.mutable#1907#PK), scala.collection.mutable.HashMap#1908#CLS, List(TypeRef(ThisType(java.lang#128#PK), java.lang.String#129#CLS, List()), TypeRef(ThisType(java.lang#128#PK), java.lang.String#129#CLS, List())))) +[7] TypeRef(ThisType(scala.collection.mutable#1907#PK), scala.collection.mutable.HashMap#1908#CLS, List()) diff --git a/test/files/run/showraw_tree_ultimate.scala b/test/files/run/showraw_tree_ultimate.scala new file mode 100644 index 0000000000..dfd7abde52 --- /dev/null +++ b/test/files/run/showraw_tree_ultimate.scala @@ -0,0 +1,10 @@ +import scala.reflect.runtime.universe._ +import scala.tools.reflect.ToolBox + +object Test extends App { + val tb = runtimeMirror(getClass.getClassLoader).mkToolBox() + val tree1 = reify(new collection.immutable.HashMap[String, String]) + val tree2 = reify(new collection.mutable.HashMap[String, String]) + println(showRaw(tb.typeCheck(tree1.tree), printIds = true, printKinds = true, printTypes = true)) + println(showRaw(tb.typeCheck(tree2.tree), printIds = true, printKinds = true, printTypes = true)) +} \ No newline at end of file -- cgit v1.2.3