summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2009-07-02 13:37:14 +0000
committerPaul Phillips <paulp@improving.org>2009-07-02 13:37:14 +0000
commit8e2090600c9d217a60c0a86a48b0e49b0f81561b (patch)
tree9eb957a5151ac653ba96fb0410eb8b9ce97dc8d9
parent568cba14a3b458977988788fb0281865002916cb (diff)
downloadscala-8e2090600c9d217a60c0a86a48b0e49b0f81561b.tar.gz
scala-8e2090600c9d217a60c0a86a48b0e49b0f81561b.tar.bz2
scala-8e2090600c9d217a60c0a86a48b0e49b0f81561b.zip
Instilling a little consistency in the pattern ...
Instilling a little consistency in the pattern matcher.
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeDSL.scala2
-rw-r--r--src/compiler/scala/tools/nsc/matching/CodeFactory.scala14
-rw-r--r--src/compiler/scala/tools/nsc/matching/ParallelMatching.scala149
-rw-r--r--src/compiler/scala/tools/nsc/matching/PatternNodes.scala66
-rw-r--r--src/compiler/scala/tools/nsc/matching/TransMatcher.scala21
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala2
6 files changed, 112 insertions, 142 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreeDSL.scala b/src/compiler/scala/tools/nsc/ast/TreeDSL.scala
index 49e0a0385a..658a8121ad 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeDSL.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeDSL.scala
@@ -33,7 +33,7 @@ trait TreeDSL {
// So it's inconsistent until I devise a better way.
val TRUE = LIT(true)
val FALSE = LIT(false)
- def NULL = LIT(null)
+ val NULL = LIT(null)
def UNIT = LIT(())
val ZERO = LIT(0)
diff --git a/src/compiler/scala/tools/nsc/matching/CodeFactory.scala b/src/compiler/scala/tools/nsc/matching/CodeFactory.scala
index 0c81c3d27a..09f4cea5f8 100644
--- a/src/compiler/scala/tools/nsc/matching/CodeFactory.scala
+++ b/src/compiler/scala/tools/nsc/matching/CodeFactory.scala
@@ -16,16 +16,26 @@ trait CodeFactory extends ast.TreeDSL
{
self: transform.ExplicitOuter with PatternNodes =>
- import global.{typer => _, _}
+ import global.{ typer => _, _ }
import analyzer.Typer
import definitions._
import CODE._
+ // strip bindings to find what tree lies underneath
+ def unbind(x: Tree): Tree = x match {
+ case Bind(_, y) => unbind(y)
+ case y => y
+ }
+
+ // Create a conditional based on a partial function - for values not defined
+ // on the partial, it is false.
+ def cond[T](x: T)(f: PartialFunction[T, Boolean]) = (f isDefinedAt x) && f(x)
+
final def typedValDef(x: Symbol, rhs: Tree)(implicit typer: Typer) = {
val finalRhs = x.tpe match {
case WildcardType =>
rhs setType null
- x setInfo typer.typed(rhs).tpe
+ x setInfo (typer typed rhs).tpe
rhs
case _ =>
typer.typed(rhs, x.tpe)
diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
index c4eef5283f..093b968ff4 100644
--- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
+++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
@@ -80,7 +80,7 @@ trait ParallelMatching extends ast.TreeDSL {
def assertIsSubtype(other: Type) = assert(isSubType(tpe, other), "problem "+tpe+" not <: "+other)
def casted(headType: Type)(implicit theOwner: Symbol) =
if (tpe =:= headType) this
- else new Scrutinee(newVar(pos, headType, flags))
+ else new Scrutinee(newVar(pos, headType, flags = flags))
}
case class Pattern(tree: Tree) {
@@ -98,26 +98,16 @@ trait ParallelMatching extends ast.TreeDSL {
/**
* Can this pattern be part of a switch statement?
*/
- lazy val isSimpleSwitchCandidate = stripped.tree match {
- case Literal(const : Constant) if isNumeric(const.tag) =>
- const.tag match {
- case FloatTag | DoubleTag | LongTag => false
- case _ => true
- }
- case _ => false
+ lazy val isSimpleSwitchCandidate = cond(stripped.tree) {
+ case Literal(const: Constant) if isNumeric(const.tag) =>
+ !cond(const.tag) { case FloatTag | DoubleTag | LongTag => true }
}
/** returns if pattern can be considered a no-op test ??for expected type?? */
- final def isDefault: Boolean = isDefaultPattern(tree);
-
- final def isEquals = tpe match {
- case TypeRef(_, sym, _) => sym eq EqualsPatternClass
- case _ => false
- }
+ final def isDefault = isDefaultPattern(tree)
+ final def isEquals = cond(tpe) { case TypeRef(_, EqualsPatternClass, _) => true }
final def getAlternativeBranches: List[Tree] = {
-
-
def get_BIND(pctx: Tree => Tree, 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)
case Alternative(ps) => ps map pctx
@@ -146,7 +136,7 @@ trait ParallelMatching extends ast.TreeDSL {
}
case class Patterns(scrut: Scrutinee, ps: List[Pattern]) {
- private lazy val column = ps.map(_.tree)
+ private lazy val column = ps map (_.tree)
lazy val head = ps.head
lazy val tail = Patterns(scrut, ps.tail)
lazy val last = ps.last
@@ -162,10 +152,7 @@ trait ParallelMatching extends ast.TreeDSL {
def isObjectTest(pat: Pattern) = pat isObjectTest headType
def isObjectTest(pat: Tree) = Pattern(pat) isObjectTest headType
// an unapply for which we don't need a type test
- def isUnapplyHead = head.tree match {
- case __UnApply(_,argtpe,_) => scrut.tpe <:< argtpe
- case _ => false
- }
+ def isUnapplyHead = cond (head.tree) { case __UnApply(_,tpe,_) => scrut.tpe <:< tpe }
def isSimpleSwitch: Boolean =
scrut.isSimple && ps.init.forall(_.isSimpleSwitchCandidate) &&
@@ -331,7 +318,8 @@ trait ParallelMatching extends ast.TreeDSL {
}
}
- def newVarCapture(pos: Position,tpe: Type)(implicit theOwner:Symbol) = newVar(pos, tpe, scrut.flags)
+ def newVarCapture(pos: Position,tpe: Type)(implicit theOwner:Symbol) =
+ newVar(pos, tpe, flags = scrut.flags)
/** returns (unapply-call, success-rep, optional fail-rep*/
final def getTransition(implicit theOwner: Symbol): (Tree, List[Tree], Rep, Option[Rep]) = {
@@ -615,10 +603,10 @@ trait ParallelMatching extends ast.TreeDSL {
val subtests =
if (!ms) subsumed
else moreSpecific.zip(subsumed) map { case (mspat, (j, pats)) => (j, mspat::pats) }
- val ntriples = for ((j, ps) <- subtests) yield {
- val (vs, thePat) = strip(pats(j))
- rest.row(j).insert2(ps, vs, casted.sym)
- }
+ val ntriples =
+ for ((j, ps) <- subtests ; val Strip(vs, thePat) = pats(j)) yield
+ (rest row j).insert2(ps, vs, casted.sym)
+
rep.make(subtestTemps ::: accessorTemps ::: rest.temp, ntriples)
}
@@ -665,7 +653,7 @@ trait ParallelMatching extends ast.TreeDSL {
* @param comb pairs of (column index, type symbol)
*/
def covers(comb: List[Combo]) = {
- lazy val results = for (Combo(i, sym) <- comb ; val p = pat(i).stripped) yield p match {
+ val results = for (Combo(i, sym) <- comb ; val p = pat(i).stripped) yield p match {
case _ if isDefaultPattern(p) => true
case _: UnApply | _: ArrayValue => true
case _ => p.tpe coversSym sym
@@ -676,16 +664,13 @@ trait ParallelMatching extends ast.TreeDSL {
// returns this row with alternatives expanded
def expand(classifyPat: (Tree, Int) => Tree): List[Row] = {
- def isAlternative(p: Tree): Boolean = p.stripped match {
- case Alternative(ps) => true
- case _ => false
- }
+ def isAlternative(p: Tree) = cond(p.stripped) { case Alternative(_) => true }
def getAlternativeBranches(p: Tree): List[Tree] = {
def get_BIND(pctx:Tree => Tree, 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)
case Alternative(ps) => ps map pctx
}
- get_BIND(x => x, p)
+ logAndReturn("get_BIND: ", get_BIND(x => x, p))
}
val indexOfAlternative = pat findIndexOf isAlternative
@@ -697,14 +682,14 @@ trait ParallelMatching extends ast.TreeDSL {
}
}
- class RepFactory(val handleOuter: Tree => Tree)(implicit val typer : Typer) {
+ class RepFactory(val handleOuter: Tree => Tree)(implicit val typer: Typer) {
var vss: List[List[Symbol]] = _
val labels = new collection.mutable.HashMap[Int, Symbol]()
var targets: List[Tree] = _
var reached: BitSet = _
var shortCuts: List[Symbol] = Nil
- final def make(temp:List[Symbol], row:List[Row], targets: List[Tree], vss:List[List[Symbol]])(implicit theOwner: Symbol): Rep = {
+ 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
this.vss = vss
@@ -712,7 +697,7 @@ trait ParallelMatching extends ast.TreeDSL {
make(temp, row)
}
- final def shortCut(theLabel:Symbol): Int = {
+ final def shortCut(theLabel: Symbol): Int = {
shortCuts = shortCuts ::: List(theLabel)
-shortCuts.length
}
@@ -722,16 +707,18 @@ trait ParallelMatching extends ast.TreeDSL {
override def transform(tree: Tree): Tree = tree match {
case blck @ Block(vdefs, ld @ LabelDef(name,params,body)) =>
val bx = labelIndex(ld.symbol)
- if (bx >= 0 && !isReachedTwice(bx)) squeezedBlock(vdefs,body)
+ if (bx >= 0 && !isReachedTwice(bx)) squeezedBlock(vdefs, body)
else blck
- case If(cond, TRUE, FALSE) =>
- super.transform(cond)
- case If(cond1, If(cond2, thenp, elsep1), elsep2) if (elsep1 equalsStructure elsep2) =>
- super.transform( IF (cond1 AND cond2) THEN thenp ELSE elsep1 )
- case If(cond1, If(cond2, thenp, Apply(jmp, Nil)), ld: LabelDef) if (jmp.symbol eq ld.symbol) =>
- super.transform( IF (cond1 AND cond2) THEN thenp ELSE ld )
- case t => super.transform(t)
+ case t => super.transform(t match {
+ case If(cond, TRUE, FALSE) =>
+ cond
+ case If(cond1, If(cond2, thenp, elsep1), elsep2) if (elsep1 equalsStructure elsep2) =>
+ IF (cond1 AND cond2) THEN thenp ELSE elsep1
+ case If(cond1, If(cond2, thenp, Apply(jmp, Nil)), ld: LabelDef) if jmp.symbol eq ld.symbol =>
+ IF (cond1 AND cond2) THEN thenp ELSE ld
+ case t => t
+ })
}
}
val res = lxtt transform tree
@@ -751,10 +738,10 @@ trait ParallelMatching extends ast.TreeDSL {
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 = {
- for ((k, v) <- labels ; if v eq label) return k
- -1
- }
+ 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
@@ -777,10 +764,10 @@ trait ParallelMatching extends ast.TreeDSL {
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)
- case _ => squeezedBlock(vdefs.reverse, LabelDef(label, vsyms, body setType tpe))
- }
+ return squeezedBlock(vdefs, (
+ if (isLabellable(body)) LabelDef(label, vsyms, body setType tpe)
+ else body.duplicate setType tpe
+ ))
}
// if some bx is not reached twice, its LabelDef is replaced with body itself
@@ -805,13 +792,10 @@ trait ParallelMatching extends ast.TreeDSL {
}
log("no consistency problem: calling %s(%s) with (%s)".format(label, fmls, args))
- body match {
- case _: Throw | _: Literal => // might be bound elsewhere (see `x @ unapply')
- val vdefs = for (v <- vss(bx) ; substv <- subst(v)) yield typedValDef(v, substv)
- squeezedBlock(vdefs, body.duplicate setType resultType)
- case _ =>
- Apply(ID(label), args)
- }
+ def vds = for (v <- vss(bx) ; substv <- subst(v)) yield typedValDef(v, substv)
+
+ if (isLabellable(body)) ID(label) APPLY (args)
+ else squeezedBlock(vds, body.duplicate setType resultType)
}
/** the injection here handles alternatives and unapply type tests */
@@ -826,8 +810,8 @@ trait ParallelMatching extends ast.TreeDSL {
// sType is called. But it ends up mixing the prefix of the other module with the val symbol
// which then causes erasure to be confused.
def sType(o: Tree) = o.tpe match {
- case st @ SingleType(pre, sym) => st
- case _ => singleType(o.tpe.prefix, o.symbol)
+ case st: SingleType => st
+ 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
@@ -844,7 +828,10 @@ trait ParallelMatching extends ast.TreeDSL {
}
def classifyPat(opat: Tree, j: Int): Tree = {
- val (vs, strippedPat) = strip(opat) match { case (vset, pat) => (vset.toList, pat) }
+ val (vs, strippedPat) = {
+ val Strip(vset, pat) = opat
+ (vset.toList, pat)
+ }
// @todo: rewrite UnApply(Apply(fn, _), _) case, using __UnApply instead of UnApply like so:
// case ua @ __UnApply(_,argtpe,_) =>
// val ua = prepat
@@ -968,7 +955,8 @@ trait ParallelMatching extends ast.TreeDSL {
var bnd = subst
for (((rpat, t), px) <- pats zip temp zipWithIndex) {
- val (vs, p) = strip(rpat)
+ val Strip(vs, p) = rpat
+
if (isDefaultPattern(p)) bnd = bnd.add(vs, t)
else {
// Row( _ ... _ p_1i ... p_1n g_m b_m ) :: rows
@@ -1020,19 +1008,17 @@ trait ParallelMatching extends ast.TreeDSL {
rep.make(roots, rows.flatMap(x => x), targets, vss)
}
- final def newVar(pos: Position, name: Name, tpe: Type, flags: List[Long])(implicit theOwner: Symbol): Symbol = {
- assert(tpe ne null, "newVar("+name+", null)")
- val sym = theOwner.newVariable(pos, name) // careful: pos has special meaning
- sym setInfo tpe
- sym setFlag flags.foldLeft(Flags.SYNTHETIC.toLong)(_|_)
+ final def newVar(
+ pos: Position,
+ tpe: Type,
+ flags: List[Long] = Nil,
+ name: Name = null
+ )(implicit theOwner: Symbol): Symbol = {
+ val n: Name = if (name == null) newName(pos, "temp") else name
+ // careful: pos has special meaning
+ theOwner.newVariable(pos, n) setInfo tpe setFlag (0L /: flags)(_|_)
}
- final def newVar(pos: Position, tpe: Type, flags: List[Long])(implicit theOwner: Symbol): Symbol =
- newVar(pos, newName(pos, "temp"), tpe, flags)
-
- final def newVar(pos: Position, tpe: Type)(implicit theOwner: Symbol): Symbol =
- newVar(pos, tpe, Nil)
-
/** returns the condition in "if (cond) k1 else k2"
*/
final def condition(tpe: Type, scrut: Scrutinee)(implicit typer: Typer, theOwner: Symbol, rep: RepFactory): Tree = {
@@ -1043,21 +1029,22 @@ trait ParallelMatching extends ast.TreeDSL {
else addOuterCondition(cond, tpe, scrut.id, rep.handleOuter)
}
- final def condition(tpe: Type, scrutTree: Tree)(implicit typer : Typer): Tree = {
+ final def condition(tpe: Type, scrutTree: Tree)(implicit typer: Typer): Tree = {
assert((tpe ne NoType) && (scrutTree.tpe ne NoType))
- def equalsRef = REF(tpe.termSymbol) ANY_== scrutTree
- def isInst = scrutTree IS tpe
+ def equalsRef = REF(tpe.termSymbol) ANY_== scrutTree
+ def isInst = scrutTree IS tpe
+ def isAnyRef(t: Type) = t <:< definitions.AnyRefClass.tpe
tpe match {
- case ct: ConstantType => ct.value match { // constant
- case v @ Constant(null) if scrutTree.tpe.isAnyRef => scrutTree ANY_EQ NULL
- case v => scrutTree ANY_== Literal(v)
+ case ct: ConstantType => ct.value match { // constant
+ case v @ Constant(null) if isAnyRef(scrutTree.tpe) => scrutTree ANY_EQ NULL
+ case v => scrutTree ANY_== Literal(v)
}
case _: SingletonType =>
if (tpe.termSymbol.isModule) equalsRef // object
- else typer typed (if (tpe.prefix ne NoPrefix) isInst else equalsRef)
+ else typer typed { if (tpe.prefix ne NoPrefix) isInst else equalsRef }
case _ =>
- if (scrutTree.tpe <:< tpe && tpe.isAnyRef) typer typed (scrutTree OBJ_!= NULL)
+ if (scrutTree.tpe <:< tpe && isAnyRef(tpe)) typer typed (scrutTree OBJ_!= NULL)
else isInst
}
}
diff --git a/src/compiler/scala/tools/nsc/matching/PatternNodes.scala b/src/compiler/scala/tools/nsc/matching/PatternNodes.scala
index 7d83f9a5d3..69a9652ac8 100644
--- a/src/compiler/scala/tools/nsc/matching/PatternNodes.scala
+++ b/src/compiler/scala/tools/nsc/matching/PatternNodes.scala
@@ -32,9 +32,9 @@ trait PatternNodes extends ast.TreeDSL
private def cmpSymbols(t1: Type, t2: Type) = t1.typeSymbol eq t2.typeSymbol
// true if t2 is a parent of t1. Should this be rather: tpe.baseTypes.exists...?
- private def parenthood(t1: Type, t2: Type) = t1.parents.exists(p => cmpSymbols(p, t2))
+ private def parenthood(t1: Type, t2: Type) = t1.parents exists (p => cmpSymbols(p, t2))
// true if t1 is direct subtype of t2 (can't use just <:< cause have to take variance into account)
- private def subtypehood(t1: Type, t2: Type) = t1.parents.exists(p => cmpSymbols(p, t2) && p <:< t2)
+ private def subtypehood(t1: Type, t2: Type) = t1.parents exists (p => cmpSymbols(p, t2) && p <:< t2)
def yParentsX = parenthood(x, y)
def xParentsY = parenthood(y, x)
@@ -72,15 +72,14 @@ trait PatternNodes extends ast.TreeDSL
}
lazy val tpe = tpeWRTEquality(_tpe)
- // The several different logics in these tests are intentionally grouped here to
- // draw attention to them. To the extent that the differences are intentional,
- // the thinking behind the distinctions needs to be documented.
- def isInt = tpe =:= IntClass.tpe
- def isChar = tpe =:= CharClass.tpe
- def isAnyRef = tpe <:< AnyRefClass.tpe
- def isBoolean = tpe.typeSymbol eq BooleanClass
- def isArray = tpe.typeSymbol eq ArrayClass
- def isNothing = tpe.typeSymbol eq NothingClass
+ // These tests for final classes can inspect the typeSymbol
+ private def is(s: Symbol) = tpe.typeSymbol eq s
+ def isInt = is(IntClass)
+ def isChar = is(CharClass)
+ def isBoolean = is(BooleanClass)
+ def isNothing = is(NothingClass)
+ def isArray = is(ArrayClass)
+
def isCaseClass = tpe.typeSymbol hasFlag Flags.CASE
def cmp(other: Type): TypeComparison = TypeComparison(tpe, tpeWRTEquality(other))
@@ -95,7 +94,7 @@ trait PatternNodes extends ast.TreeDSL
(tpe.typeSymbol == sym) ||
(symtpe <:< tpe) ||
(symtpe.parents exists (_.typeSymbol eq tpe.typeSymbol)) || // e.g. Some[Int] <: Option[&b]
- (tpe.prefix.memberType(sym) <:< tpe) // outer, see combinator.lexical.Scanner
+ ((tpe.prefix memberType sym) <:< tpe) // outer, see combinator.lexical.Scanner
}
}
@@ -133,7 +132,7 @@ trait PatternNodes extends ast.TreeDSL
val dummyMethod = new TermSymbol(NoSymbol, NoPosition, "matching$dummy")
val res = mkTypeRef(sym)
- (MethodType(dummyMethod.newSyntheticValueParams(List(tptArg, mkTypeRef(ListClass))), res), res)
+ (MethodType(dummyMethod newSyntheticValueParams List(tptArg, mkTypeRef(ListClass)), res), res)
}
Apply(TypeTree(consType), List(x, normalizedListPattern(xs, tptArg))) setType resType
}
@@ -164,22 +163,6 @@ trait PatternNodes extends ast.TreeDSL
}
}
- // TODO - this doesn't work! For some reason this sometimes returns false when encapsulated
- // in an object like this, when it returns true if the same logic is applied literally in
- // the classifyPat match in ParallelMatching. I couldn't figure out why, and it concerns
- // me - if this isn't working maybe other unapply objects aren't working right either. The big
- // problem with using unapply and type matching is that if something's amiss, it will simply fail
- // silently, with the bug most likely manifesting at some unknown later point.
- // DRM: This problem is almost certainly an instance of bug 1697
- object Ident_Or_Empty {
- def unapply(x: Any) = x match {
- case Ident(nme.WILDCARD) | EmptyTree | _: Typed | _: Literal => true
- // this returns false, and then a line identical the one above will match
- // back in PM.scala.
- case _ => false
- }
- }
-
object UnApply_TypeApply {
def unapply(x: UnApply) = x match {
case UnApply(Apply(TypeApply(sel @ Select(stor, nme.unapplySeq), List(tptArg)), _), ArrayValue(_, xs)::Nil)
@@ -197,25 +180,24 @@ trait PatternNodes extends ast.TreeDSL
}
/** returns if pattern can be considered a no-op test ??for expected type?? */
- final def isDefaultPattern(pattern: Tree): Boolean = pattern match {
- case Bind(_, p) => isDefaultPattern(p)
- case EmptyTree => true // dummy
- case Ident(nme.WILDCARD) => true
- case _ => false
-// -- what about the following? still have to test "ne null" :/
-// case Typed(nme.WILDCARD,_) => pattern.tpe <:< scrut.tpe
- }
+ 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
*/
- final def strip(x: Tree): (Set[Symbol], Tree) = x match {
- case b @ Bind(_,pat) => val (vs, p) = strip(pat); (vs + b.symbol, p)
- case _ => (emptySymbolSet, x)
- }
- object Strip { def unapply(x: Tree): Option[(Set[Symbol], Tree)] = Some(strip(x)) }
+ object Strip {
+ // all variables binding the given pattern
+ private def strip(syms: Set[Symbol], t: Tree): (Set[Symbol], Tree) = t match {
+ case b @ Bind(_, pat) => strip(syms + b.symbol, pat)
+ case _ => (syms, t)
+ }
+ def unapply(x: Tree): Option[(Set[Symbol], Tree)] = Some(strip(Set(), x))
+ }
object BoundVariables {
def unapply(x: Tree): Option[List[Symbol]] = Some(Pattern(x).boundVariables)
diff --git a/src/compiler/scala/tools/nsc/matching/TransMatcher.scala b/src/compiler/scala/tools/nsc/matching/TransMatcher.scala
index d7dd685b24..a348ea83a4 100644
--- a/src/compiler/scala/tools/nsc/matching/TransMatcher.scala
+++ b/src/compiler/scala/tools/nsc/matching/TransMatcher.scala
@@ -30,15 +30,8 @@ trait TransMatcher extends ast.TreeDSL {
final val settings_squeeze = settings.Xsqueeze.value == "on"
// check special case Seq(p1,...,pk,_*)
- protected def isRightIgnoring(p: ArrayValue): Boolean = {
- def isDefaultStar(tree: Tree): Boolean = tree match {
- case Bind(_, q) => isDefaultStar(q)
- case Star(q) => isDefaultPattern(q)
- case _ => false
- }
-
- !p.elems.isEmpty && isDefaultStar(p.elems.last)
- }
+ protected def isRightIgnoring(p: ArrayValue): Boolean =
+ !p.elems.isEmpty && cond(unbind(p.elems.last)) { case Star(q) => isDefaultPattern(q) }
/** handles all translation of pattern matching
*/
@@ -54,11 +47,9 @@ trait TransMatcher extends ast.TreeDSL {
implicit val rep = new RepFactory(handleOuter)
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.pat match {
- case _: Apply | Ident(nme.WILDCARD) => true
- case _ => false
- }
+ def matchError(obj: Tree) = atPos(selector.pos)(THROW(MatchErrorClass, obj))
+ def caseIsOk(c: CaseDef) = cond(c.pat) { case _: Apply | Ident(nme.WILDCARD) => true }
+
def doApply(fn: Tree): Boolean =
(fn.symbol eq (selector.tpe.decls lookup nme.CONSTRUCTOR)) &&
(cases forall caseIsOk)
@@ -67,7 +58,7 @@ trait TransMatcher extends ast.TreeDSL {
val Apply(fn, args) = app
val (tmps, vds) = List.unzip(
for ((arg, typeArg) <- args zip selector.tpe.typeArgs) yield {
- val v = newVar(arg.pos, newName(arg.pos, "tp"), typeArg, flags)
+ val v = newVar(arg.pos, typeArg, flags, newName(arg.pos, "tp"))
(v, typedValDef(v, arg))
}
)
diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
index 960a4e8a9a..a27f6989e1 100644
--- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
@@ -317,7 +317,7 @@ abstract class ExplicitOuter extends InfoTransform
* @pre mixinClass is an inner class
*/
def mixinOuterAccessorDef(mixinClass: Symbol): Tree = {
- val outerAcc = outerAccessor(mixinClass).overridingSymbol(currentClass)
+ val outerAcc = outerAccessor(mixinClass) overridingSymbol currentClass
assert(outerAcc != NoSymbol)
val path =
if (mixinClass.owner.isTerm) THIS(mixinClass.owner.enclClass)