summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2010-05-14 19:25:31 +0000
committerPaul Phillips <paulp@improving.org>2010-05-14 19:25:31 +0000
commitd97b3a8066dfe588e080c6b3c87bda2c9f27f80e (patch)
tree587dcb985358d3381bc4fa9648ba12a725ea42dc /src/compiler
parent7b822f28663e547e438f7aeb4e6520af32be7c07 (diff)
downloadscala-d97b3a8066dfe588e080c6b3c87bda2c9f27f80e.tar.gz
scala-d97b3a8066dfe588e080c6b3c87bda2c9f27f80e.tar.bz2
scala-d97b3a8066dfe588e080c6b3c87bda2c9f27f80e.zip
Starting to look like the pattern matcher and I...
Starting to look like the pattern matcher and I can meet in the middle. More distributing my acquired bottom-up knowledge among the current code. No review.
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/matching/ParallelMatching.scala26
-rw-r--r--src/compiler/scala/tools/nsc/matching/PatternBindings.scala5
-rw-r--r--src/compiler/scala/tools/nsc/matching/Patterns.scala62
3 files changed, 43 insertions, 50 deletions
diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
index 7fbc57c325..73ecbdee70 100644
--- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
+++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
@@ -171,9 +171,7 @@ trait ParallelMatching extends ast.TreeDSL
def tail = ps.tail
def size = ps.length
- def caseAccessors = head.necessaryType.typeSymbol.caseFieldAccessors
- def currentArity = if (head.isCaseClass) caseAccessors.length else 0
- def dummies = emptyPatterns(currentArity)
+ def dummies = head.dummies
def apply(i: Int): Pattern = ps(i)
def pzip() = ps.zipWithIndex
@@ -190,17 +188,11 @@ trait ParallelMatching extends ast.TreeDSL
}
}
- object TypedUnapply {
- def unapply(x: Tree): Option[Boolean] = condOpt(x) {
- case Typed(UnapplyParamType(tpe), tpt) => !(tpt.tpe <:< tpe)
- }
- }
-
def mkRule(rest: Rep): RuleApplication = {
tracing("Rule", head match {
case x if isEquals(x.tree.tpe) => new MixEquals(this, rest)
case x: SequencePattern => new MixSequence(this, rest, x)
- case AnyUnapply(false) => new MixUnapply(this, rest, false)
+ case AnyUnapply(false) => new MixUnapply(this, rest)
case _ =>
isPatternSwitch(scrut, ps) match {
case Some(x) => new MixLiteralInts(x, rest)
@@ -356,7 +348,7 @@ trait ParallelMatching extends ast.TreeDSL
/** mixture rule for unapply pattern
*/
- class MixUnapply(val pmatch: PatternMatch, val rest: Rep, typeTest: Boolean) extends RuleApplication {
+ class MixUnapply(val pmatch: PatternMatch, val rest: Rep) extends RuleApplication {
val uapattern = head match { case x: UnapplyPattern => x ; case _ => abort("XXX") }
val ua @ UnApply(app, args) = head.tree
@@ -569,16 +561,16 @@ trait ParallelMatching extends ast.TreeDSL
val failRows = new ListBuffer[(Int, Pattern)]
for ((pattern, j) <- pmatch.pzip()) {
- def isMoreSpecific = matches(pattern.tpe, head.necessaryType)
- def isLessSpecific = matches(head.necessaryType, pattern.tpe)
- def isEquivalent = head.necessaryType =:= pattern.tpe
- def isObjectTest = pattern.isObject && (head.necessaryType =:= pattern.necessaryType)
+ def isMoreSpecific = matches(pattern.tpe, head.tpe)
+ def isLessSpecific = matches(head.tpe, pattern.tpe)
+ def isEquivalent = head.tpe =:= pattern.tpe
+ def isObjectTest = pattern.isObject && (head.tpe =:= pattern.tpe)
def ifElsePattern(yes: Pattern) = if (isEquivalent) yes else pattern
def succDummy = succRows += ((j, NoPattern :: pmatch.dummies))
def succTyped(pp: Pattern) = succRows += ((j, ifElsePattern(pp) :: pmatch.dummies))
- def succSubs = succRows += ((j, ifElsePattern(NoPattern) :: (pattern subpatterns pmatch)))
+ def succSubs = succRows += ((j, ifElsePattern(NoPattern) :: (pattern expandToArity head.arity)))
def failOnly = failRows += ((j, pattern))
pattern match {
@@ -605,7 +597,7 @@ trait ParallelMatching extends ast.TreeDSL
}
}
- lazy val casted = scrut castedTo head.necessaryType
+ lazy val casted = scrut castedTo head.tpe
lazy val cond = condition(checkErroneous(casted), scrut, head.boundVariables.nonEmpty)
lazy val success = {
diff --git a/src/compiler/scala/tools/nsc/matching/PatternBindings.scala b/src/compiler/scala/tools/nsc/matching/PatternBindings.scala
index 83fd3a9608..82bddb2013 100644
--- a/src/compiler/scala/tools/nsc/matching/PatternBindings.scala
+++ b/src/compiler/scala/tools/nsc/matching/PatternBindings.scala
@@ -104,10 +104,7 @@ trait PatternBindings extends ast.TreeDSL
// Like rebindToEqualsCheck, but subtly different. Not trying to be
// mysterious -- I haven't sorted it all out yet.
- def rebindToObjectCheck(): Pattern = {
- val sType = sufficientType
- rebindToType(mkEqualsRef(sType), sType)
- }
+ def rebindToObjectCheck(): Pattern = rebindToType(mkEqualsRef(atomicTpe), atomicTpe)
/** Helpers **/
private def wrapBindings(vs: List[Symbol], pat: Tree): Tree = vs match {
diff --git a/src/compiler/scala/tools/nsc/matching/Patterns.scala b/src/compiler/scala/tools/nsc/matching/Patterns.scala
index a135655b9d..b1bcf44c38 100644
--- a/src/compiler/scala/tools/nsc/matching/Patterns.scala
+++ b/src/compiler/scala/tools/nsc/matching/Patterns.scala
@@ -89,7 +89,7 @@ trait Patterns extends ast.TreeDSL {
// require (!isVarPattern(fn) && args.isEmpty)
val ident @ Ident(name) = fn
- override def sufficientType = Pattern(ident).equalsCheck
+ override def atomicTpe = Pattern(ident).equalsCheck
override def simplify(pv: PatternVar) = this.rebindToObjectCheck()
override def description = "Id(%s)".format(name)
}
@@ -98,7 +98,7 @@ trait Patterns extends ast.TreeDSL {
require (args.isEmpty)
val Apply(select: Select, _) = tree
- override def sufficientType = mkSingletonFromQualifier
+ override def atomicTpe = mkSingletonFromQualifier
override def simplify(pv: PatternVar) = this.rebindToObjectCheck()
override def description = backticked match {
case Some(s) => "this." + s
@@ -117,7 +117,7 @@ trait Patterns extends ast.TreeDSL {
case class ObjectPattern(tree: Apply) extends ApplyPattern { // NamePattern?
require(!fn.isType && isModule)
- override def sufficientType = tpe.narrow
+ override def atomicTpe = tpe.narrow
override def simplify(pv: PatternVar) = this.rebindToObjectCheck()
override def description = "Obj(%s)".format(fn)
}
@@ -139,9 +139,10 @@ trait Patterns extends ast.TreeDSL {
private def isColonColon = cleanName == "::"
- override def subpatterns(pm: MatchMatrix#PatternMatch) =
- if (pm.head.isCaseClass) toPats(args)
- else super.subpatterns(pm)
+ override def expandToArity(newArity: Int): List[Pattern] = {
+ assert(newArity == args.length)
+ toPats(args)
+ }
override def simplify(pv: PatternVar) =
if (args.isEmpty) this rebindToEmpty tree.tpe
@@ -168,13 +169,14 @@ trait Patterns extends ast.TreeDSL {
private val MethodType(List(arg, _*), _) = fn.tpe
private def uaTyped = Typed(tree, TypeTree(arg.tpe)) setType arg.tpe
- override def necessaryType = arg.tpe
+ // to match an extractor, the arg type must be matched.
+ override def tpe = arg.tpe
override def simplify(pv: PatternVar) =
if (pv.sym.tpe <:< arg.tpe) this
else this rebindTo uaTyped
- override def description = "UnApp(%s => %s)".format(necessaryType, resTypesString)
+ override def description = "UnApp(%s => %s)".format(tpe, resTypesString)
}
// 8.1.8 (unapplySeq calls)
@@ -384,7 +386,7 @@ trait Patterns extends ast.TreeDSL {
protected def mkSingletonFromQualifier = {
def pType = qualifier match {
case _: Apply => PseudoType(tree)
- case _ => singleType(Pattern(qualifier).necessaryType, sym)
+ case _ => singleType(Pattern(qualifier).tpe, sym)
}
qualifier.tpe match {
case t: ThisType => singleType(t, sym) // this.X
@@ -395,7 +397,7 @@ trait Patterns extends ast.TreeDSL {
sealed trait NamePattern extends Pattern {
def name: Name
- override def sufficientType = tpe.narrow
+ override def atomicTpe = tpe.narrow
override def simplify(pv: PatternVar) = this.rebindToEqualsCheck()
override def description = name.toString()
}
@@ -422,22 +424,31 @@ 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(sufficientType.typeSymbol.caseFieldAccessors.size)
-
def isConstructorPattern = fn.isType
}
sealed abstract class Pattern extends PatternBindingLogic {
val tree: Tree
+ // The type of a pattern says: in order for something to match this
+ // pattern, it must conform to this type. It does NOT say that if
+ // something does conform to this type, it definitely matches the pattern:
+ // see atomic type for that.
+ def tpe = tree.tpe
+
+ // The atomic type of a pattern says: if something matches this, it
+ // definitely matches the pattern (but this is independent of nullness
+ // and guards, which are checked independently.)
+ def atomicTpe = tpe
+
// returns either a simplification of this pattern or identity.
def simplify(pv: PatternVar): Pattern = this
- def simplify(): Pattern = this simplify null
+
+ // the arity of this pattern
+ def arity = if (isCaseClass) caseAccessors.length else 0
// the right number of dummies for this pattern
- def dummies: List[Pattern] = Nil
+ def dummies: List[Pattern] = emptyPatterns(arity)
// 8.1.13
// A pattern p is irrefutable for type T if any of the following applies:
@@ -448,33 +459,26 @@ trait Patterns extends ast.TreeDSL {
// pi is irrefutable for Ti.
def irrefutableFor(tpe: Type) = false
- // does this pattern completely cover that pattern (i.e. latter cannot be matched)
- def completelyCovers(second: Pattern) = false
-
// Is this a default pattern (untyped "_" or an EmptyTree inserted by the matcher)
def isDefault = false
- // what type must a scrutinee have to have any chance of matching this pattern?
- def necessaryType = tpe
-
- // what type could a scrutinee have which would automatically indicate a match?
- // (nullness and guards will still be checked.)
- def sufficientType = tpe
-
// XXX have to determine if this can be made useful beyond an extractor barrier.
// Default sufficient type might be NothingClass.tpe, tpe.narrow, ...
// the subpatterns for this pattern (at the moment, that means constructor arguments)
- def subpatterns(pm: MatchMatrix#PatternMatch): List[Pattern] = pm.dummies
+ def expandToArity(newArity: Int): List[Pattern] =
+ if (isDefault) emptyPatterns(newArity)
+ else if (newArity == 0) Nil
+ else Predef.error("expandToArity(" + newArity + ") in " + this)
def sym = tree.symbol
- def tpe = tree.tpe
def prefix = tpe.prefix
def isEmpty = tree.isEmpty
def isSymValid = (sym != null) && (sym != NoSymbol)
def isModule = sym.isModule || tpe.termSymbol.isModule
def isCaseClass = tpe.typeSymbol hasFlag Flags.CASE
+ def caseAccessors = tpe.typeSymbol.caseFieldAccessors
def isObject = isSymValid && prefix.isStable // XXX not entire logic
def unadorn(t: Tree): Tree = Pattern unadorn t
@@ -516,7 +520,7 @@ trait Patterns extends ast.TreeDSL {
if (boundVariables.isEmpty) description
else "%s%s".format(bindingsDescription, description)
}
- def toTypeString() = "%s <: x <: %s".format(necessaryType, sufficientType)
+ def toTypeString() = "%s <: x <: %s".format(tpe, atomicTpe)
}
/*** Extractors ***/