From e3d9ce3e0923077911fbc26df0cac3a9137be966 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Tue, 6 Oct 2009 17:04:40 +0000 Subject: Debugging code - pattern matcher activity tracing. --- src/compiler/scala/tools/nsc/matching/Matrix.scala | 5 +- .../tools/nsc/matching/ParallelMatching.scala | 59 +++++++++---------- .../scala/tools/nsc/matching/Patterns.scala | 67 ++++++++++++++++------ 3 files changed, 79 insertions(+), 52 deletions(-) diff --git a/src/compiler/scala/tools/nsc/matching/Matrix.scala b/src/compiler/scala/tools/nsc/matching/Matrix.scala index edd6d60fab..527c01b1a8 100644 --- a/src/compiler/scala/tools/nsc/matching/Matrix.scala +++ b/src/compiler/scala/tools/nsc/matching/Matrix.scala @@ -95,7 +95,7 @@ trait Matrix extends PatternOptimizer { { val n: Name = if (name == null) newName(pos, "temp") else name // careful: pos has special meaning - owner.newVariable(pos, n) setInfo tpe setFlag (0L /: flags)(_|_) + traceAndReturn("[newVar] ", owner.newVariable(pos, n) setInfo tpe setFlag (0L /: flags)(_|_)) } def typedValDef(x: Symbol, rhs: Tree) = { @@ -107,8 +107,7 @@ trait Matrix extends PatternOptimizer { case _ => typer.typed(rhs, x.tpe) } - typer typed (VAL(x) === finalRhs) + traceAndReturn("[typedValDef] ", typer typed (VAL(x) === finalRhs)) } } - } \ No newline at end of file diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala index 8f354c2be9..e7f3c3784e 100644 --- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala +++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala @@ -39,12 +39,13 @@ trait ParallelMatching extends ast.TreeDSL def ifDebug(body: => Unit): Unit = { if (settings.debug.value) body } def DBG(msg: => String): Unit = { ifDebug(println(msg)) } - @elidable(elidable.FINE) + // @elidable(elidable.FINE) def TRACE(f: String, xs: Any*): Unit = { if (trace) println(if (xs.isEmpty) f else f.format(xs : _*)) } - - def logAndReturn[T](s: String, x: T): T = { log(s + x.toString) ; x } def traceAndReturn[T](s: String, x: T): T = { TRACE(s + x.toString) ; x } + def indent(s: Any) = s.toString() split "\n" map (" " + _) mkString "\n" + def indentAll(s: Seq[Any]) = s map (" " + _.toString() + "\n") mkString + /** 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 @@ -91,7 +92,7 @@ trait ParallelMatching extends ast.TreeDSL else Rep(tvars, rows).checkExhaustive } - override def toString() = "MatchMatrix(%s)".format(targets) + override def toString() = "MatchMatrix(%s) { %s }".format(matchResultType, indentAll(targets)) /** * Encapsulates a symbol being matched on. @@ -123,7 +124,7 @@ trait ParallelMatching extends ast.TreeDSL def seqType = tpe.widen baseType SeqClass def elemType = tpe typeArgs 0 // can this happen? if (seqType == NoType) error("...") - def newVarOfTpe(tpe: Type) = context.newVar(pos, tpe, flags) + def newVarOfTpe(tpe: Type) = newVar(pos, tpe, flags) def newVarOfSeqType = newVar(pos, seqType) def newVarOfElemType = newVar(pos, elemType) @@ -134,7 +135,7 @@ trait ParallelMatching extends ast.TreeDSL if (tpe =:= headType) this else new Scrutinee(newVar(pos, headType, flags)) - override def toString() = "Scrutinee(sym = %s, tpe = %s, id = %s)".format(sym, tpe, id) + override def toString() = "(%s: %s)".format(id, tpe) } def isPatternSwitch(scrut: Scrutinee, ps: List[Pattern]): Option[PatternSwitch] = { @@ -187,7 +188,7 @@ trait ParallelMatching extends ast.TreeDSL } def mkRule(rest: Rep): RuleApplication = { - logAndReturn("mkRule: ", head.tree match { + traceAndReturn("[mkRule] ", head.tree match { case x if isEquals(x.tpe) => new MixEquals(this, rest) case x: ArrayValue => new MixSequence(this, rest) case AnyUnapply(false) => new MixUnapply(this, rest, false) @@ -199,6 +200,7 @@ trait ParallelMatching extends ast.TreeDSL } ) } + override def toString() = "%s match {%s}".format(scrut, indentAll(ps)) } // PatternMatch /** picks which rewrite rule to apply @@ -225,24 +227,25 @@ trait ParallelMatching extends ast.TreeDSL def rest: Rep lazy val PatternMatch(scrut, patterns) = pats lazy val head = pats.head - private def sym = scrut.sym /** Creates Some(fail rule) even if xs == Nil. */ - def mkFail(xs: List[Row]): Option[Rep] = Some(make(sym :: rest.tvars, xs)) + def mkFail(xs: List[Row]): Option[Rep] = Some(make(scrut.sym :: rest.tvars, xs)) /** Returns None if xs == Nil, Some(fail rule) otherwise. */ def mkFailOpt(xs: List[Row]): Option[Rep] = if (xs.isEmpty) None else mkFail(xs) /** Splices scrutinee's symbol in between the given lists */ def mkNewRep(pre: List[Symbol], post: List[Symbol], rows: List[Row]) = - make(pre ::: sym :: post, rows) + make(pre ::: scrut.sym :: post, rows) /** translate outcome of the rule application into code (possible involving recursive application of rewriting) */ def tree(): Tree override def toString = { - "RuleApplication/%s (%s: %s) { %s ... }".format( - getClass(), scrut, scrut.tpe, head + "Rule/%s (%s =^= %s) {\n%s}".format( + getClass.getSimpleName, + scrut, head, + indentAll(patterns) ) } } @@ -338,11 +341,6 @@ trait ParallelMatching extends ast.TreeDSL target MATCH (casesWithDefault: _*) } } - override def toString = { - "MixLiteralInts {\n pats: %s\n varMap: %s\n}".format( - pats, varMap - ) - } } /** mixture rule for unapply pattern @@ -430,11 +428,6 @@ trait ParallelMatching extends ast.TreeDSL IF (cond) THEN squeezedBlock(vdefs, succ) ELSE fail ) } - override def toString = { - "MixUnapply {\n pats: %s\n ua: %s\n}".format( - pats, ua - ) - } } /** handle sequence pattern and ArrayValue (but not star patterns) @@ -533,8 +526,9 @@ trait ParallelMatching extends ast.TreeDSL /** condition (to be used in IF), success and failure Rep */ final def getTransition(): (Branch[Tree], Symbol) = { val value = { - // how is it known these are the only possible typerefs here? - val TypeRef(_,_,List(arg)) = head.tpe + // val TypeRef(_,_,List(arg)) = head.tpe + val arg = decodedEqualsType(head.tpe) + arg match { case SingleType(pre, sym) => REF(pre, sym) case PseudoType(o) => o.duplicate @@ -563,6 +557,7 @@ trait ParallelMatching extends ast.TreeDSL IF (handleOuter(cond)) THEN srep.toTree ELSE LabelDef(failLabel, Nil, fail) ) } + override def toString() = "MixEquals(%s == %s)".format(scrut, head) } /** mixture rule for type tests @@ -638,9 +633,8 @@ trait ParallelMatching extends ast.TreeDSL ) match { case (x,y,z) => (join(x), join(y), join(z)) } override def toString = { - "MixTypes(%s: %s) {\n moreSpecific: %s\n subsumed: %s\n remaining: %s\n}".format( - scrut, scrut.tpe, moreSpecific, subsumed, remaining - ) + super.toString() + + indentAll(List("moreSpecific: " + moreSpecific, "subsumed: " + subsumed, "remaining: " + remaining)) } /** returns casted symbol, success matrix and optionally fail matrix for type test on the top of this column */ @@ -734,11 +728,12 @@ trait ParallelMatching extends ast.TreeDSL } } override def toString() = { - val patStr = pat.mkString - val others = List(subst, guard) map (_.toString) filter (_ != "") - val otherStr = if (others.isEmpty) "" else " // " + others.mkString(" ") - - "Row(%d) %s%s".format(bx, patStr, otherStr) + val str = indent( + "%s\n%s\n%s\n".format( + subst, pat.mkString("\n"), guard + ) + ) + "Row(%d) {\n%s}".format(bx, str) } } diff --git a/src/compiler/scala/tools/nsc/matching/Patterns.scala b/src/compiler/scala/tools/nsc/matching/Patterns.scala index 017840d0c6..04c46d7e2a 100644 --- a/src/compiler/scala/tools/nsc/matching/Patterns.scala +++ b/src/compiler/scala/tools/nsc/matching/Patterns.scala @@ -61,6 +61,7 @@ trait Patterns extends ast.TreeDSL { val tree = EmptyTree override def irrefutableFor(tpe: Type) = true override def isDefault = true + override def toString() = "_" } // 8.1.2 @@ -80,16 +81,28 @@ 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() } // 8.1.4 - case class StableIdPattern(tree: Ident) extends IdentifierPattern { - val Ident(name) = tree + case class StableIdPattern(tree: Select) extends IdentifierPattern { + val Select(qualifier, name) = tree + + def pathSegments = getPathSegments(tree) + private def getPathSegments(t: Tree): List[Name] = t match { + case Select(q, name) => name :: getPathSegments(q) + case Apply(f, Nil) => getPathSegments(f) + case _ => Nil + } + + override def toString() = "StableId(%s)".format(pathSegments.mkString(" . ")) } // 8.1.4 (b) case class SelectPattern(tree: Select) extends IdentifierPattern { val Select(qualifier, name) = tree + + override def toString() = "Select(%s, %s)".format(qualifier, name) } trait IdentifierPattern extends Pattern { @@ -110,12 +123,21 @@ trait Patterns extends ast.TreeDSL { if (args.isEmpty) this rebindToEmpty tree.tpe else this + override def toString() = "Constructor(%s)".format(toPats(args).mkString(", ")) + // XXX todo // override def irrefutableFor(tpe: Type) = false } // XXX temp case class ApplyValuePattern(tree: Apply) extends ApplyPattern { require(!fn.isType) + // + // val Apply(Select(qualifier, name), Nil) = tree + // + // Examples where the above does not match: + // files/pos/t0710.scala Child() + // files/run/lazy-exprs.scala Z1() + // files/run/patmatnew.scala Child() override def simplify(testVar: Symbol) = { def examinePrefix(path: Tree) = (path, path.tpe) match { @@ -247,21 +269,30 @@ trait Patterns extends ast.TreeDSL { object Pattern { - def apply(tree: Tree): Pattern = tree match { - case x: Bind => apply(unbind(tree)) withBoundTree x - case EmptyTree => WildcardPattern() - case Ident(nme.WILDCARD) => WildcardPattern() - case x @ Alternative(ps) => AlternativePattern(x) - case x: Apply => ApplyPattern(x) - case x: Typed => TypedPattern(x) - case x: Literal => LiteralPattern(x) - case x: UnApply => UnapplyPattern(x) - case x: Ident => if (isVarPattern(x)) VariablePattern(x) else StableIdPattern(x) - // case x: ArrayValue => if (isRightIgnoring(x)) SequenceStarPattern(x) else SequencePattern(x) - case x: ArrayValue => SequencePattern(x) - case x: Select => SelectPattern(x) - case x: Star => StarPattern(x) - case _ => abort("Unknown Tree reached pattern matcher: %s/%s".format(tree, tree.getClass)) + def apply(tree: Tree): Pattern = { + val p = tree match { + case x: Bind => apply(unbind(tree)) withBoundTree x + case EmptyTree => WildcardPattern() + case Ident(nme.WILDCARD) => WildcardPattern() + case x @ Alternative(ps) => AlternativePattern(x) + case x: Apply => ApplyPattern(x) + case x: Typed => TypedPattern(x) + case x: Literal => LiteralPattern(x) + case x: UnApply => UnapplyPattern(x) + case x: Ident => VariablePattern(x) + // case x: Ident => if (isVarPattern(x)) VariablePattern(x) else StableIdPattern(x) + // case x: ArrayValue => if (isRightIgnoring(x)) SequenceStarPattern(x) else SequencePattern(x) + case x: ArrayValue => SequencePattern(x) + case x: Select => SelectPattern(x) + case x: Star => StarPattern(x) + case _ => abort("Unknown Tree reached pattern matcher: %s/%s".format(tree, tree.getClass)) + } + + p match { + case WildcardPattern() => p + case _: LiteralPattern => p + case _ => traceAndReturn("[Pattern] ", p) + } } def unapply(other: Any): Option[(Tree, List[Symbol])] = other match { case x: Tree => unapply(Pattern(x)) @@ -308,6 +339,8 @@ trait Patterns extends ast.TreeDSL { def apply(x: Apply): Pattern = { val Apply(fn, args) = x + // case x @ Apply(sel: Select, Nil) => StableIdPattern(sel) + if (fn.isType) { if (isTupleType(fn.tpe)) TuplePattern(x) else ConstructorPattern(x) -- cgit v1.2.3