From bb817a67b99253662f42f788555a3617310a52a0 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Tue, 13 Oct 2009 17:49:36 +0000 Subject: Yet more code for scrutinizing the pattern matc... Yet more code for scrutinizing the pattern matcher, and a couple minor duplication/dead-code cleanups seen elsewhere. --- .../scala/tools/nsc/matching/MatchSupport.scala | 16 +++++--- .../scala/tools/nsc/matching/MatrixAdditions.scala | 34 ++++++++-------- .../tools/nsc/matching/ParallelMatching.scala | 1 - .../scala/tools/nsc/matching/Patterns.scala | 46 +++++++++++++++------- .../scala/tools/nsc/matching/TransMatcher.scala | 8 ++-- src/compiler/scala/tools/nsc/symtab/Types.scala | 13 +++--- .../scala/tools/nsc/transform/Erasure.scala | 3 -- 7 files changed, 70 insertions(+), 51 deletions(-) diff --git a/src/compiler/scala/tools/nsc/matching/MatchSupport.scala b/src/compiler/scala/tools/nsc/matching/MatchSupport.scala index 499523bc1a..927079bedc 100644 --- a/src/compiler/scala/tools/nsc/matching/MatchSupport.scala +++ b/src/compiler/scala/tools/nsc/matching/MatchSupport.scala @@ -111,6 +111,9 @@ trait MatchSupport extends ast.TreeDSL 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)) @@ -181,10 +184,7 @@ trait MatchSupport extends ast.TreeDSL override def printRaw(tree: Tree): Unit = { // routing supercalls through this for debugging ease - def s() = { - // Console.println("toSuper: " + tree.getClass) - super.printRaw(tree) - } + def s() = super.printRaw(tree) tree match { // labels used for jumps - does not map to valid scala code @@ -202,8 +202,6 @@ trait MatchSupport extends ast.TreeDSL 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) @@ -223,6 +221,12 @@ trait MatchSupport extends ast.TreeDSL case _ => s() } + // We get a lot of this stuff + case If( IsTrue(), x, _) => printRaw(x) + case If(IsFalse(), _, x) => printRaw(x) + case If(cond, IsFalse(), elsep) => + printRow(List(cond, elsep), " !(", ") && (", ") ") + // 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 (", "", ") ") diff --git a/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala b/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala index e542e1ab11..4a1a423b7f 100644 --- a/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala +++ b/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala @@ -20,6 +20,22 @@ trait MatrixAdditions extends ast.TreeDSL 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 + } + /** The Squeezer, responsible for all the squeezing. */ private[matching] trait Squeezer { @@ -28,10 +44,9 @@ trait MatrixAdditions extends ast.TreeDSL def squeezedBlockPVs(pvs: List[PatternVar], exp: Tree): Tree = squeezedBlock(pvs map (_.valDef), exp) - def squeezedBlock(vds: List[Tree], exp: Tree): Tree = tracing("squeezed", + def squeezedBlock(vds: List[Tree], exp: Tree): Tree = if (settings_squeeze) Block(Nil, squeezedBlock1(vds, exp)) else Block(vds, exp) - ) private def squeezedBlock1(vds: List[Tree], exp: Tree): Tree = { class RefTraverser(sym: Symbol) extends Traverser { @@ -96,21 +111,6 @@ trait MatrixAdditions extends ast.TreeDSL import self.context._ final def optimize(tree: Tree): Tree = { - // 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 - } object lxtt extends Transformer { override def transform(tree: Tree): Tree = tree match { case blck @ Block(vdefs, ld @ LabelDef(name, params, body)) => diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala index 7d5850ac27..02e6afdb4e 100644 --- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala +++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala @@ -27,7 +27,6 @@ trait ParallelMatching extends ast.TreeDSL import global.{ typer => _, _ } import definitions.{ AnyRefClass, IntClass, BooleanClass, getProductArgs, productProj } - import treeInfo.{ isStar } import CODE._ import Types._ import Debug._ diff --git a/src/compiler/scala/tools/nsc/matching/Patterns.scala b/src/compiler/scala/tools/nsc/matching/Patterns.scala index 54733e2eea..184054bc04 100644 --- a/src/compiler/scala/tools/nsc/matching/Patterns.scala +++ b/src/compiler/scala/tools/nsc/matching/Patterns.scala @@ -49,7 +49,7 @@ trait Patterns extends ast.TreeDSL { val tree = EmptyTree override def irrefutableFor(tpe: Type) = true override def isDefault = true - override def toString() = "_" + override def description = "_" } // 8.1.2 @@ -63,7 +63,7 @@ trait Patterns extends ast.TreeDSL { case ExtractorPattern(ua) if pv.sym.tpe <:< tpt.tpe => this rebindTo expr case _ => this } - override def toString() = "%s: %s".format(Pattern(expr), tpt) + override def description = "%s: %s".format(Pattern(expr), tpt) } // 8.1.3 @@ -72,7 +72,7 @@ trait Patterns extends ast.TreeDSL { def isSwitchable = cond(const.tag) { case ByteTag | ShortTag | IntTag | CharTag => true } def intValue = const.intValue - override def toString() = if (value == null) "null" else value.toString() + override def description = if (value == null) "null" else value.toString() } // 8.1.4 (a) @@ -82,7 +82,7 @@ trait Patterns extends ast.TreeDSL { override def sufficientType = Pattern(ident).equalsCheck override def simplify(pv: PatternVar) = this.rebindToObjectCheck() - override def toString() = "Id(%s)".format(name) + override def description = "Id(%s)".format(name) } // 8.1.4 (b) case class ApplySelectPattern(tree: Apply) extends ApplyPattern with SelectPattern { @@ -90,12 +90,12 @@ trait Patterns extends ast.TreeDSL { override def sufficientType = mkSingletonFromQualifier override def simplify(pv: PatternVar) = this.rebindToObjectCheck() - override def toString() = "SelectApply(%s)".format(name) + override def description = "SelectApply(%s)".format(name) } // 8.1.4 (c) case class StableIdPattern(tree: Select) extends SelectPattern { def select = tree - override def toString() = "StableId(%s)".format(pathSegments.mkString(" . ")) + override def description = "StableId(%s)".format(pathSegments.mkString(" . ")) } // 8.1.4 (d) case class ObjectPattern(tree: Apply) extends ApplyPattern { // NamePattern? @@ -103,7 +103,7 @@ trait Patterns extends ast.TreeDSL { override def sufficientType = tpe.narrow override def simplify(pv: PatternVar) = this.rebindToObjectCheck() - override def toString() = "Object(%s)".format(fn) + override def description = "Object(%s)".format(fn) } // 8.1.4 (e) case class SimpleIdPattern(tree: Ident) extends NamePattern { @@ -122,7 +122,7 @@ trait Patterns extends ast.TreeDSL { if (args.isEmpty) this rebindToEmpty tree.tpe else this - override def toString() = "Constructor(%s)".format(toPats(args).mkString(", ")) + override def description = "Constructor(%s)".format(toPats(args).mkString(", ")) // XXX todo // override def irrefutableFor(tpe: Type) = false @@ -147,7 +147,7 @@ trait Patterns extends ast.TreeDSL { if (pv.sym.tpe <:< arg.tpe) this else this rebindTo uaTyped - override def toString() = "Unapply(f: %s => %s)".format(necessaryType, fn.tpe.resultType) + override def description = "Unapply(f: %s => %s)".format(necessaryType, fn.tpe.resultType) } // 8.1.8 (unapplySeq calls) @@ -181,7 +181,7 @@ trait Patterns extends ast.TreeDSL { pv.sym setFlag Flags.TRANS_FLAG this rebindTo elems.foldRight(gen.mkNil)(listFolder) } - override def toString() = "UnapplySeq(%s)".format(elems) + override def description = "UnapplySeq(%s)".format(elems) } // 8.1.8 (b) (literal ArrayValues) @@ -193,7 +193,6 @@ trait Patterns extends ast.TreeDSL { override def subpatternsForVars: List[Pattern] = elemPatterns - def hasStar = elems.nonEmpty && (cond(lastPattern) { case _: StarPattern => true }) def nonStarLength = nonStarPatterns.length def isAllDefaults = nonStarPatterns forall (_.isDefault) @@ -244,7 +243,7 @@ trait Patterns extends ast.TreeDSL { false } } - override def toString() = "Sequence(%s)".format(elems) + override def description = "Sequence(%s)".format(elems) } // 8.1.8 (b) @@ -271,7 +270,7 @@ trait Patterns extends ast.TreeDSL { private lazy val Alternative(subtrees) = tree private def alts = subtrees map Pattern.apply // override def subpatterns(pmatch: PatternMatch) = subtrees map Pattern.apply - override def toString() = "Alts(%s)".format(alts mkString " | ") + override def description = "Alts(%s)".format(alts mkString " | ") } // 8.1.11 @@ -482,6 +481,24 @@ trait Patterns extends ast.TreeDSL { def isCaseClass = tpe.typeSymbol hasFlag Flags.CASE def isObject = isSymValid && prefix.isStable // XXX not entire logic + def unadorn(x: Tree): Tree = x match { + case Typed(expr, _) => unadorn(expr) + case Bind(_, x) => unadorn(x) + case _ => x + } + + private def isStar(x: Tree) = cond(unadorn(x)) { case Star(_) => true } + private def endsStar(xs: List[Tree]) = xs.nonEmpty && isStar(xs.last) + + def isSequence = cond(unadorn(tree)) { + case Sequence(xs) => true + case ArrayValue(tpt, xs) => true + } + def hasStar = cond(unadorn(tree)) { + case Sequence(xs) if endsStar(xs) => true + case ArrayValue(_, xs) if endsStar(xs) => true + } + def setType(tpe: Type): this.type = { tree setType tpe this @@ -503,9 +520,10 @@ trait Patterns extends ast.TreeDSL { case _ => super.equals(other) } override def hashCode() = boundTree.hashCode() + def description = super.toString() + final override def toString() = "%s %s".format(description, isSequence) } - /*** Extractors ***/ object UnapplyParamType { diff --git a/src/compiler/scala/tools/nsc/matching/TransMatcher.scala b/src/compiler/scala/tools/nsc/matching/TransMatcher.scala index 4244b13f6a..b47ebccfa9 100644 --- a/src/compiler/scala/tools/nsc/matching/TransMatcher.scala +++ b/src/compiler/scala/tools/nsc/matching/TransMatcher.scala @@ -58,7 +58,7 @@ trait TransMatcher extends ast.TreeDSL { // For x match { ... we start with a single root def singleMatch(): MatrixInit = { val v = copyVar(selector, isChecked) - tracing("root(s)", context.MatrixInit(List(v), cases, matchError(v.ident))) + context.MatrixInit(List(v), cases, matchError(v.ident)) } // For (x, y, z) match { ... we start with multiple roots, called tpXX. @@ -67,14 +67,14 @@ trait TransMatcher extends ast.TreeDSL { val vs = args zip rootTypes map { case (arg, tpe) => copyVar(arg, isChecked, tpe, "tp") } def merror = matchError(treeCopy.Apply(app, fn, vs map (_.ident))) - tracing("root(s)", context.MatrixInit(vs, cases, merror)) + context.MatrixInit(vs, cases, merror) } // sets up top level variables and algorithm input - val matrixInit = selector match { + val matrixInit = tracing("matrixInit", selector match { case app @ Apply(fn, _) if isTupleType(selector.tpe) && doApply(fn) => tupleMatch(app) case _ => singleMatch() - } + }) val matrix = new MatchMatrix(context) { lazy val data = matrixInit } val rep = matrix.expansion // expands casedefs and assigns name diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala index 1c6c04b2bc..1765536d8d 100644 --- a/src/compiler/scala/tools/nsc/symtab/Types.scala +++ b/src/compiler/scala/tools/nsc/symtab/Types.scala @@ -2706,10 +2706,13 @@ A type's typeSymbol should never be inspected directly. eparams } + // note: it's important to write the two tests in this order, + // as only typeParams forces the classfile to be read. See #400 + private def isRawIfWithoutArgs(sym: Symbol) = + !sym.typeParams.isEmpty && sym.hasFlag(JAVA) + def isRaw(sym: Symbol, args: List[Type]) = - !phase.erasedTypes && !sym.typeParams.isEmpty && sym.hasFlag(JAVA) && args.isEmpty - // note: it's important to write the two first tests in this order, - // as only typeParams forces the classfile to be read. See #400 + !phase.erasedTypes && isRawIfWithoutArgs(sym) && args.isEmpty /** Is type tp a ``raw type''? */ def isRawType(tp: Type) = tp match { @@ -2727,9 +2730,7 @@ A type's typeSymbol should never be inspected directly. */ object rawToExistential extends TypeMap { def apply(tp: Type): Type = tp match { - case TypeRef(pre, sym, List()) if !sym.typeParams.isEmpty && sym.hasFlag(JAVA) => - // note: it's important to write the two tests in this order, - // as only typeParams forces the classfile to be read. See #400 + case TypeRef(pre, sym, List()) if isRawIfWithoutArgs(sym) => val eparams = typeParamsToExistentials(sym, sym.typeParams) existentialAbstraction(eparams, TypeRef(pre, sym, eparams map (_.tpe))) case _ => diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index a5f764952f..43a743ea3b 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -384,9 +384,6 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer with ast. } } - private def isSeqClass(sym: Symbol) = - (SeqClass isNonBottomSubClass sym) && (sym != ObjectClass) - /** The symbol which is called by a bridge; * @pre phase > erasure */ -- cgit v1.2.3