summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/Interpreter.scala5
-rw-r--r--src/compiler/scala/tools/nsc/InterpreterLoop.scala17
-rw-r--r--src/compiler/scala/tools/nsc/Settings.scala1
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeInfo.scala17
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreePrinters.scala307
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala17
-rw-r--r--src/compiler/scala/tools/nsc/matching/MatchSupport.scala132
-rw-r--r--src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala17
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Names.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala1
-rw-r--r--test/files/run/treePrint.check5
-rw-r--r--test/files/run/treePrint.scala40
12 files changed, 353 insertions, 208 deletions
diff --git a/src/compiler/scala/tools/nsc/Interpreter.scala b/src/compiler/scala/tools/nsc/Interpreter.scala
index 6ef1c19eac..e413911eb0 100644
--- a/src/compiler/scala/tools/nsc/Interpreter.scala
+++ b/src/compiler/scala/tools/nsc/Interpreter.scala
@@ -80,7 +80,10 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
/** have to be careful completion doesn't start querying global before it's ready */
private var _initialized = false
def isInitialized = _initialized
- private[nsc] def setInitialized = {
+ def initialize() = {
+ // forces something to be compiled
+ isettings
+
_initialized = true
}
diff --git a/src/compiler/scala/tools/nsc/InterpreterLoop.scala b/src/compiler/scala/tools/nsc/InterpreterLoop.scala
index 7a4668abcf..ab643def53 100644
--- a/src/compiler/scala/tools/nsc/InterpreterLoop.scala
+++ b/src/compiler/scala/tools/nsc/InterpreterLoop.scala
@@ -222,19 +222,6 @@ class InterpreterLoop(in0: Option[BufferedReader], out: PrintWriter) {
/** Available commands */
def commands: List[Command] = standardCommands ::: (if (powerUserOn) powerCommands else Nil)
- /* For some reason, the first interpreted command always takes
- * a second or two. So, wait until the welcome message
- * has been printed before calling isettings. That way,
- * the user can read the welcome message while this
- * command executes.
- */
- private def initInterpreter() {
- // forces something to be compiled
- interpreter.isettings
- // signals completion it's okay to proceed
- interpreter.setInitialized
- }
-
/** The main read-eval-print loop for the interpreter. It calls
* <code>command()</code> for each line of input, and stops when
* <code>command()</code> returns <code>false</code>.
@@ -255,12 +242,12 @@ class InterpreterLoop(in0: Option[BufferedReader], out: PrintWriter) {
/* For some reason, the first interpreted command always takes
* a second or two. So, wait until the welcome message
- * has been printed before calling initInterpreter. That way,
+ * has been printed before calling initialize. That way,
* the user can read the welcome message while this
* command executes.
*/
val futLine = scala.concurrent.ops.future(readOneLine)
- initInterpreter()
+ interpreter.initialize()
if (!processLine(futLine()))
return
diff --git a/src/compiler/scala/tools/nsc/Settings.scala b/src/compiler/scala/tools/nsc/Settings.scala
index 05e12760a2..f15017f933 100644
--- a/src/compiler/scala/tools/nsc/Settings.scala
+++ b/src/compiler/scala/tools/nsc/Settings.scala
@@ -892,6 +892,7 @@ trait ScalacSettings {
val check = PhasesSetting ("-Ycheck", "Check the tree at the end of")
val Xcloselim = BooleanSetting ("-Yclosure-elim", "Perform closure elimination")
val Xcodebase = StringSetting ("-Ycodebase", "codebase", "Specify the URL containing the Scala libraries", "")
+ val Ycompacttrees = BooleanSetting ("-Ycompact-trees", "Use compact tree printer when displaying trees")
val noCompletion = BooleanSetting ("-Yno-completion", "Disable tab-completion in the REPL")
val Xdce = BooleanSetting ("-Ydead-code", "Perform dead code elimination")
val debug = BooleanSetting ("-Ydebug", "Output debugging messages")
diff --git a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
index fd7227c371..aa0e484578 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
@@ -350,4 +350,21 @@ abstract class TreeInfo {
case TypeDef(_, _, _, _) => !isAbsTypeDef(tree)
case _ => false
}
+
+ /** Some handy extractors for spotting true and false expressions
+ * through the haze of braces.
+ */
+ abstract class SeeThroughBlocks[T] {
+ protected def unapplyImpl(x: Tree): T
+ def unapply(x: Tree): T = x match {
+ case Block(Nil, expr) => unapply(expr)
+ case _ => unapplyImpl(x)
+ }
+ }
+ object IsTrue extends SeeThroughBlocks[Boolean] {
+ protected def unapplyImpl(x: Tree): Boolean = x equalsStructure Literal(Constant(true))
+ }
+ object IsFalse extends SeeThroughBlocks[Boolean] {
+ protected def unapplyImpl(x: Tree): Boolean = x equalsStructure Literal(Constant(false))
+ }
}
diff --git a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
index 4ba5f17a40..c0b2fb41be 100644
--- a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
@@ -8,14 +8,14 @@ package scala.tools.nsc
package ast
import compat.Platform.{EOL => LINE_SEPARATOR}
-import java.io.{OutputStream, PrintWriter, Writer}
+import java.io.{ OutputStream, PrintWriter, StringWriter, Writer }
import symtab.Flags._
import symtab.SymbolTable
abstract class TreePrinters {
-
val trees: SymbolTable
import trees._
+ import treeInfo.{ IsTrue, IsFalse }
final val showOuterTests = false
@@ -29,6 +29,9 @@ abstract class TreePrinters {
def indent = indentMargin += indentStep
def undent = indentMargin -= indentStep
+ protected def doPrintPositions = settings.Xprintpos.value
+ def printPosition(tree: Tree) = if (doPrintPositions) print(tree.pos.show)
+
def println {
out.println()
while (indentMargin > indentString.length())
@@ -75,11 +78,11 @@ abstract class TreePrinters {
def printParam(tree: Tree) {
tree match {
case ValDef(mods, name, tp, rhs) =>
- if (settings.Xprintpos.value) print(tree.pos.show)
+ printPosition(tree)
printAnnotations(tree)
print(symName(tree, name)); printOpt(": ", tp); printOpt(" = ", rhs)
case TypeDef(mods, name, tparams, rhs) =>
- if (settings.Xprintpos.value) print(tree.pos.show)
+ printPosition(tree)
print(symName(tree, name))
printTypeParams(tparams); print(rhs)
}
@@ -93,46 +96,49 @@ abstract class TreePrinters {
printColumn(List(tree), "{", ";", "}")
}
}
- def symName(tree: Tree, name: Name): String =
- if (tree.symbol != null && tree.symbol != NoSymbol) {
- ((if (tree.symbol.isMixinConstructor) "/*"+tree.symbol.owner.name+"*/" else "") +
- tree.symbol.nameString)
- } else name.toString();
+
+ private def symNameInternal(tree: Tree, name: Name, decoded: Boolean): String = {
+ val nameToString: Name => String = if (decoded) _.decode else _.toString
+
+ tree.symbol match {
+ case null | NoSymbol => nameToString(name)
+ case sym =>
+ val prefix = if (sym.isMixinConstructor) "/*%s*/".format(nameToString(sym.owner.name)) else ""
+ prefix + tree.symbol.nameString
+ }
+ }
+
+ def decodedSymName(tree: Tree, name: Name) = symNameInternal(tree, name, true)
+ def symName(tree: Tree, name: Name) = symNameInternal(tree, name, false)
def printOpt(prefix: String, tree: Tree) {
if (!tree.isEmpty) { print(prefix); print(tree) }
}
def printModifiers(tree: Tree, mods: Modifiers) {
- if (tree.symbol == NoSymbol)
- printFlags(mods.flags, mods.privateWithin.toString)
- else if (tree.symbol.privateWithin == NoSymbol ||
- tree.symbol.privateWithin == tree.symbol.owner)
- printFlags(tree.symbol.flags, "")
- else
- printFlags(tree.symbol.flags, tree.symbol.privateWithin.name.toString)
+ def pw = tree.symbol.privateWithin
+ val args =
+ if (tree.symbol == NoSymbol) (mods.flags, mods.privateWithin)
+ else if (pw == NoSymbol || pw == tree.symbol.owner) (tree.symbol.flags, "")
+ else (tree.symbol.flags, pw.name)
+
+ printFlags(args._1, args._2.toString)
}
def printFlags(flags: Long, privateWithin: String) {
var mask: Long = if (settings.debug.value) -1L else PrintableFlags
val s = flagsToString(flags & mask, privateWithin)
- if (s.length() != 0) print(s + " ")
+ if (s != "") print(s + " ")
}
def printAnnotations(tree: Tree) {
- if (!tree.symbol.rawAnnotations.isEmpty) {
- val annots = tree.symbol.annotations
- if (!annots.isEmpty) {
- annots foreach { annot => print("@"+annot+" ") }
- println
- }
- } else {
- val annots = tree.asInstanceOf[MemberDef].mods.annotations
- if (!annots.isEmpty) {
- annots foreach { annot => print("@"+annot+" ") }
- println
- }
- }
+ val annots =
+ if (tree.symbol.rawAnnotations.nonEmpty) tree.symbol.annotations
+ else tree.asInstanceOf[MemberDef].mods.annotations
+
+ annots foreach (annot => print("@"+annot+" "))
+ if (annots.nonEmpty)
+ println
}
def print(str: String) { out.print(str) }
@@ -165,7 +171,7 @@ abstract class TreePrinters {
case ValDef(mods, name, tp, rhs) =>
printAnnotations(tree)
printModifiers(tree, mods)
- print(if (mods.hasFlag(MUTABLE)) "var " else "val ")
+ print(if (mods.isVariable) "var " else "val ")
print(symName(tree, name))
printOpt(": ", tp)
if (!mods.hasFlag(DEFERRED)) {
@@ -389,7 +395,7 @@ abstract class TreePrinters {
}
def print(tree: Tree) {
- if (settings.Xprintpos.value) print(tree.pos.show)
+ printPosition(tree)
printRaw(
if (tree.isDef && tree.symbol != NoSymbol && tree.symbol.isInitialized) {
tree match {
@@ -417,11 +423,242 @@ abstract class TreePrinters {
}
}
+
+ /** 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))
+ printRaw(t1._1)
+ print(") %s %s(".format(op, maybenot(t2._2)))
+ printRaw(t2._1)
+ print(")")
+ }
+
+ override def printRaw(tree: Tree): Unit = {
+ // routing supercalls through this for debugging ease
+ def s() = super.printRaw(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)
+
+ 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) =>
+ printRaw(target)
+ print(" ")
+ printRaw(Ident(method))
+ print(" ")
+ printRaw(arg)
+ case _ => s()
+ }
+
+ // target.unary_! ==> !target
+ case Select(qualifier, name) if (name.decode startsWith "unary_") =>
+ print(name.decode drop 6)
+ printRaw(qualifier)
+
+ case Select(qualifier, name) =>
+ printRaw(qualifier)
+ print(".")
+ print(name.decode)
+
+ // target.toString() ==> target.toString
+ case Apply(fn, Nil) => printRaw(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 xs => s()
+ }
+
+ // We get a lot of this stuff
+ case If( IsTrue(), x, _) => printRaw(x)
+ case If(IsFalse(), _, x) => printRaw(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 ; printRaw(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) => printRaw(x)
+ case _ => printRaw(thenp)
+ }
+
+ if (elseStmts.nonEmpty) {
+ print("else")
+ indent ; println
+ elseStmts match {
+ case List(x) => printRaw(x)
+ case _ => printRaw(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) {
+ 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 ", "
+
+ 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 printRaw(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) =>
+
+ // 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
+ }
+ }
+
+ 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, create)
+ def asCompactString(t: Tree): String = asStringInternal(t, createCompact)
+
def create(writer: PrintWriter): TreePrinter = new TreePrinter(writer)
def create(stream: OutputStream): TreePrinter = create(new PrintWriter(stream))
- def create(): TreePrinter = {
- create(new PrintWriter(ConsoleWriter))
- }
+ def create(): TreePrinter = create(new PrintWriter(ConsoleWriter))
+
+ def createCompact(writer: PrintWriter): CompactTreePrinter = new CompactTreePrinter(writer)
+ def createCompact(stream: OutputStream): CompactTreePrinter = createCompact(new PrintWriter(stream))
+ def createCompact(): CompactTreePrinter = createCompact(new PrintWriter(ConsoleWriter))
+
/** A writer that writes to the current Console and
* is sensitive to replacement of the Console's
* output stream.
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala
index 0d94048f67..21f2919535 100644
--- a/src/compiler/scala/tools/nsc/ast/Trees.scala
+++ b/src/compiler/scala/tools/nsc/ast/Trees.scala
@@ -36,7 +36,9 @@ trait Trees {
val trees: Trees.this.type = Trees.this
} with TreePrinters
- lazy val treePrinter = treePrinters.create()
+ lazy val treePrinter =
+ if (settings.Ycompacttrees.value) treePrinters.createCompact()
+ else treePrinters.create()
object treeInfo extends {
val trees: Trees.this.type = Trees.this
@@ -197,13 +199,9 @@ trait Trees {
productIterator.toList flatMap subtrees
}
- override def toString(): String = {
- val buffer = new StringWriter()
- val printer = treePrinters.create(new PrintWriter(buffer))
- printer.print(this)
- printer.flush()
- buffer.toString
- }
+ override def toString(): String =
+ if (settings.Ycompacttrees.value) treePrinters.asCompactString(this)
+ else treePrinters.asString(this)
override def hashCode(): Int = super.hashCode()
@@ -834,9 +832,10 @@ trait Trees {
/** Self reference */
case class This(qual: Name)
- extends TermTree with SymTree
+ extends TermTree with SymTree {
// The symbol of a This is the class to which the this refers.
// For instance in C.this, it would be C.
+ }
def This(sym: Symbol): Tree = This(sym.name) setSymbol sym
diff --git a/src/compiler/scala/tools/nsc/matching/MatchSupport.scala b/src/compiler/scala/tools/nsc/matching/MatchSupport.scala
index 1722500066..e51919b7c2 100644
--- a/src/compiler/scala/tools/nsc/matching/MatchSupport.scala
+++ b/src/compiler/scala/tools/nsc/matching/MatchSupport.scala
@@ -102,26 +102,13 @@ trait MatchSupport extends ast.TreeDSL
pp(x match {
case s: String => return clean(s)
- case x: Tree => treeToCompactString(x)
+ case x: Tree => treePrinters asCompactString x
case xs: List[_] => pplist(xs map pp)
case x: Tuple2[_,_] => "%s -> %s".format(pp(x._1), pp(x._2))
case x => x.toString
})
}
- object compactTreePrinter extends CompactTreePrinter
-
- // def treeChildrenString(t: Tree): String =
- // nodeToString(t)
-
- def treeToCompactString(t: Tree): String = {
- val buffer = new StringWriter()
- val printer = compactTreePrinter.create(new PrintWriter(buffer))
- printer.print(t)
- printer.flush()
- buffer.toString
- }
-
def ifDebug(body: => Unit): Unit = { if (settings.debug.value) body }
def DBG(msg: => String): Unit = { ifDebug(println(msg)) }
@@ -166,121 +153,4 @@ trait MatchSupport extends ast.TreeDSL
*/
def extractIndex[T](xs: List[T], n: Int): (T, List[T]) =
(xs(n), dropIndex(xs, n))
-
- /** A tree printer which is stingier about vertical whitespace and unnecessary
- * punctuation than the standard one.
- */
- class CompactTreePrinter extends {
- val trees: global.type = global
- } with TreePrinters {
- import trees._
-
- override def create(writer: PrintWriter): TreePrinter = new TreePrinter(writer) {
- // 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 "!"
-
- printRow(List(t1._1, t2._1),
- " %s(" format maybenot(t1._2),
- ") %s %s(".format(op, maybenot(t2._2)),
- ")"
- )
- }
-
- override def printRaw(tree: Tree): Unit = {
- // routing supercalls through this for debugging ease
- def s() = super.printRaw(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)
-
- // target.method(arg) ==> target method arg
- case Apply(Select(target, method), List(arg)) =>
- (target, arg) match {
- case (_: Ident, _: Literal | _: Ident) =>
- printRaw(target)
- print(" %s " format symName(tree, method))
- printRaw(arg)
- case _ => s()
- }
-
- // target.unary_! ==> !target
- case Select(qualifier, name) =>
- val n = symName(tree, name)
- if (n startsWith "unary_") {
- print(n drop 6)
- print(qualifier)
- }
- else s()
-
- // target.toString() ==> target.toString
- case Apply(fn, Nil) => printRaw(fn)
-
- // if a Block only continues one actual statement, just print it.
- case Block(stats, expr) =>
- allStatements(tree) match {
- case List(x) => printRow(List(x), "", ";", "")
- case _ => s()
- }
-
- // We get a lot of this stuff
- case If( IsTrue(), x, _) => printRaw(x)
- case If(IsFalse(), _, x) => printRaw(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) =>
- printRow(List(cond), "if (", "", ") ")
-
- def ifIndented(x: Tree) = {
- indent ; println ; printRaw(x) ; undent
- }
-
- indent ; println ;
- allStatements(thenp) match {
- case List(x: If) => ifIndented(x)
- case List(x) => printRaw(x)
- case _ => printRaw(thenp)
- }
- undent ; println ;
- val elseStmts = allStatements(elsep)
- if (!elseStmts.isEmpty) {
- print("else")
- indent ; println
- elseStmts match {
- case List(x) => printRaw(x)
- case xs => printRaw(elsep)
- }
- undent ; println
- }
- case _ => s()
- }
- }
- }
- }
}
diff --git a/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala b/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala
index 4f13d4fd99..fd55945d50 100644
--- a/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala
+++ b/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala
@@ -20,22 +20,7 @@ trait MatrixAdditions extends ast.TreeDSL
import symtab.Flags
import CODE._
import Debug._
-
- // Extractors which can spot pure true/false expressions
- // even through the haze of braces
- abstract class SeeThroughBlocks[T] {
- protected def unapplyImpl(x: Tree): T
- def unapply(x: Tree): T = x match {
- case Block(Nil, expr) => unapply(expr)
- case _ => unapplyImpl(x)
- }
- }
- object IsTrue extends SeeThroughBlocks[Boolean] {
- protected def unapplyImpl(x: Tree): Boolean = x equalsStructure TRUE
- }
- object IsFalse extends SeeThroughBlocks[Boolean] {
- protected def unapplyImpl(x: Tree): Boolean = x equalsStructure FALSE
- }
+ import treeInfo.{ IsTrue, IsFalse }
/** The Squeezer, responsible for all the squeezing.
*/
diff --git a/src/compiler/scala/tools/nsc/symtab/Names.scala b/src/compiler/scala/tools/nsc/symtab/Names.scala
index 5f5a220b8a..ddadc32202 100644
--- a/src/compiler/scala/tools/nsc/symtab/Names.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Names.scala
@@ -390,6 +390,8 @@ class Names {
def decode: String = (
NameTransformer.decode(toString()) +
(if (nameDebug && isTypeName) "!" else ""))//debug
+
+ def isOperatorName: Boolean = decode != toString
}
private class TermName(index: Int, len: Int, hash: Int) extends Name(index, len) {
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index f50dee615b..d6f4ef5672 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -1745,7 +1745,6 @@ trait Symbols {
/** A class for module symbols */
class ModuleSymbol(initOwner: Symbol, initPos: Position, initName: Name)
extends TermSymbol(initOwner, initPos, initName) {
-
private var flatname = nme.EMPTY
override def owner: Symbol =
diff --git a/test/files/run/treePrint.check b/test/files/run/treePrint.check
new file mode 100644
index 0000000000..3360815ac1
--- /dev/null
+++ b/test/files/run/treePrint.check
@@ -0,0 +1,5 @@
+def foo = {
+ var q: Boolean = false;
+ val x = 5;
+ ((x == 5) || (!q)) || (true)
+}
diff --git a/test/files/run/treePrint.scala b/test/files/run/treePrint.scala
new file mode 100644
index 0000000000..ffe9a392d4
--- /dev/null
+++ b/test/files/run/treePrint.scala
@@ -0,0 +1,40 @@
+/** Testing compact tree printers.
+ */
+object Test {
+ import scala.tools.nsc._
+ import java.io.{ OutputStream, BufferedReader, StringReader, PrintWriter, Writer, OutputStreamWriter}
+
+ val code = """
+ def foo = {
+ var q: Boolean = false
+ val x = if (true) {
+ if (true) {
+ if (true) {
+ 5
+ }
+ else if (true) {
+ 5
+ } else {
+ 10
+ }
+ }
+ else 20
+ }
+ else 30
+
+ (x == 5) || !q || true
+ }
+ """
+
+ class NullOutputStream extends OutputStream { def write(b: Int) { } }
+
+ def main(args: Array[String]) {
+ val settings = new Settings
+ settings.classpath.value = System.getProperty("java.class.path")
+ settings.Ycompacttrees.value = true
+
+ val repl = new Interpreter(settings, new PrintWriter(new NullOutputStream))
+ repl.interpret("""def initialize = "Have to interpret something or we get errors." """)
+ println(repl mkTree code)
+ }
+}