summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2009-07-06 17:43:06 +0000
committerPaul Phillips <paulp@improving.org>2009-07-06 17:43:06 +0000
commit5754e85ed09df3722c3ca98e0832656ab8699e74 (patch)
treec875f7a6edde22154d6d159228d46e739317dca7 /src
parentdba0f7f3bde3d1b4e55831f9293c800955882166 (diff)
downloadscala-5754e85ed09df3722c3ca98e0832656ab8699e74.tar.gz
scala-5754e85ed09df3722c3ca98e0832656ab8699e74.tar.bz2
scala-5754e85ed09df3722c3ca98e0832656ab8699e74.zip
And more pattern matcher refinement.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeDSL.scala3
-rw-r--r--src/compiler/scala/tools/nsc/matching/ParallelMatching.scala187
-rw-r--r--src/compiler/scala/tools/nsc/matching/PatternNodes.scala10
-rw-r--r--src/compiler/scala/tools/nsc/matching/TransMatcher.scala21
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Unapplies.scala1
5 files changed, 100 insertions, 122 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreeDSL.scala b/src/compiler/scala/tools/nsc/ast/TreeDSL.scala
index d25861ee39..af4e470e81 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeDSL.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeDSL.scala
@@ -27,6 +27,9 @@ trait TreeDSL {
// on the partial, it is false.
def cond[T](x: T)(f: PartialFunction[T, Boolean]) = (f isDefinedAt x) && f(x)
+ // Applies a function to a value and then returns the value.
+ def applyAndReturn[T](f: T => Unit)(x: T): T = { f(x) ; x }
+
// strip bindings to find what lies beneath
final def unbind(x: Tree): Tree = x match {
case Bind(_, y) => unbind(y)
diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
index 6691dad894..774eca3eb0 100644
--- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
+++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
@@ -40,7 +40,8 @@ trait ParallelMatching extends ast.TreeDSL {
// debugging var, set to true to see how sausages are made
private var trace = false
- import global.{typer => _, _}
+ import global.{ typer => _, _ }
+ import definitions.{ AnyRefClass, EqualsPatternClass, IntClass, getProductArgs, productProj }
import analyzer.Typer;
import symtab.Flags
import Types._
@@ -53,11 +54,32 @@ trait ParallelMatching extends ast.TreeDSL {
def ifDebug(body: => Unit): Unit = { if (settings.debug.value) body }
def DBG(msg: => String): Unit = { ifDebug(println(msg)) }
+
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 isRightIgnoring(t: Tree) = t.isRightIgnoring
+ // Tests on misc
+ def isSwitchableTag(tag: Int) = cond(tag) { case ByteTag | ShortTag | IntTag | CharTag => true }
+ def isSwitchableConst(t: Tree) = cond(t) { case Literal(x: Constant) => isSwitchableTag(x.tag) }
+
+ // Tests on Trees
+ def isStar(t: Tree) = cond(unbind(t)) { case Star(q) => isDefaultPattern(q) }
+ def isAlternative(t: Tree) = cond(unbind(t)) { case Alternative(_) => true }
+ def isRightIgnoring(t: Tree) = cond(t) { case ArrayValue(_, xs) if !xs.isEmpty => isStar(xs.last) }
+ def isDefaultPattern(t: Tree) = cond(unbind(t)) { case EmptyTree | WILD() => true }
+ def isLabellable(t: Tree) = !cond(t) { case _: Throw | _: Literal => true }
+
+ def isModule(t: Tree) = t.symbol.isModule || t.tpe.termSymbol.isModule
+
+ // Tests on Types
+ def isEquals(t: Type) = cond(t) { case TypeRef(_, EqualsPatternClass, _) => true }
+ def isAnyRef(t: Type) = t <:< AnyRefClass.tpe
+ def isCaseClass(t: Type) = t.typeSymbol hasFlag Flags.CASE
+
+ // XXX isDefaultPattern questions:
+ // Typed(nme.WILDCARD,_) => pattern.tpe <:< scrut.tpe ... ne null
+
case class Pattern(tree: Tree) {
import definitions._
lazy val sym = tree.symbol
@@ -72,21 +94,11 @@ trait ParallelMatching extends ast.TreeDSL {
/**
* Can this pattern be part of a switch statement?
*/
- lazy val isSimpleSwitchCandidate = cond(stripped.tree) {
- case Literal(const: Constant) if isNumeric(const.tag) =>
- !cond(const.tag) { case FloatTag | DoubleTag | LongTag => true }
- }
+ lazy val isSimpleSwitchCandidate = isSwitchableConst(unbind(tree))
- /** returns if pattern can be considered a no-op test ??for expected type?? */
- final def isDefault = isDefaultPattern(tree)
- final def isEquals = cond(tpe) { case TypeRef(_, EqualsPatternClass, _) => true }
+ final def isDefault = isDefaultPattern(tree)
/* a Seq ending in _* */
- final def isRightIgnoring = {
- def isStar(t: Tree) = cond(unbind(t)) { case Star(q) => isDefaultPattern(q) }
-
- cond(tree) { case ArrayValue(_, xs) if !xs.isEmpty => isStar(xs.last) }
- }
final def getAlternativeBranches: List[Tree] = {
def get_BIND(pctx: TreeFunction1, p: Tree): List[Tree] = p match {
@@ -116,29 +128,22 @@ trait ParallelMatching extends ast.TreeDSL {
(sym ne null) && (sym != NoSymbol) && prefix.isStable && (head =:= singleType(prefix, sym))
}
- import collection.mutable.HashMap
- class MatchMatrix(context: MatchMatrixContext, failTree: Tree) {
+ import collection.mutable.{ HashMap, ListBuffer }
+ class MatchMatrix(context: MatchMatrixContext, data: MatchMatrixInit) {
import context._
+ val MatchMatrixInit(roots, cases, failTree) = data
- var vss: List[List[Symbol]] = _
- val labels: HashMap[Int, Symbol] = new HashMap
- var targets: List[Tree] = _
- var reached: BitSet = _
- var shortCuts: List[Symbol] = _
-
- final def make(temp: List[Symbol], row:List[Row], targets: List[Tree], vss: List[List[Symbol]]): Rep = {
- // ensured that labels(i) eq null for all i, cleanup() has to be called after translation
- this.vss = vss
- this.labels.clear()
- shortCuts = Nil
- this.targets = targets
- this.reached = new BitSet(targets.length)
-
- make(temp, row)
- }
+ val labels = new HashMap[Int, Symbol]()
+ val shortCuts = new ListBuffer[Symbol]()
+ lazy val reached = new BitSet(targets.size)
+
+ private lazy val expandResult = expand(roots, cases)
+ lazy val targets: List[Tree] = expandResult._2
+ lazy val vss: List[List[Symbol]] = expandResult._3
+ lazy val expansion: Rep = make(roots, expandResult._1)
final def shortCut(theLabel: Symbol): Int = {
- shortCuts = shortCuts ::: List(theLabel)
+ shortCuts += theLabel
-shortCuts.length
}
@@ -189,19 +194,9 @@ trait ParallelMatching extends ast.TreeDSL {
}
}
- val res = lxtt transform tree
- cleanup()
- resetTraverser traverse res
- res
+ applyAndReturn[Tree](resetTraverser traverse _)(lxtt transform tree)
}
- final def cleanup() {
- this.vss = null
- this.targets = null
- labels.clear()
- reached = null
- shortCuts = Nil
- }
final def isReached(bx: Int) = labels contains bx
final def markReachedTwice(bx: Int) { reached += bx }
@@ -211,9 +206,6 @@ trait ParallelMatching extends ast.TreeDSL {
/* @returns bx such that labels(bx) eq label, -1 if no such bx exists */
final def labelIndex(label: Symbol) = labels find (_._2 eq label) map (_._1) getOrElse (-1)
- /** All trees except those which don't need labels (?) */
- def isLabellable(t: Tree) = !cond(t) { case _: Throw | _: Literal => true }
-
/** first time bx is requested, a LabelDef is returned. next time, a jump.
* the function takes care of binding
*/
@@ -289,7 +281,6 @@ trait ParallelMatching extends ast.TreeDSL {
case _ => singleType(o.tpe.prefix, o.symbol)
}
def equalsCheck(o: Tree) = if (o.symbol.isValue) singleType(NoPrefix, o.symbol) else sType(o)
- def isModule(o: Tree) = o.symbol.isModule || o.tpe.termSymbol.isModule
def doSelect(o: Tree, path: Tree) = (path, path.tpe) match {
case (_, t: ThisType) => singleType(t, o.symbol) // cases 2/3 are e.g. `case Some(p._2)' in s.c.jcl.Map
@@ -359,20 +350,21 @@ trait ParallelMatching extends ast.TreeDSL {
val row = row1 flatMap (_ expand classifyPat)
if (row.length != row1.length) make(temp, row) // recursive call if any change
- else Rep(temp, row).init
+ else Rep(temp, row).checkExhaustive
}
override def toString() = {
- val toPrint: List[(Any, Traversable[Any])] =
- ((vss.zipWithIndex map (_.swap)) :::
+ val toPrint: List[(Any, Traversable[Any])] = (
+ (vss.zipWithIndex map (_.swap)) :::
List[(Any, Traversable[Any])](
"labels" -> labels,
"targets" -> targets,
"reached" -> reached,
- "shortCuts" -> shortCuts)
+ "shortCuts" -> shortCuts.toList
) filterNot (_._2.isEmpty)
- val strs = toPrint map { case (k, v) => " %s = %s\n".format(k, v) }
+ )
+ val strs = toPrint map { case (k, v) => " %s = %s\n".format(k, v) }
if (toPrint.isEmpty) "MatchMatrix()"
else "MatchMatrix(\n%s)".format(strs mkString)
}
@@ -419,7 +411,7 @@ trait ParallelMatching extends ast.TreeDSL {
lazy val tail = Patterns(scrut, ps.tail)
lazy val last = ps.last
lazy val headType = head.tpeIfHead
- lazy val isCaseHead = headType.isCaseClass
+ lazy val isCaseHead = isCaseClass(headType)
lazy val dummies = if (isCaseHead) getDummies(headType.typeSymbol.caseFieldAccessors.length) else Nil
lazy val size = ps.length
@@ -439,8 +431,8 @@ trait ParallelMatching extends ast.TreeDSL {
def mkRule(rest: Rep): RuleApplication =
logAndReturn("mkRule: ", head match {
- case x if x.isEquals => new MixEquals(this, rest)
- case Pattern(x: ArrayValue) => if (x.isRightIgnoring) new MixSequenceStar(this, rest)
+ case x if isEquals(x.tpe) => new MixEquals(this, rest)
+ case Pattern(x: ArrayValue) => if (isRightIgnoring(x)) new MixSequenceStar(this, rest)
else new MixSequence(this, rest)
case _ if isSimpleSwitch => new MixLiterals(this, rest)
case _ if isUnapplyHead => new MixUnapply(this, rest)
@@ -547,8 +539,9 @@ trait ParallelMatching extends ast.TreeDSL {
// e.g. (1,1) (1,3) (42,2) for column { case ..1.. => ;; case ..42..=> ;; case ..1.. => }
var defaultV: Set[Symbol] = emptySymbolSet
var defaultIndexSet = new BitSet(pats.size)
+ protected var tagIndices = IntMap.empty[List[Int]]
- def insertDefault(tag: Int, vs: Traversable[Symbol]) {
+ def insertDefault(tag: Int, vs: Traversable[Symbol]): Unit = {
defaultIndexSet += tag
defaultV = defaultV ++ vs
}
@@ -556,7 +549,6 @@ trait ParallelMatching extends ast.TreeDSL {
def haveDefault: Boolean = !defaultIndexSet.isEmpty
def defaultRows: List[Row] = defaultIndexSet.toList reverseMap grabRow
- protected var tagIndices = IntMap.empty[List[Int]]
protected def grabRow(index: Int): Row = {
val r = rest.row(index)
if (defaultV.isEmpty) r
@@ -605,7 +597,7 @@ trait ParallelMatching extends ast.TreeDSL {
CASE(Literal(tag)) ==> r2.toTree
}
lazy val ndefault = defaultRep map (_.toTree) getOrElse (failTree)
- lazy val casesWithDefault = cases ::: List(CASE(WILD(definitions.IntClass.tpe)) ==> ndefault)
+ lazy val casesWithDefault = cases ::: List(CASE(WILD(IntClass.tpe)) ==> ndefault)
cases match {
case CaseDef(lit,_,body) :: Nil => IF (scrut.id ANY_== lit) THEN body ELSE ndefault
@@ -663,7 +655,6 @@ trait ParallelMatching extends ast.TreeDSL {
def mkGet(s: Symbol) = typedValDef(s, fn(ID(unapplyRes), nme.get))
def mkVar(tpe: Type) = newVarCapture(ua.pos, tpe)
- import definitions.{ getProductArgs, productProj }
// 0 args => Boolean, 1 => Option[T], >1 => Option[? <: ProductN[T1,...,Tn]]
args.length match {
case 0 =>
@@ -853,7 +844,7 @@ trait ParallelMatching extends ast.TreeDSL {
class MixTypes(val pats: Patterns, val rest: Rep) extends RuleApplication {
private def subpatterns(p: Tree): List[Tree] = p match {
case Bind(_, p) => subpatterns(p)
- case app @ Apply(fn, ps) if app.tpe.isCaseClass && fn.isType => if (pats.isCaseHead) ps else pats.dummies
+ case app @ Apply(fn, ps) if isCaseClass(app.tpe) && fn.isType => if (pats.isCaseHead) ps else pats.dummies
case Apply(fn, xs) if !xs.isEmpty || fn.isType => abort("strange Apply")
case _ => pats.dummies
}
@@ -987,7 +978,6 @@ trait ParallelMatching extends ast.TreeDSL {
// returns this row with alternatives expanded
def expand(classifyPat: (Tree, Int) => Tree): List[Row] = {
- def isAlternative(p: Tree) = cond(p.stripped) { case Alternative(_) => true }
def getAlternativeBranches(p: Tree): List[Tree] = {
def get_BIND(pctx: TreeFunction1, p:Tree): List[Tree] = p match {
case b @ Bind(n,p) => get_BIND((x: Tree) => pctx(treeCopy.Bind(b, n, x) setType x.tpe), p)
@@ -1017,26 +1007,26 @@ trait ParallelMatching extends ast.TreeDSL {
case class UnapplyCall(ua: Tree, args: List[Tree])
case class Rep(val temp: List[Symbol], val row: List[Row]) {
- /** converts this to a tree - performs recursive call to translation in the process to get sub reps
- */
- final def toTree(): Tree =
- this.applyRule.tree
+ import Flags._
+
+ /** Converts this to a tree - recursively acquires subreps. */
+ final def toTree(): Tree = this.applyRule.tree
private def toUse(s: Symbol) =
- (s hasFlag Flags.MUTABLE) && // indicates that have not yet checked exhaustivity
- !(s hasFlag Flags.TRANS_FLAG) && // indicates @unchecked
- (s.tpe.typeSymbol hasFlag Flags.SEALED)
+ (s hasFlag MUTABLE) && // indicates that have not yet checked exhaustivity
+ !(s hasFlag TRANS_FLAG) && // indicates @unchecked
+ (s.tpe.typeSymbol hasFlag SEALED)
// the superclass is taken if it is not abstract
- private def countSuper(s: Symbol): Set[Symbol] = if (s hasFlag Flags.ABSTRACT) emptySymbolSet else Set(s)
+ private def countSuper(s: Symbol): Set[Symbol] = if (s hasFlag ABSTRACT) emptySymbolSet else Set(s)
private def countSymbol(s: Symbol): Set[Symbol] = candidates(s) ++ countSuper(s)
private def candidates(s: Symbol): Set[Symbol] =
- if (s hasFlag Flags.SEALED) s.children flatMap countSymbol
+ if (s hasFlag SEALED) s.children flatMap countSymbol
else emptySymbolSet
private def setsToCombine: List[(Int, Set[Symbol])] =
for ((sym, i) <- temp.zipWithIndex ; if toUse(sym)) yield {
- sym resetFlag Flags.MUTABLE
+ sym resetFlag MUTABLE
(i, candidates(sym.tpe.typeSymbol))
}
@@ -1047,25 +1037,6 @@ trait ParallelMatching extends ast.TreeDSL {
case (i, syms) :: cs => for (s <- syms.toList; rest <- combine(cs)) yield Combo(i, s) :: rest
}
- private def comboCovers(combo: List[Combo]) = row exists (_ covers combo)
-
- def init: this.type = {
- val allcomb = combine(setsToCombine)
- if (allcomb forall comboCovers) return this
-
- // if we reach here, patterns were not exhaustive
- def mkPad(xs: List[Combo], i: Int): String = xs match {
- case Nil => pad("*")
- case Combo(j, sym) :: rest => if (j == i) pad(sym.name.toString) else mkPad(rest, i)
- }
- def mkMissingStr(open: List[Combo]) =
- "missing combination " + temp.indices.map(mkPad(open, _)).mkString + "\n"
-
- val missingCombos = (allcomb filter (open => row.forall(!_.covers(open))) map mkMissingStr).mkString
- cunit.warning(temp.head.pos, "match is not exhaustive!\n" + missingCombos)
- this
- }
-
/* internal representation is (temp:List[Symbol], row:List[Row])
*
* tmp1 tmp_m
@@ -1098,6 +1069,24 @@ trait ParallelMatching extends ast.TreeDSL {
VariableRule(bnd, g, rest, bx)
}
+ def checkExhaustive: this.type = {
+ val allcomb = combine(setsToCombine)
+ if (allcomb forall (combo => row exists (_ covers combo)))
+ return this
+
+ // if we reach here, patterns were not exhaustive
+ def mkPad(xs: List[Combo], i: Int): String = xs match {
+ case Nil => pad("*")
+ case Combo(j, sym) :: rest => if (j == i) pad(sym.name.toString) else mkPad(rest, i)
+ }
+ def mkMissingStr(open: List[Combo]) =
+ "missing combination " + temp.indices.map(mkPad(open, _)).mkString + "\n"
+
+ val missingCombos = allcomb filter (open => row.forall(!_.covers(open))) map mkMissingStr
+ cunit.warning(temp.head.pos, "match is not exhaustive!\n" + missingCombos.mkString)
+ this
+ }
+
// a fancy toString method for debugging
override def toString() = {
val tempStr = (temp map (t => pad(t.name))).mkString
@@ -1141,9 +1130,9 @@ trait ParallelMatching extends ast.TreeDSL {
}
/** Expands the patterns recursively. */
- final def expand(roots: List[Symbol], cases: List[Tree]) = {
- 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
+ final def expand(roots: List[Symbol], cases: List[Tree]): (List[Row], List[Tree], List[List[Symbol]]) =
+ unzip3(
+ for ((CaseDef(pat, g, b), bx) <- cases.zipWithIndex) yield {
def mkRow(ps: List[Tree]) = Some(Row(ps, NoBinding, Guard(g), bx))
def rowForPat: Option[Row] = pat match {
@@ -1155,11 +1144,7 @@ trait ParallelMatching extends ast.TreeDSL {
(rowForPat, b, definedVars(pat))
}
- )
-
- // flatMap the list of options yields the list of values
- make(roots, rows.flatMap(x => x), targets, vss)
- }
+ ) match { case (r, t, s) => (r flatMap (x => x), t, s) }
/** returns the condition in "if (cond) k1 else k2"
*/
@@ -1173,8 +1158,6 @@ trait ParallelMatching extends ast.TreeDSL {
final def condition(tpe: Type, scrutTree: Tree): Tree = {
assert((tpe ne NoType) && (scrutTree.tpe ne NoType))
-
- def isAnyRef(t: Type) = t <:< definitions.AnyRefClass.tpe
def useEqTest = tpe.termSymbol.isModule || (tpe.prefix eq NoPrefix)
typer typed (tpe match {
@@ -1200,7 +1183,7 @@ trait ParallelMatching extends ast.TreeDSL {
})
outerAccessor(tpe2test.typeSymbol) match {
- case NoSymbol => ifDebug(cunit.warning(scrut.pos, "no outer acc for "+tpe2test.typeSymbol)) ; cond
+ case NoSymbol => ifDebug(cunit.warning(scrut.pos, "no outer acc for " + tpe2test.typeSymbol)) ; cond
case outerAcc => cond AND (((scrut AS_ANY tpe2test) DOT outerAcc)() ANY_EQ theRef)
}
}
diff --git a/src/compiler/scala/tools/nsc/matching/PatternNodes.scala b/src/compiler/scala/tools/nsc/matching/PatternNodes.scala
index 324a6b8057..0985269ea1 100644
--- a/src/compiler/scala/tools/nsc/matching/PatternNodes.scala
+++ b/src/compiler/scala/tools/nsc/matching/PatternNodes.scala
@@ -86,8 +86,6 @@ trait PatternNodes extends ast.TreeDSL
def isNothing = is(NothingClass)
def isArray = is(ArrayClass)
- def isCaseClass = tpe.typeSymbol hasFlag Flags.CASE
-
def cmp(other: Type): TypeComparison = TypeComparison(tpe, tpeWRTEquality(other))
def coversSym(sym: Symbol) = {
@@ -152,7 +150,7 @@ trait PatternNodes extends ast.TreeDSL
// if Apply tpe !isCaseClass and Apply_Value says false, return the Apply target
object Apply_Function {
/* see t301 */
- def isApplyFunction(o: Apply) = !o.tpe.isCaseClass || !Apply_Value.unapply(o).isEmpty
+ def isApplyFunction(t: Apply) = !isCaseClass(t.tpe) || !Apply_Value.unapply(t).isEmpty
def unapply(x: Any) = x match {
case x @ Apply(fun, Nil) if isApplyFunction(x) => Some(fun)
case _ => None
@@ -183,12 +181,6 @@ trait PatternNodes extends ast.TreeDSL
}
}
- /** returns if pattern can be considered a no-op test ??for expected type?? */
- final def isDefaultPattern(pattern: Tree): Boolean =
- cond(unbind(pattern)) { case EmptyTree | Ident(nme.WILDCARD) => true }
- // -- what about the following? still have to test "ne null" :/
- // case Typed(nme.WILDCARD,_) => pattern.tpe <:< scrut.tpe
-
/** returns all variables that are binding the given pattern
* @param x a pattern
* @return vs variables bound, p pattern proper
diff --git a/src/compiler/scala/tools/nsc/matching/TransMatcher.scala b/src/compiler/scala/tools/nsc/matching/TransMatcher.scala
index 9c7878a229..f7b3d27477 100644
--- a/src/compiler/scala/tools/nsc/matching/TransMatcher.scala
+++ b/src/compiler/scala/tools/nsc/matching/TransMatcher.scala
@@ -143,9 +143,9 @@ trait TransMatcher extends ast.TreeDSL with CompactTreePrinter {
}
}
- case class MatchMatrixInput(
+ case class MatchMatrixInit(
roots: List[Symbol],
- vars: List[Tree],
+ cases: List[CaseDef],
default: Tree
)
@@ -159,6 +159,7 @@ trait TransMatcher extends ast.TreeDSL with CompactTreePrinter {
{
import context._
+ // TRANS_FLAG communicates that there should be no exhaustiveness checking
val flags = List(Flags.TRANS_FLAG) filterNot (_ => isChecked)
def matchError(obj: Tree) = atPos(selector.pos)(THROW(MatchErrorClass, obj))
def caseIsOk(c: CaseDef) = cond(c.pat) { case _: Apply | Ident(nme.WILDCARD) => true }
@@ -170,15 +171,15 @@ trait TransMatcher extends ast.TreeDSL with CompactTreePrinter {
(cases forall caseIsOk)
// For x match { ... we start with a single root
- def singleMatch() = {
+ def singleMatch(): (List[Tree], MatchMatrixInit) = {
val root: Symbol = newVar(selector.pos, selector.tpe, flags)
val varDef: Tree = typedValDef(root, selector)
- MatchMatrixInput(List(root), List(varDef), matchError(ID(root)))
+ (List(varDef), MatchMatrixInit(List(root), cases, matchError(ID(root))))
}
// For (x, y, z) match { ... we start with multiple roots, called tpXX.
- def tupleMatch(app: Apply) = {
+ def tupleMatch(app: Apply): (List[Tree], MatchMatrixInit) = {
val Apply(fn, args) = app
val (roots, vars) = List.unzip(
for ((arg, typeArg) <- args zip selector.tpe.typeArgs) yield {
@@ -186,17 +187,17 @@ trait TransMatcher extends ast.TreeDSL with CompactTreePrinter {
(v, typedValDef(v, arg))
}
)
- MatchMatrixInput(roots, vars, matchError(treeCopy.Apply(app, fn, roots map ID)))
+ (vars, MatchMatrixInit(roots, cases, matchError(treeCopy.Apply(app, fn, roots map ID))))
}
- // sets up input for the matching algorithm
- val MatchMatrixInput(roots, vars, default) = selector match {
+ // sets up top level variables and algorithm input
+ val (vars, matrixInit) = selector match {
case app @ Apply(fn, _) if isTupleType(selector.tpe) && doApply(fn) => tupleMatch(app)
case _ => singleMatch()
}
- val matrix = new MatchMatrix(context, default)
- val rep = matrix.expand(roots, cases) // expands casedefs and assigns name
+ val matrix = new MatchMatrix(context, matrixInit)
+ val rep = matrix.expansion // expands casedefs and assigns name
val mch = typer typed rep.toTree // executes algorithm, converts tree to DFA
val dfatree = typer typed Block(vars, mch) // packages into a code block
diff --git a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
index fc20277c52..e1d13a5253 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
@@ -23,7 +23,6 @@ trait Unapplies extends ast.TreeDSL
private def isVarargs(vd: ValDef) = treeInfo isRepeatedParamType vd.tpt
private def isByName(vd: ValDef) = treeInfo isByNameParamType vd.tpt
private def toIdent(x: DefTree) = Ident(x.name)
- private def applyAndReturn[T](f: T => Unit)(x: T): T = { f(x) ; x }
/** returns type list for return type of the extraction */
def unapplyTypeList(ufn: Symbol, ufntpe: Type) = {