From 8a45a5570ed0f091f3501fbfcc4c7dcb9f1c6a99 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Sun, 11 Oct 2009 00:32:19 +0000 Subject: Improving tracing output, and more code organiz... Improving tracing output, and more code organization to hide the uninteresting bits. --- .../scala/tools/nsc/matching/MatchSupport.scala | 113 ++++++++++++++++++++- src/compiler/scala/tools/nsc/matching/Matrix.scala | 11 +- .../tools/nsc/matching/ParallelMatching.scala | 40 ++++++-- .../scala/tools/nsc/matching/PatternBindings.scala | 4 +- .../scala/tools/nsc/matching/Patterns.scala | 38 +++---- .../scala/tools/nsc/matching/TransMatcher.scala | 104 ++----------------- .../scala/tools/nsc/transform/ExplicitOuter.scala | 26 ++--- 7 files changed, 185 insertions(+), 151 deletions(-) (limited to 'src/compiler') diff --git a/src/compiler/scala/tools/nsc/matching/MatchSupport.scala b/src/compiler/scala/tools/nsc/matching/MatchSupport.scala index 8ae98d30a4..a768f675d5 100644 --- a/src/compiler/scala/tools/nsc/matching/MatchSupport.scala +++ b/src/compiler/scala/tools/nsc/matching/MatchSupport.scala @@ -7,6 +7,8 @@ package scala.tools.nsc package matching import transform.ExplicitOuter +import ast.{ TreePrinters, Trees } +import java.io.{ StringWriter, PrintWriter } /** Ancillary bits of ParallelMatching which are better off * out of the way. @@ -73,10 +75,12 @@ trait MatchSupport extends ast.TreeDSL // pretty print for debugging def pp(x: Any): String = pp(x, false) def pp(x: Any, newlines: Boolean): String = { - def clean(s: String): String = s.replaceAll("""java\.lang\.""", "") + def clean(s: String): String = + s . replaceAll("""java\.lang\.""", "") + . replaceAll("""\$iw\.""", "") val elems: List[Any] = x match { - case x: String => return clean(x) + case x: String => return x case xs: List[_] => xs case x: Tuple2[_,_] => return pp(x._1) + " -> " + pp(x._2) case x => return pp(x.toString) @@ -88,7 +92,7 @@ trait MatchSupport extends ast.TreeDSL else xs2.mkString("(", ", ", ")") } - pplist(elems) + clean(pplist(elems)) } def ifDebug(body: => Unit): Unit = { if (settings.debug.value) body } @@ -139,5 +143,106 @@ trait MatchSupport extends ast.TreeDSL /** Drops the 'i'th element of a list. */ - def dropIndex[T](xs: List[T], n: Int) = (xs take n) ::: (xs drop (n + 1)) + def dropIndex[T](xs: List[T], n: Int) = { + val (l1, l2) = xs splitAt n + l1 ::: (l2 drop 1) + } + + /** Extract the nth element of a list and return it and the remainder. + */ + 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. + */ + + // lazy val compactTreePrinter = compactTreePrinters.create() + + 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) + } + + override def printRaw(tree: Tree): Unit = { + // routing supercalls through this for debugging ease + def s() = { + // Console.println("toSuper: " + tree.getClass) + 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() + } + + // case Select(Select(_, x), y) if x.toString == "this" => + // print(symName(tree, y)) + // 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() + } + + // 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/Matrix.scala b/src/compiler/scala/tools/nsc/matching/Matrix.scala index 631f517ab7..6d9f6a099b 100644 --- a/src/compiler/scala/tools/nsc/matching/Matrix.scala +++ b/src/compiler/scala/tools/nsc/matching/Matrix.scala @@ -99,6 +99,8 @@ trait Matrix extends MatrixAdditions { class PatternVar(val lhs: Symbol, val rhs: Tree) { lazy val ident = ID(lhs) lazy val valDef = typedValDef(lhs, rhs) + + override def toString() = "%s: %s = %s".format(lhs, lhs.info, rhs) } /** Given a tree, creates a new synthetic variable of the same type @@ -114,7 +116,7 @@ trait Matrix extends MatrixAdditions { val name = newName(root.pos, label) val sym = newVar(root.pos, tpe, flags(checked), name) - new PatternVar(sym, root) + tracing("copy", new PatternVar(sym, root)) } /** The rhs is expressed as a function of the lhs. */ @@ -122,7 +124,7 @@ trait Matrix extends MatrixAdditions { val lhs = newVar(owner.pos, tpe, flags(checked)) val rhs = f(lhs) - new PatternVar(lhs, rhs) + tracing("create", new PatternVar(lhs, rhs)) } private def newVar( @@ -133,10 +135,7 @@ trait Matrix extends MatrixAdditions { { val n: Name = if (name == null) newName(pos, "temp") else name // careful: pos has special meaning - val res = owner.newVariable(pos, n) setInfo tpe setFlag (0L /: flags)(_|_) - - traceCategory("newVar", "%s: %s", res, tpe) - res + owner.newVariable(pos, n) setInfo tpe setFlag (0L /: flags)(_|_) } def typedValDef(x: Symbol, rhs: Tree) = diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala index 54ad0354da..801bdd3d19 100644 --- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala +++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala @@ -34,7 +34,6 @@ trait ParallelMatching extends ast.TreeDSL import Flags.{ TRANS_FLAG } /** Transition **/ - def isRightIgnoring(t: Tree) = cond(unbind(t)) { case ArrayValue(_, xs) if !xs.isEmpty => isStar(xs.last) } def toPats(xs: List[Tree]): List[Pattern] = xs map Pattern.apply /** The umbrella matrix class. **/ @@ -72,6 +71,19 @@ trait ParallelMatching extends ast.TreeDSL else target.getLabelBody(idents, patternValDefs) } + // make(tvars, rows) + // make(scrut.sym :: rest.tvars, xs).toTree + // make(rest.tvars, newRows ::: defaultRows) + // make(r.tvars, r.rows map (x => x rebind bindVars(tag, x.subst))) + // make(rest.tvars, defaultRows).toTree + // make(ntemps ::: scrut.sym :: rest.tvars, rows).toTree + // make(List(vs map (_.lhs), symList, rest.tvars).flatten, nrows.flatten) + // make(scrut.sym :: rest.tvars, frows.flatten).toTree + // make(scrut.sym :: rest.tvars, rows).toTree + // make(subtestVars ::: casted.accessorVars ::: rest.tvars, newRows) + // make(tvars, rows.tail) + // make(_tvars, _rows) + /** the injection here handles alternatives and unapply type tests */ final def make(tvars: List[Symbol], row1: List[Row]): Rep = { def classifyPat(opat: Pattern, j: Int): Pattern = opat simplify tvars(j) @@ -450,7 +462,7 @@ trait ParallelMatching extends ast.TreeDSL case (false, false) => toPats(xs) ::: List(NoPattern) }) } - else if (pivot.hasStar && isRightIgnoring(av) && xs.length-1 < pivotLen) + else if (pivot.hasStar && sp.hasStar && xs.length-1 < pivotLen) Some(emptyPatterns(pivotLen + 1) ::: List(x)) else defaults // XXX @@ -574,7 +586,7 @@ trait ParallelMatching extends ast.TreeDSL (pattern match { case Pattern(LIT(null), _) if !(p =:= s) => (None, None, pass) // (1) case x if isObjectTest => (NoPattern, dummy, None) // (2) - case Pattern(Typed(pp @ Pattern(_: UnApply, _), _), _) if sMatchesP => (Pattern(pp), dummy, None) // (3) + // case Pattern(Typed(pp @ Pattern(_: UnApply, _), _), _) if sMatchesP => (Pattern(pp), dummy, None) // (3) case Pattern(Typed(pp, _), _) if sMatchesP => (alts(Pattern(pp), pattern), dummy, None) // (4) case Pattern(_: UnApply, _) => (NoPattern, dummy, pass) case x if !x.isDefault && sMatchesP => (alts(NoPattern, pattern), subs, None) @@ -649,6 +661,12 @@ trait ParallelMatching extends ast.TreeDSL /** Drops the 'i'th pattern */ def drop(i: Int) = copy(pats = dropIndex(pats, i)) + /** Extracts the nth pattern. */ + def extractColumn(i: Int) = { + val (x, xs) = extractIndex(pats, i) + (x, copy(pats = xs)) + } + /** Replaces the 'i'th pattern with the argument. */ def replaceAt(i: Int, p: Pattern) = { val newps = (pats take i) ::: p :: (pats drop (i + 1)) @@ -773,16 +791,18 @@ trait ParallelMatching extends ast.TreeDSL /** Cut out the column containing the non-default pattern. */ class Cut(index: Int) { /** The first two separate out the 'i'th pattern in each row from the remainder. */ - private val _column = rows map (_ pats index) - private val _rows = rows map (_ drop index) + private val (_column, _rows) = + List.unzip(rows map (_ extractColumn index)) /** Now the 'i'th tvar is separated out and used as a new Scrutinee. */ - private val _sym = tvars(index) - private val _tvars = dropIndex(tvars, index) - private val _scrut = new Scrutinee(_sym) + private val (_sym, _tvars) = + extractIndex(tvars, index) + + /** The non-default pattern (others.head) replaces the column head. */ + private val (_ncol, _nrep) = + (others.head :: _column.tail, make(_tvars, _rows)) - /** The first non-default pattern (others.head) takes the place of _column's head. */ - def mix = MixtureRule(_scrut, others.head :: _column.tail, make(_tvars, _rows)) + def mix = MixtureRule(new Scrutinee(_sym), _ncol, _nrep) } /** Converts this to a tree - recursively acquires subreps. */ diff --git a/src/compiler/scala/tools/nsc/matching/PatternBindings.scala b/src/compiler/scala/tools/nsc/matching/PatternBindings.scala index de622b91a2..6c44cde880 100644 --- a/src/compiler/scala/tools/nsc/matching/PatternBindings.scala +++ b/src/compiler/scala/tools/nsc/matching/PatternBindings.scala @@ -134,7 +134,9 @@ trait PatternBindings extends ast.TreeDSL } class Bindings(private val vlist: List[Binding]) extends Function1[Symbol, Option[Ident]] { - traceCategory("Bindings", this.toString) + if (!vlist.isEmpty) + traceCategory("Bindings", this.toString) + def vmap(v: Symbol): Option[Binding] = vlist find (_.pvar eq v) // filters the given list down to those defined in these bindings diff --git a/src/compiler/scala/tools/nsc/matching/Patterns.scala b/src/compiler/scala/tools/nsc/matching/Patterns.scala index 647d6c92d8..75b13c2d32 100644 --- a/src/compiler/scala/tools/nsc/matching/Patterns.scala +++ b/src/compiler/scala/tools/nsc/matching/Patterns.scala @@ -187,17 +187,17 @@ trait Patterns extends ast.TreeDSL { lazy val ArrayValue(elemtpt, elems) = tree lazy val elemPatterns = toPats(elems) lazy val nonStarPatterns = if (hasStar) elemPatterns.init else elemPatterns - private def starPattern = elemPatterns.last + private def lastPattern = elemPatterns.last override def subpatternsForVars: List[Pattern] = elemPatterns - def hasStar = isRightIgnoring(tree) + def hasStar = elems.nonEmpty && (cond(lastPattern) { case _: StarPattern => true }) def nonStarLength = nonStarPatterns.length def isAllDefaults = nonStarPatterns forall (_.isDefault) def rebindStar(seqType: Type): List[Pattern] = { require(hasStar) - nonStarPatterns ::: List(starPattern rebindTo WILD(seqType)) + nonStarPatterns ::: List(lastPattern rebindTo WILD(seqType)) } // optimization to avoid trying to match if length makes it impossible @@ -503,20 +503,20 @@ trait Patterns extends ast.TreeDSL { } } - object SeqStarSubPatterns { - def removeStar(xs: List[Tree], seqType: Type): List[Pattern] = { - val ps = toPats(xs) - ps.init ::: List(ps.last rebindToType seqType) - } - - def unapply(x: Pattern)(implicit min: Int, seqType: Type): Option[List[Pattern]] = x.tree match { - case av @ ArrayValue(_, xs) => - if (!isRightIgnoring(av) && xs.length == min) Some(toPats(xs ::: List(gen.mkNil, EmptyTree))) // Seq(p1,...,pN) - else if ( isRightIgnoring(av) && xs.length-1 == min) Some(removeStar(xs, seqType) ::: List(NoPattern)) // Seq(p1,...,pN,_*) - else if ( isRightIgnoring(av) && xs.length-1 < min) Some(emptyPatterns(min + 1) ::: List(x)) // Seq(p1..,pJ,_*) J < N - else None - case _ => - if (x.isDefault) Some(emptyPatterns(min + 1 + 1)) else None - } - } + // object SeqStarSubPatterns { + // def removeStar(xs: List[Tree], seqType: Type): List[Pattern] = { + // val ps = toPats(xs) + // ps.init ::: List(ps.last rebindToType seqType) + // } + // + // def unapply(x: Pattern)(implicit min: Int, seqType: Type): Option[List[Pattern]] = x.tree match { + // case av @ ArrayValue(_, xs) => + // if (!isRightIgnoring(av) && xs.length == min) Some(toPats(xs ::: List(gen.mkNil, EmptyTree))) // Seq(p1,...,pN) + // else if ( isRightIgnoring(av) && xs.length-1 == min) Some(removeStar(xs, seqType) ::: List(NoPattern)) // Seq(p1,...,pN,_*) + // else if ( isRightIgnoring(av) && xs.length-1 < min) Some(emptyPatterns(min + 1) ::: List(x)) // Seq(p1..,pJ,_*) J < N + // else None + // case _ => + // if (x.isDefault) Some(emptyPatterns(min + 1 + 1)) else None + // } + // } } \ No newline at end of file diff --git a/src/compiler/scala/tools/nsc/matching/TransMatcher.scala b/src/compiler/scala/tools/nsc/matching/TransMatcher.scala index b73acb8004..2fb162a059 100644 --- a/src/compiler/scala/tools/nsc/matching/TransMatcher.scala +++ b/src/compiler/scala/tools/nsc/matching/TransMatcher.scala @@ -18,13 +18,14 @@ import scala.util.NameTransformer.decode * * @author Burak Emir */ -trait TransMatcher extends ast.TreeDSL with CompactTreePrinter { +trait TransMatcher extends ast.TreeDSL { self: ExplicitOuter with ParallelMatching => import global.{ typer => _, _ } import analyzer.Typer import definitions._ import CODE._ + import Debug.tracing // cunit is set to the current unit in ExplicitOuter's transformUnit, // and nulled out afterward to avoid leaking. @@ -58,7 +59,7 @@ trait TransMatcher extends ast.TreeDSL with CompactTreePrinter { def singleMatch(): (List[Tree], MatrixInit) = { val v = copyVar(selector, isChecked) - (List(v.valDef), MatrixInit(List(v.lhs), cases, matchError(v.ident))) + (tracing("root(s)", List(v.valDef)), MatrixInit(List(v.lhs), cases, matchError(v.ident))) } // For (x, y, z) match { ... we start with multiple roots, called tpXX. @@ -67,7 +68,7 @@ trait TransMatcher extends ast.TreeDSL with CompactTreePrinter { val vs = args zip rootTypes map { case (arg, tpe) => copyVar(arg, isChecked, tpe, "tp") } def merror = matchError(treeCopy.Apply(app, fn, vs map (_.ident))) - (vs map (_.valDef), MatrixInit(vs map (_.lhs), cases, merror)) + (tracing("root(s)", vs map (_.valDef)), MatrixInit(vs map (_.lhs), cases, merror)) } // sets up top level variables and algorithm input @@ -87,6 +88,8 @@ trait TransMatcher extends ast.TreeDSL with CompactTreePrinter { matrix optimize dfatree } + object compactTreePrinters extends CompactTreePrinter + private def toCompactString(t: Tree): String = { val buffer = new StringWriter() val printer = compactTreePrinters.create(new PrintWriter(buffer)) @@ -96,98 +99,3 @@ trait TransMatcher extends ast.TreeDSL with CompactTreePrinter { } } -/** A tree printer which is stingier about vertical whitespace and unnecessary - * punctuation than the standard one. - */ -trait CompactTreePrinter { - val global: Global - - object compactTreePrinters 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) - } - - override def printRaw(tree: Tree): Unit = { - // routing supercalls through this for debugging ease - def s() = { - // Console.println("toSuper: " + tree.getClass) - 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() - } - - // case Select(Select(_, x), y) if x.toString == "this" => - // print(symName(tree, y)) - // 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() - } - - // 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() - } - } - } - } - - lazy val compactTreePrinter = compactTreePrinters.create() -} diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala index 0118c0f9cc..9aeebb2360 100644 --- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala +++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala @@ -460,19 +460,19 @@ abstract class ExplicitOuter extends InfoTransform sym setFlag notPROTECTED super.transform(tree) - case Apply(sel @ Select(qual, name), args) - if (name == nme.CONSTRUCTOR && isInner(sel.symbol.owner)) => - val outerVal = atPos(tree.pos) { - if (qual.isInstanceOf[This]) { // it's a call between constructors of same class - assert(outerParam != NoSymbol) - outerValue - } else { - var pre = qual.tpe.prefix - if (pre == NoPrefix) pre = sym.owner.outerClass.thisType - gen.mkAttributedQualifier(pre) - } - } - super.transform(treeCopy.Apply(tree, sel, outerVal :: args)) + case Apply(sel @ Select(qual, name), args) if (name == nme.CONSTRUCTOR && isInner(sel.symbol.owner)) => + val outerVal = atPos(tree.pos)(qual match { + // it's a call between constructors of same class + case _: This => + assert(outerParam != NoSymbol) + outerValue + case _ => + gen.mkAttributedQualifier(qual.tpe.prefix match { + case NoPrefix => sym.owner.outerClass.thisType + case x => x + }) + }) + super.transform(treeCopy.Apply(tree, sel, outerVal :: args)) // TransMatch hook case mch: Match => -- cgit v1.2.3