summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2009-07-01 21:18:25 +0000
committerPaul Phillips <paulp@improving.org>2009-07-01 21:18:25 +0000
commite308e10616f47eea2115eec32a31c3aad47904c7 (patch)
tree3ebb1e4fdd15f85a5940109e3faaa499c23b4817
parentf535672a90db2b3314711bf23db3550391d54e7a (diff)
downloadscala-e308e10616f47eea2115eec32a31c3aad47904c7.tar.gz
scala-e308e10616f47eea2115eec32a31c3aad47904c7.tar.bz2
scala-e308e10616f47eea2115eec32a31c3aad47904c7.zip
Working on pattern matcher debuggability.
-rw-r--r--src/compiler/scala/tools/nsc/matching/ParallelMatching.scala81
-rw-r--r--src/compiler/scala/tools/nsc/matching/TransMatcher.scala27
2 files changed, 54 insertions, 54 deletions
diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
index 2ede333ecf..c4eef5283f 100644
--- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
+++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
@@ -335,18 +335,18 @@ trait ParallelMatching extends ast.TreeDSL {
/** returns (unapply-call, success-rep, optional fail-rep*/
final def getTransition(implicit theOwner: Symbol): (Tree, List[Tree], Rep, Option[Rep]) = {
- val ures = newVarCapture(ua.pos, app.tpe)
- val rhs = Apply(fxn, scrut.id :: appargs.tail) setType ures.tpe
- val uacall = typedValDef(ures, rhs)
- val zipped = pats zip rest.row
- val nrowsOther = zipped.tail flatMap {
+ val ures = newVarCapture(ua.pos, app.tpe)
+ val rhs = Apply(fxn, scrut.id :: appargs.tail) setType ures.tpe
+ val uacall = typedValDef(ures, rhs)
+ val zipped = pats zip rest.row
+ val nrowsOther = zipped.tail flatMap {
case (Stripped(sameUnapplyCall(_)), _) => Nil
case (pat, r) => List(r insert pat)
}
val nrepFail =
if (nrowsOther.isEmpty) None
- else Some(rep.make(scrut.mkList(rest.temp), nrowsOther))
+ else Some(rep.make(scrut mkList rest.temp, nrowsOther))
def mkTransition(vdefs: List[Tree], ntemps: List[Symbol], nrows: List[Row]) =
(uacall, vdefs, rep.make(scrut.mkList(ntemps, rest.temp), nrows), nrepFail)
@@ -404,6 +404,11 @@ 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)
@@ -415,7 +420,7 @@ trait ParallelMatching extends ast.TreeDSL {
final def removeStar(xs: List[Tree]): List[Tree] =
xs.init ::: makeBind(xs.last.boundVariables, WILD(scrut.sequenceType)) :: Nil
- protected def getSubPatterns(len:Int, x:Tree):Option[List[Tree]] = x match {
+ protected def getSubPatterns(len: Int, x: Tree): Option[List[Tree]] = x match {
case av @ ArrayValue(_,xs) if (!isRightIgnoring(av) && xs.length == len) => Some(xs ::: List(EmptyTree))
case av @ ArrayValue(_,xs) if ( isRightIgnoring(av) && xs.length == len+1) => Some(removeStar(xs)) // (*)
case EmptyTree | Ident(nme.WILDCARD) => Some(getDummies(len+1))
@@ -456,8 +461,8 @@ trait ParallelMatching extends ast.TreeDSL {
val (nrows, frows) = List.unzip(
for ((c, row) <- pats.zip(rest.row)) yield getSubPatterns(ys.size, c) match {
- case Some(ps) => (Some(row.insert(ps)), if (mustCheck(c, av)) Some(row.insert(c)) else None)
- case None => (None, Some(row.insert(c)))
+ case Some(ps) => (Some(row insert ps), if (mustCheck(c, av)) Some(row insert c) else None)
+ case None => (None, Some(row insert c))
})
val succRep = makeSuccRep(vs, tail, nrows.flatMap(x => x))
@@ -524,7 +529,7 @@ trait ParallelMatching extends ast.TreeDSL {
val nsuccRow = nsuccFst :: Row(getDummies( 1 /* scrutinee */ + rest.temp.length), NoBinding, NoGuard, sx) :: Nil
// todo: optimize if no guard, and no further tests
- val nsucc = rep.make(scrut.mkList(rest.temp), nsuccRow)
+ val nsucc = rep.make(scrut mkList rest.temp, nsuccRow)
val nfail = repWithoutHead(pats, rest)
(typer.typed(scrut.id ANY_== vlue), nsucc, fLabel, nfail)
@@ -619,8 +624,8 @@ trait ParallelMatching extends ast.TreeDSL {
// fails => transition to translate(remaining)
val nmatrixFail: Option[Rep] = {
- val ntemps = scrut.mkList(rest.temp)
- val ntriples = for ((j, pat) <- remaining) yield rest.row(j).insert(pat)
+ val ntemps = scrut mkList rest.temp
+ val ntriples = for ((j, pat) <- remaining) yield (rest row j) insert pat
if (ntriples.isEmpty) None else Some(rep.make(ntemps, ntriples))
}
@@ -694,7 +699,7 @@ trait ParallelMatching extends ast.TreeDSL {
class RepFactory(val handleOuter: Tree => Tree)(implicit val typer : Typer) {
var vss: List[List[Symbol]] = _
- var labels: Array[Symbol] = new Array[Symbol](4)
+ val labels = new collection.mutable.HashMap[Int, Symbol]()
var targets: List[Tree] = _
var reached: BitSet = _
var shortCuts: List[Symbol] = Nil
@@ -702,8 +707,6 @@ trait ParallelMatching extends ast.TreeDSL {
final def make(temp:List[Symbol], row:List[Row], targets: List[Tree], vss:List[List[Symbol]])(implicit theOwner: Symbol): Rep = {
// ensured that labels(i) eq null for all i, cleanup() has to be called after translation
this.targets = targets
- if (targets.length > labels.length)
- this.labels = new Array[Symbol](targets.length)
this.vss = vss
this.reached = new BitSet(targets.length)
make(temp, row)
@@ -737,16 +740,21 @@ trait ParallelMatching extends ast.TreeDSL {
}
final def cleanup() {
- for (i <- 0 until targets.length) labels(i) = null
+ labels.clear()
reached = null
shortCuts = Nil
}
- final def isReached(bx:Int) = labels(bx) ne null
- final def markReachedTwice(bx:Int) { reached += bx }
+ final def isReached(bx: Int) = labels contains bx
+ final def markReachedTwice(bx: Int) { reached += bx }
+
/** @pre bx < 0 || labelIndex(bx) != -1 */
final def isReachedTwice(bx: Int) = (bx < 0) || reached(bx)
+
/* @returns bx such that labels(bx) eq label, -1 if no such bx exists */
- final def labelIndex(label: Symbol): Int = labels.findIndexOf(_ eq label)
+ final def labelIndex(label: Symbol): Int = {
+ for ((k, v) <- labels ; if v eq label) return k
+ -1
+ }
/** first time bx is requested, a LabelDef is returned. next time, a jump.
* the function takes care of binding
@@ -757,19 +765,17 @@ trait ParallelMatching extends ast.TreeDSL {
return Apply(ID(jlabel), Nil)
}
if (!isReached(bx)) { // first time this bx is requested
- // might be bound elsewhere ( see `x @ unapply' ) <-- this comment refers to null check
+ // might be bound elsewhere
val (vsyms, vdefs) : (List[Symbol], List[Tree]) = List.unzip(
for (v <- vss(bx) ; substv <- subst(v)) yield
(v, typedValDef(v, substv))
)
- val body = targets(bx)
+ val body = targets(bx)
// @bug: typer is not able to digest a body of type Nothing being assigned result type Unit
- val tpe = if (body.tpe.isNothing) body.tpe else resultType
- val label = theOwner.newLabel(body.pos, "body%"+bx) setInfo MethodType(vsyms, tpe)
- // TODO - newLabel doesn't get a fresh name, is that okay? or should it be more like this:
- // val label = theOwner.newLabel(body.pos, newName(body.pos, "body%"+bx)) setInfo MethodType(argts, tpe)
- labels(bx) = label
+ val tpe = if (body.tpe.isNothing) body.tpe else resultType
+ val label = theOwner.newLabel(body.pos, "body%"+bx) setInfo MethodType(vsyms, tpe)
+ labels(bx) = label
return body match {
case _: Throw | _: Literal => squeezedBlock(vdefs, body.duplicate setType tpe)
@@ -779,7 +785,8 @@ trait ParallelMatching extends ast.TreeDSL {
// if some bx is not reached twice, its LabelDef is replaced with body itself
markReachedTwice(bx)
- val args = vss(bx) map subst flatten // flatMap (subst(_))
+
+ val args = vss(bx) map subst flatten
val label = labels(bx)
val body = targets(bx)
val fmls = label.tpe.paramTypes
@@ -959,7 +966,6 @@ trait ParallelMatching extends ast.TreeDSL {
case Nil => ErrorRule()
case Row(pats, subst, g, bx) :: xs =>
-
var bnd = subst
for (((rpat, t), px) <- pats zip temp zipWithIndex) {
val (vs, p) = strip(rpat)
@@ -977,7 +983,6 @@ trait ParallelMatching extends ast.TreeDSL {
}
// Row( _ ... _ g_1 b_1 ) :: rows it's all default patterns
val rest = if (g.isEmpty) null else rep.make(temp, xs) // TODO - why null?
- //DBG("\n---\nmixture rule is = VariableRule")
VariableRule (bnd, g, rest, bx)
}
@@ -996,7 +1001,6 @@ trait ParallelMatching extends ast.TreeDSL {
/** creates initial clause matrix
*/
final def initRep(roots: List[Symbol], cases: List[Tree], rep: RepFactory)(implicit theOwner: Symbol) = {
- // communicate whether exhaustiveness-checking is enabled via some flag
val (rows, targets, vss): (List[Option[Row]], List[Tree], List[List[Symbol]]) = unzip3(
for ((CaseDef(pat, g, b), bx) <- cases.zipWithIndex) yield { // stash away pvars and bodies for later
@@ -1033,7 +1037,7 @@ trait ParallelMatching extends ast.TreeDSL {
*/
final def condition(tpe: Type, scrut: Scrutinee)(implicit typer: Typer, theOwner: Symbol, rep: RepFactory): Tree = {
assert(scrut.isDefined)
- val cond = rep.handleOuter(typer.typed(condition(tpe, scrut.id)))
+ val cond = rep handleOuter (typer typed condition(tpe, scrut.id))
if (!needsOuterTest(tpe, scrut.tpe, theOwner)) cond
else addOuterCondition(cond, tpe, scrut.id, rep.handleOuter)
@@ -1045,16 +1049,16 @@ trait ParallelMatching extends ast.TreeDSL {
def isInst = scrutTree IS tpe
tpe match {
- case _: SingletonType if !tpe.isInstanceOf[ConstantType] =>
- if (tpe.termSymbol.isModule) equalsRef // object
- else if (tpe.prefix ne NoPrefix) typer typed isInst
- else typer typed equalsRef
case ct: ConstantType => ct.value match { // constant
- case v @ Constant(null) if scrutTree.tpe.isAnyRef => scrutTree ANY_EQ Literal(v)
+ case v @ Constant(null) if scrutTree.tpe.isAnyRef => scrutTree ANY_EQ NULL
case v => scrutTree ANY_== Literal(v)
}
- case _ if scrutTree.tpe <:< tpe && tpe.isAnyRef => typer typed (scrutTree OBJ_!= NULL)
- case _ => isInst
+ case _: SingletonType =>
+ if (tpe.termSymbol.isModule) equalsRef // object
+ else typer typed (if (tpe.prefix ne NoPrefix) isInst else equalsRef)
+ case _ =>
+ if (scrutTree.tpe <:< tpe && tpe.isAnyRef) typer typed (scrutTree OBJ_!= NULL)
+ else isInst
}
}
@@ -1071,5 +1075,4 @@ trait ParallelMatching extends ast.TreeDSL {
case outerAcc => cond AND (((scrut AS_ANY tpe2test) DOT outerAcc)() ANY_EQ theRef)
}
}
-
}
diff --git a/src/compiler/scala/tools/nsc/matching/TransMatcher.scala b/src/compiler/scala/tools/nsc/matching/TransMatcher.scala
index 20ffd9186a..d7dd685b24 100644
--- a/src/compiler/scala/tools/nsc/matching/TransMatcher.scala
+++ b/src/compiler/scala/tools/nsc/matching/TransMatcher.scala
@@ -55,23 +55,20 @@ trait TransMatcher extends ast.TreeDSL {
val flags = if (doCheckExhaustive) Nil else List(Flags.TRANS_FLAG)
def matchError(obj: Tree) = atPos(selector.pos)(THROW(MatchErrorClass, obj))
- def caseIsOk(c: CaseDef) = c match {
- case CaseDef(_: Apply, _, _) => true
- case CaseDef(Ident(nme.WILDCARD), _, _) => true
- case _ => false
+ def caseIsOk(c: CaseDef) = c.pat match {
+ case _: Apply | Ident(nme.WILDCARD) => true
+ case _ => false
}
def doApply(fn: Tree): Boolean =
- (fn.symbol eq selector.tpe.decls.lookup(nme.CONSTRUCTOR)) &&
+ (fn.symbol eq (selector.tpe.decls lookup nme.CONSTRUCTOR)) &&
(cases forall caseIsOk)
- def processApply(app: Apply): (List[Symbol], List[Tree], Tree) = {
+ def processTuple(app: Apply): (List[Symbol], List[Tree], Tree) = {
val Apply(fn, args) = app
val (tmps, vds) = List.unzip(
- for ((ti, i) <- args.zipWithIndex) yield {
- // These type parameter vars were not being set as synthetic.
- // Temporarily noted on the off chance it was intentional.
- val v = newVar(ti.pos, cunit.fresh.newName(ti.pos, "tp"), selector.tpe.typeArgs(i), flags)
- (v, typedValDef(v, ti))
+ for ((arg, typeArg) <- args zip selector.tpe.typeArgs) yield {
+ val v = newVar(arg.pos, newName(arg.pos, "tp"), typeArg, flags)
+ (v, typedValDef(v, arg))
}
)
(tmps, vds, matchError(treeCopy.Apply(app, fn, tmps map ID)))
@@ -80,10 +77,10 @@ trait TransMatcher extends ast.TreeDSL {
// sets temporaries, variable declarations, and the fail tree
val (tmps, vds, theFailTree) = selector match {
case app @ Apply(fn, _) if isTupleType(selector.tpe) && doApply(fn) =>
- processApply(app)
+ processTuple(app)
case _ =>
val root: Symbol = newVar(selector.pos, selector.tpe, flags)
- val vdef: Tree = typer.typed(ValDef(root, selector))
+ val vdef: Tree = typer typed (VAL(root) === selector)
val failTree: Tree = matchError(ID(root))
(List(root), List(vdef), failTree)
}
@@ -97,8 +94,8 @@ trait TransMatcher extends ast.TreeDSL {
for ((cs, bx) <- cases.zipWithIndex)
if (!rep.isReached(bx)) cunit.error(cs.body.pos, "unreachable code")
- dfatree = rep.cleanup(dfatree)
- resetTraverser.traverse(dfatree)
+ dfatree = rep cleanup dfatree
+ resetTraverser traverse dfatree
dfatree
}