summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2009-10-11 20:17:32 +0000
committerPaul Phillips <paulp@improving.org>2009-10-11 20:17:32 +0000
commit112a1dbef04bdeb8255ab4af709b2e16a79bc827 (patch)
tree8abe5a91a7a5496daf01d4fe9bd6a715e9397190 /src
parent901ce7a85bec6cda170ec0949bada3f9c8d6213a (diff)
downloadscala-112a1dbef04bdeb8255ab4af709b2e16a79bc827.tar.gz
scala-112a1dbef04bdeb8255ab4af709b2e16a79bc827.tar.bz2
scala-112a1dbef04bdeb8255ab4af709b2e16a79bc827.zip
Further iteration related to patterns and bindi...
Further iteration related to patterns and bindings.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/matching/Matrix.scala1
-rw-r--r--src/compiler/scala/tools/nsc/matching/ParallelMatching.scala67
-rw-r--r--src/compiler/scala/tools/nsc/matching/Patterns.scala46
3 files changed, 68 insertions, 46 deletions
diff --git a/src/compiler/scala/tools/nsc/matching/Matrix.scala b/src/compiler/scala/tools/nsc/matching/Matrix.scala
index 96b665f2ea..c489955e5e 100644
--- a/src/compiler/scala/tools/nsc/matching/Matrix.scala
+++ b/src/compiler/scala/tools/nsc/matching/Matrix.scala
@@ -158,6 +158,7 @@ trait Matrix extends MatrixAdditions {
override def toString() = "%s: %s = %s".format(lhs, lhs.info, rhs)
}
+ // val NoPatternVar = PatternVar(NoSymbol, EmptyTree, false)
/** Sets the rhs to EmptyTree, which makes the valDef ignored in Scrutinee.
*/
diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
index 0e08c0eaf5..5c27a7373c 100644
--- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
+++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
@@ -53,12 +53,15 @@ trait ParallelMatching extends ast.TreeDSL
-shortCuts.length
}
+ // XXX transitional.
+ final def requestBody(bx: Int, subst: Bindings): Tree =
+ requestBody(bx, PatternVarGroup.fromBindings(subst.get(), targets(bx).freeVars))
+
/** first time bx is requested, a LabelDef is returned. next time, a jump.
* the function takes care of binding
*/
- final def requestBody(bx: Int, subst: Bindings): Tree = {
- val target @ FinalState(tbx, body, freeVars) = targets(bx)
- val pvgroup = PatternVarGroup.fromBindings(subst.get(), freeVars)
+ final def requestBody(bx: Int, pvgroup: PatternVarGroup): Tree = {
+ val target = targets(bx)
// shortcut
if (bx < 0) Apply(ID(shortCuts(-bx-1)), Nil)
@@ -70,7 +73,7 @@ trait ParallelMatching extends ast.TreeDSL
/** the injection here handles alternatives and unapply type tests */
final def make(tvars: PatternVarGroup, row1: List[Row]): Rep = {
- def classifyPat(opat: Pattern, j: Int): Pattern = opat simplify tvars(j).sym
+ def classifyPat(opat: Pattern, j: Int): Pattern = opat simplify tvars(j)
val rows = row1 flatMap (_ expandAlternatives classifyPat)
if (rows.length != row1.length) make(tvars, rows) // recursive call if any change
@@ -114,10 +117,13 @@ trait ParallelMatching extends ast.TreeDSL
// sequences
def seqType = tpe.widen baseType SeqClass
def elemType = tpe typeArgs 0
- def elemAt(i: Int) = (id DOT (tpe member nme.apply))(LIT(i))
- def createElemVar(i: Int) = createVar(elemType, _ => elemAt(i))
- def createSeqVar(drop: Int) = createVar(seqType, _ => id DROP drop)
+ private def elemAt(i: Int) = (id DOT (tpe member nme.apply))(LIT(i))
+ private def createElemVar(i: Int) = createVar(elemType, _ => elemAt(i))
+ private def createSeqVar(drop: Int) = createVar(seqType, _ => id DROP drop)
+
+ def createSequenceVars(count: Int): List[PatternVar] =
+ (0 to count).toList map (i => if (i < count) createElemVar(i) else createSeqVar(i))
// for propagating "unchecked" to synthetic vars
def isChecked = !(sym hasFlag TRANS_FLAG)
@@ -171,6 +177,7 @@ trait ParallelMatching extends ast.TreeDSL
def isCaseHead = head.isCaseClass
private val dummyCount = if (isCaseHead) headType.typeSymbol.caseFieldAccessors.length else 0
def dummies = emptyPatterns(dummyCount)
+ // def dummies = head.dummies
def apply(i: Int): Pattern = ps(i)
def pzip() = ps.zipWithIndex
@@ -362,7 +369,8 @@ trait ParallelMatching extends ast.TreeDSL
private def sameFunction(fn1: Tree) = fxn.symbol == fn1.symbol && (fxn equalsStructure fn1)
def unapply(p: Pattern) = condOpt(p) {
- case Pattern(UnApply(Apply(fn1, _), args), _) if sameFunction(fn1) => args
+ case Pattern(UnApply(Apply(fn1, _), args), _) if sameFunction(fn1) =>
+ tracing("sameUnapply", args)
}
}
object SameUnapply {
@@ -373,13 +381,6 @@ trait ParallelMatching extends ast.TreeDSL
}
def isSameUnapply(p: Pattern) = SameUnapply.unapply(p).isDefined
- // Second argument is number of dummies to prepend in the default case
- def mkNewRows(sameFilter: (List[Tree]) => List[Tree], dum: Int) =
- for ((pat, r) <- zipped) yield pat match {
- case sameUnapplyCall(args) => r.insert2(toPats(sameFilter(args)) ::: List(NoPattern), pat.boundVariables, scrut.sym)
- case _ => r insert (emptyPatterns(dum) ::: List(pat))
- }
-
lazy val cond: Tree =
if (unapplyResult.tpe.isBoolean) ID(unapplyResult.valsym)
else unapplyResult.valsym IS_DEFINED
@@ -403,11 +404,20 @@ trait ParallelMatching extends ast.TreeDSL
for ((tpe, i) <- tpes.zipWithIndex) yield
scrut.createVar(tpe, _ => fn(ID(tuple), productProj(tuple, i + 1)))
+ // the filter prevents infinite unapply recursion
+ def mkNewRows(sameFilter: (List[Tree]) => List[Tree]) = {
+ val dum = if (args.length <= 1) args.length else tpes.size
+ for ((pat, r) <- zipped) yield pat match {
+ case sameUnapplyCall(xs) => r.insert2(toPats(sameFilter(xs)) ::: List(NoPattern), pat.boundVariables, scrut.sym)
+ case _ => r insert (emptyPatterns(dum) ::: List(pat))
+ }
+ }
+
// 0 is Boolean, 1 is Option[T], 2+ is Option[(T1,T2,...)]
args.length match {
- case 0 => (Nil, Nil, mkNewRows((xs) => Nil, 0))
- case 1 => (List(pv), List(pv), mkNewRows(xs => List(xs.head), 1))
- case _ => (pv :: tuplePVs, tuplePVs, mkNewRows(identity, tpes.size))
+ case 0 => (Nil, Nil, mkNewRows((xs) => Nil))
+ case 1 => (List(pv), List(pv), mkNewRows(xs => List(xs.head)))
+ case _ => (pv :: tuplePVs, tuplePVs, mkNewRows(identity))
}
}
@@ -437,7 +447,8 @@ trait ParallelMatching extends ast.TreeDSL
}
def getSubPatterns(x: Pattern): Option[List[Pattern]] = {
- def defaults = Some(emptyPatterns(pivot.elemPatterns.length + 1))
+ // def defaults = Some(emptyPatterns(pivot.elemPatterns.length + 1))
+ def defaults = Some(pivot.dummies)
val av @ ArrayValue(_, xs) = x.tree match {
case x: ArrayValue => x
case EmptyTree | WILD() => return defaults
@@ -467,8 +478,7 @@ trait ParallelMatching extends ast.TreeDSL
assert(scrut.tpe <:< head.tpe, "fatal: %s is not <:< %s".format(scrut, head.tpe))
// one pattern var per sequence element up to elemCount, and one more for the rest of the sequence
- val elemCount = pivot.nonStarPatterns.size
- val pvs = ((0 until elemCount).toList map (scrut createElemVar _)) ::: List(scrut createSeqVar elemCount)
+ val pvs = scrut createSequenceVars pivot.nonStarPatterns.size
val (nrows, frows): (List[Option[Row]], List[Option[Row]]) = List.unzip(
for ((c, rows) <- pmatch pzip rest.rows) yield getSubPatterns(c) match {
@@ -663,11 +673,12 @@ trait ParallelMatching extends ast.TreeDSL
// returns this rows with alternatives expanded
def expandAlternatives(classifyPat: (Pattern, Int) => Pattern): List[Row] = {
+ def isNotAlternative(p: Pattern) = !cond(p.tree) { case _: Alternative => true }
+
// classify all the top level patterns - alternatives come back unaltered
val newPats: List[Pattern] = pats.zipWithIndex map tupled(classifyPat)
// see if any alternatives were in there
- val (ps, others) = newPats span (x => !x.isAlternative)
-
+ val (ps, others) = newPats span isNotAlternative
// make a new row for each alternative, with it spliced into the original position
if (others.isEmpty) List(copy(pats = ps))
else extractBindings(others.head) map (x => replaceAt(ps.size, x))
@@ -684,8 +695,14 @@ trait ParallelMatching extends ast.TreeDSL
class ExpandedMatrix(val rows: List[Row], val targets: List[FinalState]) {
require(rows.size == targets.size)
- override def toString() =
- "ExpandedMatrix(%d)".format(rows.size) + pp(rows zip targets, true)
+ override def toString() = {
+ def rprint(r: Row) = "Row %d: %d pats, %d bound".format(r.bx, r.pats.size, r.subst.get().size)
+ def tprint(t: FinalState) = "%s (free = %s)".format(t.body, pp(t.freeVars))
+ val xs = rows zip targets map { case (r,t) => rprint(r) -> tprint(t) }
+ val ppstr = pp(xs, newlines = true)
+
+ "ExpandedMatrix(%d rows)".format(rows.size) + ppstr
+ }
}
abstract class State {
diff --git a/src/compiler/scala/tools/nsc/matching/Patterns.scala b/src/compiler/scala/tools/nsc/matching/Patterns.scala
index 75b13c2d32..895bb7a4f3 100644
--- a/src/compiler/scala/tools/nsc/matching/Patterns.scala
+++ b/src/compiler/scala/tools/nsc/matching/Patterns.scala
@@ -23,7 +23,8 @@ trait Patterns extends ast.TreeDSL {
import Debug._
import treeInfo.{ unbind, isVarPattern }
- type PatternMatch = MatchMatrix#PatternMatch
+ type PatternMatch = MatchMatrix#PatternMatch
+ private type PatternVar = MatrixContext#PatternVar
// Fresh patterns
def emptyPatterns(i: Int): List[Pattern] = List.fill(i)(NoPattern)
@@ -58,8 +59,8 @@ trait Patterns extends ast.TreeDSL {
override def subpatternsForVars: List[Pattern] = List(Pattern(expr))
override def irrefutableFor(tpe: Type) = tpe <:< tree.tpe
- override def simplify(testVar: Symbol) = Pattern(expr) match {
- case ExtractorPattern(ua) if testVar.tpe <:< tpt.tpe => this rebindTo expr
+ override def simplify(pv: PatternVar) = Pattern(expr) match {
+ case ExtractorPattern(ua) if pv.sym.tpe <:< tpt.tpe => this rebindTo expr
case _ => this
}
override def toString() = "%s: %s".format(Pattern(expr), tpt)
@@ -80,7 +81,7 @@ trait Patterns extends ast.TreeDSL {
val ident @ Ident(name) = fn
override def typeToMatch = Pattern(ident).equalsCheck
- override def simplify(testVar: Symbol) = this.rebindToObjectCheck()
+ override def simplify(pv: PatternVar) = this.rebindToObjectCheck()
override def toString() = "Id(%s)".format(name)
}
// 8.1.4 (b)
@@ -88,7 +89,7 @@ trait Patterns extends ast.TreeDSL {
val Apply(select: Select, _) = tree
override def typeToMatch = mkSingletonFromQualifier
- override def simplify(testVar: Symbol) = this.rebindToObjectCheck()
+ override def simplify(pv: PatternVar) = this.rebindToObjectCheck()
override def toString() = "SelectApply(%s)".format(name)
}
// 8.1.4 (c)
@@ -101,7 +102,7 @@ trait Patterns extends ast.TreeDSL {
require(!fn.isType && isModule)
override def typeToMatch = tpe.narrow
- override def simplify(testVar: Symbol) = this.rebindToObjectCheck()
+ override def simplify(pv: PatternVar) = this.rebindToObjectCheck()
override def toString() = "Object(%s)".format(fn)
}
// 8.1.4 (e)
@@ -114,10 +115,10 @@ trait Patterns extends ast.TreeDSL {
require(fn.isType && this.isCaseClass)
override def subpatterns(pm: MatchMatrix#PatternMatch) =
- if (pm.isCaseHead) args map Pattern.apply
+ if (pm.head.isCaseClass) args map Pattern.apply
else super.subpatterns(pm)
- override def simplify(testVar: Symbol) =
+ override def simplify(pv: PatternVar) =
if (args.isEmpty) this rebindToEmpty tree.tpe
else this
@@ -141,8 +142,8 @@ trait Patterns extends ast.TreeDSL {
override def typeToMatch = arg.tpe
// can fix #1697 here?
- override def simplify(testVar: Symbol) =
- if (testVar.tpe <:< arg.tpe) this
+ override def simplify(pv: PatternVar) =
+ if (pv.sym.tpe <:< arg.tpe) this
else this rebindTo uaTyped
override def toString() = "Unapply(f: %s => %s)".format(typeToMatch, fn.tpe.resultType)
@@ -175,8 +176,8 @@ trait Patterns extends ast.TreeDSL {
}
// @pre: is not right-ignoring (no star pattern) ; no exhaustivity check
- override def simplify(testVar: Symbol) = {
- testVar setFlag Flags.TRANS_FLAG
+ override def simplify(pv: PatternVar) = {
+ pv.sym setFlag Flags.TRANS_FLAG
this rebindTo elems.foldRight(gen.mkNil)(listFolder)
}
override def toString() = "UnapplySeq(%s)".format(elems)
@@ -195,6 +196,8 @@ trait Patterns extends ast.TreeDSL {
def nonStarLength = nonStarPatterns.length
def isAllDefaults = nonStarPatterns forall (_.isDefault)
+ override def dummies = emptyPatterns(elemPatterns.length + 1)
+
def rebindStar(seqType: Type): List[Pattern] = {
require(hasStar)
nonStarPatterns ::: List(lastPattern rebindTo WILD(seqType))
@@ -399,13 +402,9 @@ trait Patterns extends ast.TreeDSL {
sealed trait NamePattern extends Pattern {
def name: Name
override def typeToMatch = tpe.narrow
- override def simplify(testVar: Symbol) = this.rebindToEqualsCheck()
+ override def simplify(pv: PatternVar) = this.rebindToEqualsCheck()
}
- // trait SimplePattern extends Pattern {
- // def simplify(testVar: Symbol): Pattern = this
- // }
-
sealed trait UnapplyPattern extends Pattern {
lazy val UnApply(unfn, args) = tree
override def subpatternsForVars: List[Pattern] = toPats(args)
@@ -422,6 +421,10 @@ trait Patterns extends ast.TreeDSL {
protected lazy val Apply(fn, args) = tree
override def subpatternsForVars: List[Pattern] = toPats(args)
+ override def dummies =
+ if (!this.isCaseClass) Nil
+ else emptyPatterns(typeToMatch.typeSymbol.caseFieldAccessors.size)
+
def isConstructorPattern = fn.isType
}
@@ -429,8 +432,11 @@ trait Patterns extends ast.TreeDSL {
val tree: Tree
// returns either a simplification of this pattern or identity.
- def simplify(testVar: Symbol): Pattern = this
- def simplify(): Pattern = this simplify NoSymbol
+ def simplify(pv: PatternVar): Pattern = this
+ def simplify(): Pattern = this simplify null
+
+ // the right number of dummies for this pattern
+ def dummies: List[Pattern] = Nil
// given this scrutinee, what if any condition must be satisfied before
// we even try to match?
@@ -478,8 +484,6 @@ trait Patterns extends ast.TreeDSL {
else tpe.narrow
)
- final def isAlternative = cond(tree) { case Alternative(_) => true }
-
/** Standard methods **/
def copy(tree: Tree = this.tree): Pattern =
if (boundTree eq tree) Pattern(tree)