874d2a95b2ae791019dd5e1ce81ab1b94bbd4588a3799c585a78ca8ba9bc0c28c76e76842098cf15
27
  type PatternMatch       = MatchMatrix#PatternMatch
27
  type PatternMatch       = MatchMatrix#PatternMatch
28
  private type PatternVar = MatrixContext#PatternVar
28
  private type PatternVar = MatrixContext#PatternVar
29
 
29
 
 
 
30
  // private def unapplyArgs(x: Any) = x match {
 
 
31
  //   case UnApply(Apply(TypeApply(_, targs), args), _) => (targs map (_.symbol), args map (_.symbol))
 
 
32
  //   case _                                            => (Nil, Nil)
 
 
33
  // }
 
 
34
  //   
 
 
35
  // private def unapplyCall(x: Any) = x match {
 
 
36
  //   case UnApply(t, _)  => treeInfo.methPart(t).symbol
 
 
37
  //   case _              => NoSymbol
 
 
38
  // }
 
 
39
 
30
  // Fresh patterns
40
  // Fresh patterns
31
  def emptyPatterns(i: Int): List[Pattern] = List.fill(i)(NoPattern)
41
  def emptyPatterns(i: Int): List[Pattern] = List.fill(i)(NoPattern)
32
  def emptyTrees(i: Int): List[Tree] = List.fill(i)(EmptyTree)
42
  def emptyTrees(i: Int): List[Tree] = List.fill(i)(EmptyTree)
...
 
...
 
45
    val Ident(name) = tree
55
    val Ident(name) = tree
46
    require(isVarPattern(tree) && name != nme.WILDCARD)
56
    require(isVarPattern(tree) && name != nme.WILDCARD)
47
 
57
 
48
    override def irrefutableFor(tpe: Type) = true
 
 
49
    override def description = "%s".format(name)
58
    override def description = "%s".format(name)
50
  }
59
  }
51
 
60
 
52
  // 8.1.1 (b)
61
  // 8.1.1 (b)
53
  case class WildcardPattern() extends Pattern {
62
  case class WildcardPattern() extends Pattern {
54
    val tree = EmptyTree
63
    val tree = EmptyTree
55
    override def irrefutableFor(tpe: Type) = true
 
 
56
    override def isDefault = true
64
    override def isDefault = true
57
    override def description = "_"
65
    override def description = "_"
58
  }
66
  }
...
 
...
 
62
    private val Typed(expr, tpt) = tree
70
    private val Typed(expr, tpt) = tree
63
 
71
 
64
    override def subpatternsForVars: List[Pattern] = List(Pattern(expr))
72
    override def subpatternsForVars: List[Pattern] = List(Pattern(expr))
65
    
 
 
66
    override def irrefutableFor(tpe: Type) = tpe <:< tree.tpe
 
 
67
    override def simplify(pv: PatternVar) = Pattern(expr) match {
73
    override def simplify(pv: PatternVar) = Pattern(expr) match {
68
      case ExtractorPattern(ua) if pv.sym.tpe <:< tpt.tpe  => this rebindTo expr
74
      case ExtractorPattern(ua) if pv.sym.tpe <:< tpt.tpe => this rebindTo expr
69
      case _                                                => this
75
      case _                                              => this
70
    }
76
    }
71
    override def description = "Typ(%s: %s)".format(Pattern(expr), tpt)
77
    override def description = "Typ(%s: %s)".format(Pattern(expr), tpt)
72
  }
78
  }
...
 
...
 
159
      if (isColonColon) "%s :: %s".format(Pattern(args(0)), Pattern(args(1)))
165
      if (isColonColon) "%s :: %s".format(Pattern(args(0)), Pattern(args(1)))
160
      else "%s(%s)".format(name, toPats(args).mkString(", "))
166
      else "%s(%s)".format(name, toPats(args).mkString(", "))
161
    }
167
    }
162
      
 
 
163
    // XXX todo
 
 
164
    // override def irrefutableFor(tpe: Type) = false
 
 
165
  }  
168
  }  
166
  // 8.1.6
169
  // 8.1.6
167
  case class TuplePattern(tree: Apply) extends ApplyPattern {
170
  case class TuplePattern(tree: Apply) extends ApplyPattern {
168
    // XXX todo
 
 
169
    // override def irrefutableFor(tpe: Type) = false
 
 
170
    override def description = "((%s))".format(args.size, toPats(args).mkString(", "))
171
    override def description = "((%s))".format(args.size, toPats(args).mkString(", "))
171
  }
172
  }
172
 
173
 
173
  // 8.1.7
174
  // 8.1.7 / 8.1.8 (unapply and unapplySeq calls)
174
  case class ExtractorPattern(tree: UnApply) extends UnapplyPattern {
175
  case class ExtractorPattern(tree: UnApply) extends UnapplyPattern {
175
    private val Apply(fn, _) = unfn
 
 
176
    private val MethodType(List(arg, _*), _) = fn.tpe
 
 
177
    private def uaTyped = Typed(tree, TypeTree(arg.tpe)) setType arg.tpe
 
 
178
 
 
 
179
    override def necessaryType = arg.tpe
 
 
180
    
 
 
181
    override def simplify(pv: PatternVar) =
176
    override def simplify(pv: PatternVar) =
182
      if (pv.sym.tpe <:< arg.tpe) this
177
      if (pv.tpe <:< arg.tpe) this
183
      else this rebindTo uaTyped
178
      else this rebindTo uaTyped
184
      
179
 
185
    override def description = "UnApp(%s => %s)".format(necessaryType, resTypesString)
180
    override def description = "Unapply(%s => %s)".format(necessaryType, resTypesString)
186
  }
181
  }
187
 
182
 
188
  // 8.1.8 (unapplySeq calls)
183
  case class SequenceExtractorPattern(tree: UnApply, elems: List[Tree]) extends UnapplyPattern with SequenceLikePattern {
189
  case class SequenceExtractorPattern(tree: UnApply) extends UnapplyPattern with SequenceLikePattern {
184
    override def simplify(pv: PatternVar) = {
190
 
185
      pv.sym setFlag NO_EXHAUSTIVE
191
    lazy val UnApply(
186
      
192
      Apply(TypeApply(Select(_, nme.unapplySeq), List(tptArg)), _),
187
      if (pv.tpe <:< arg.tpe) this
193
      List(ArrayValue(_, elems))
188
      else this rebindTo uaTyped
194
    ) = tree
189
    }
195
 
190
 
196
    /** For folding a list into a well-typed x :: y :: etc :: tree. */
191
    override def description = "UnapplySeq(%s => %s)".format(necessaryType, resTypesString)
197
    private def listFolder = {
192
  }
198
      val tpe = tptArg.tpe
193
 
199
      val MethodType(_, TypeRef(pre, sym, _)) = ConsClass.primaryConstructor.tpe
194
  // Special List handling.  It was like that when I got here.
200
      val consRef                             = typeRef(pre, sym, List(tpe))
195
  case class ListExtractorPattern(tree: UnApply, tpt: Tree, elems: List[Tree]) extends UnapplyPattern with SequenceLikePattern {    
201
      val listRef                             = typeRef(pre, ListClass, List(tpe))
196
    private val cons    = ConsClass.primaryConstructor.tpe.resultType
202
 
197
    private val consRef = typeRef(cons.prefix, ConsClass, List(tpt.tpe))
203
      def fold(x: Tree, xs: Tree) = unbind(x) match {
198
    private val listRef = typeRef(cons.prefix, ListClass, List(tpt.tpe))
204
        case _: Star  => Pattern(x) rebindTo WILD(x.tpe) boundTree  // this is using boundVariables instead of deepBoundVariables
199
 
205
        case _        =>
200
    // Fold a list into a well-typed x :: y :: etc :: tree.
206
          val dummyMethod = new TermSymbol(NoSymbol, NoPosition, "matching$dummy")
201
    private def listFolder(x: Tree, xs: Tree) = unbind(x) match {
207
          val consType    = MethodType(dummyMethod newSyntheticValueParams List(tpe, listRef), consRef)
202
      case _: Star  => Pattern(x) rebindTo WILD(x.tpe) boundTree
208
 
203
      case _        =>
209
          Apply(TypeTree(consType), List(x, xs)) setType consRef
204
        val dummyMethod = new TermSymbol(NoSymbol, NoPosition, "matching$dummy")
210
      }
205
        val consType    = MethodType(dummyMethod newSyntheticValueParams List(tpt.tpe, listRef), consRef)
211
 
206
 
212
      fold _
207
        Apply(TypeTree(consType), List(x, xs)) setType consRef
213
    }
208
    }
214
 
209
    override def necessaryType = if (nonStarPatterns.nonEmpty) consRef else listRef
215
    // @pre: is not right-ignoring (no star pattern) ; no exhaustivity check
 
 
216
    override def simplify(pv: PatternVar) = {
210
    override def simplify(pv: PatternVar) = {
217
      pv.sym setFlag NO_EXHAUSTIVE
211
      pv.sym setFlag NO_EXHAUSTIVE
218
      this rebindTo elems.foldRight(gen.mkNil)(listFolder)
212
 
 
 
213
      if (pv.tpe <:< necessaryType)
 
 
214
        this rebindTo elems.foldRight(gen.mkNil)(listFolder)
 
 
215
      else
 
 
216
        this rebindTo (Typed(tree, TypeTree(necessaryType)) setType necessaryType)
219
    }
217
    }
220
    override def description = "UnSeq(%s => %s)".format(tptArg, resTypesString)
218
    override def description = "List(%s => %s)".format(tpt.tpe, resTypesString)
221
  }
219
  }
222
 
220
 
223
  trait SequenceLikePattern extends Pattern {
221
  trait SequenceLikePattern extends Pattern {
224
    def elems: List[Tree]
222
    def elems: List[Tree]
225
    def elemPatterns = toPats(elems)
223
    override def hasStar = elems.nonEmpty && isStar(elems.last)
226
 
 
 
227
    def nonStarPatterns: List[Pattern] = if (hasStar) elemPatterns.init else elemPatterns
 
 
228
    def nonStarLength = nonStarPatterns.length
 
 
229
    def isAllDefaults = nonStarPatterns forall (_.isDefault)
 
 
230
 
224
 
231
    def isShorter(other: SequenceLikePattern) = nonStarLength < other.nonStarLength
225
    def elemPatterns    = toPats(elems)
232
    def isSameLength(other: SequenceLikePattern) = nonStarLength == other.nonStarLength
226
    def nonStarElems    = if (hasStar) elems.init else elems
 
 
227
    def nonStarPatterns = toPats(nonStarElems)
 
 
228
    def nonStarLength   = nonStarElems.length
233
  }
229
  }
234
 
230
 
235
  // 8.1.8 (b) (literal ArrayValues)
231
  // 8.1.8 (b) (literal ArrayValues)
...
 
...
 
273
    private val cache = new collection.mutable.HashMap[Tree, Pattern]
269
    private val cache = new collection.mutable.HashMap[Tree, Pattern]
274
    def clear() = cache.clear()
270
    def clear() = cache.clear()
275
 
271
 
276
    def unadorn(x: Tree): Tree = x match {
 
 
277
      case Typed(expr, _) => unadorn(expr)
 
 
278
      case Bind(_, x)     => unadorn(x)
 
 
279
      case _              => x
 
 
280
    }
 
 
281
 
 
 
282
    def isRightIgnoring(t: Tree) = cond(unadorn(t)) {
 
 
283
      case ArrayValue(_, xs) if !xs.isEmpty => isStar(unadorn(xs.last))
 
 
284
    }
 
 
285
    
 
 
286
    def apply(tree: Tree): Pattern = {
272
    def apply(tree: Tree): Pattern = {
287
      if (cache contains tree)
273
      if (cache contains tree)
288
        return cache(tree)
274
        return cache(tree)
...
 
...
 
321
 
307
 
322
  object UnapplyPattern {
308
  object UnapplyPattern {
323
    private object UnapplySeq {
309
    private object UnapplySeq {
324
      private object TypeApp {
310
      def unapply(x: UnApply) = x match {
325
        def unapply(x: Any) = condOpt(x) { 
311
        case UnApply(
326
          case TypeApply(sel @ Select(stor, nme.unapplySeq), List(tpe)) if stor.symbol eq ListModule => tpe
312
        Apply(TypeApply(Select(qual, nme.unapplySeq), List(tpt)), _),
327
        }
313
        List(ArrayValue(_, elems))) =>
328
      }
314
          Some(qual.symbol, tpt, elems)
329
      def unapply(x: UnApply) = condOpt(x) {
315
        case _ =>
330
        case UnApply(Apply(TypeApp(tptArg), _), List(ArrayValue(_, xs))) => (tptArg, xs)
316
          None
331
      }
317
       }
332
    }
318
    }
333
 
319
 
334
    def apply(x: UnApply): Pattern = {
320
    def apply(x: UnApply): Pattern = x match {
335
      x match {
321
      case UnapplySeq(container, tpt, elems) =>
336
        case UnapplySeq(_, _) => SequenceExtractorPattern(x)
322
        if (container == ListModule) ListExtractorPattern(x, tpt, elems)
337
        case _                => ExtractorPattern(x)
323
        else SequenceExtractorPattern(x, elems)
338
      }
324
      case _ =>
 
 
325
        ExtractorPattern(x)
339
    }
326
    }
340
  }
327
  }
341
 
328
 
...
 
...
 
401
 
388
 
402
  sealed trait UnapplyPattern extends Pattern {
389
  sealed trait UnapplyPattern extends Pattern {
403
    lazy val UnApply(unfn, args) = tree
390
    lazy val UnApply(unfn, args) = tree
404
    override def subpatternsForVars: List[Pattern] = toPats(args)
391
    lazy val Apply(fn, _) = unfn
 
 
392
    lazy val MethodType(List(arg, _*), _) = fn.tpe
 
 
393
    protected def uaTyped = Typed(tree, TypeTree(arg.tpe)) setType arg.tpe
 
 
394
    
 
 
395
    override def necessaryType = arg.tpe
 
 
396
    override def subpatternsForVars = args match {
 
 
397
      case List(ArrayValue(elemtpe, elems)) => toPats(elems)
 
 
398
      case _                                => toPats(args)
 
 
399
    }
405
 
400
 
406
    def resTypes = analyzer.unapplyTypeList(unfn.symbol, unfn.tpe)
401
    def resTypes = analyzer.unapplyTypeList(unfn.symbol, unfn.tpe)
407
    def resTypesString = resTypes match {
402
    def resTypesString = resTypes match {
...
 
...
 
433
 
428
 
434
    // returns either a simplification of this pattern or identity.
429
    // returns either a simplification of this pattern or identity.
435
    def simplify(pv: PatternVar): Pattern = this
430
    def simplify(pv: PatternVar): Pattern = this
436
    def simplify(): Pattern = this simplify null
 
 
437
 
431
 
438
    // the right number of dummies for this pattern
432
    // the right number of dummies for this pattern
439
    def dummies: List[Pattern] = Nil
433
    def dummies: List[Pattern] = Nil
440
 
434
 
441
    // 8.1.13
 
 
442
    // A pattern p is irrefutable for type T if any of the following applies:
 
 
443
    //   1) p is a variable pattern
 
 
444
    //   2) p is a typed pattern x: T', and T <: T'
 
 
445
    //   3) p is a constructor pattern C(p1,...,pn), the type T is an instance of class C,
 
 
446
    //      the primary constructor of type T has argument types T1,...,Tn and and each
 
 
447
    //      pi is irrefutable for Ti.
 
 
448
    def irrefutableFor(tpe: Type) = false
 
 
449
    
 
 
450
    // does this pattern completely cover that pattern (i.e. latter cannot be matched)
 
 
451
    def completelyCovers(second: Pattern) = false
 
 
452
    
 
 
453
    // Is this a default pattern (untyped "_" or an EmptyTree inserted by the matcher)
435
    // Is this a default pattern (untyped "_" or an EmptyTree inserted by the matcher)
454
    def isDefault = false
436
    def isDefault = false
455
 
437
 
...
 
...
 
460
    // (nullness and guards will still be checked.)
442
    // (nullness and guards will still be checked.)
461
    def sufficientType = tpe
443
    def sufficientType = tpe
462
 
444
 
463
    // XXX have to determine if this can be made useful beyond an extractor barrier.
 
 
464
    // Default sufficient type might be NothingClass.tpe, tpe.narrow, ...
 
 
465
    
 
 
466
    // the subpatterns for this pattern (at the moment, that means constructor arguments)
445
    // the subpatterns for this pattern (at the moment, that means constructor arguments)
467
    def subpatterns(pm: MatchMatrix#PatternMatch): List[Pattern] = pm.dummies
446
    def subpatterns(pm: MatchMatrix#PatternMatch): List[Pattern] = pm.dummies
468
 
447
 
469
    def    sym  = tree.symbol
448
    def    sym  = tree.symbol
470
    def    tpe  = tree.tpe
449
    def    tpe  = tree.tpe
471
    def prefix  = tpe.prefix
 
 
472
    def isEmpty = tree.isEmpty
450
    def isEmpty = tree.isEmpty
473
 
451
 
474
    def isSymValid = (sym != null) && (sym != NoSymbol)
452
    def isModule    = sym.isModule || tpe.termSymbol.isModule
475
    def isModule = sym.isModule || tpe.termSymbol.isModule
 
 
476
    def isCaseClass = tpe.typeSymbol.isCase
453
    def isCaseClass = tpe.typeSymbol.isCase
477
    def isObject = isSymValid && prefix.isStable  // XXX not entire logic
454
    def isObject    = (sym != null) && (sym != NoSymbol) && tpe.prefix.isStable  // XXX not entire logic
478
    
 
 
479
    def unadorn(t: Tree): Tree = Pattern unadorn t
 
 
480
    
 
 
481
    private def isStar(x: Tree) = cond(unadorn(x)) { case Star(_) => true }
 
 
482
    private def endsStar(xs: List[Tree]) = xs.nonEmpty && isStar(xs.last)
 
 
483
 
455
 
484
    def isStarSequence = isSequence && hasStar
456
    def hasStar = false
485
    def isSequence = cond(unadorn(tree)) {
 
 
486
      case ArrayValue(_, _) => true
 
 
487
    }
 
 
488
    def hasStar = cond(unadorn(tree)) {
 
 
489
      case ArrayValue(_, xs) if endsStar(xs)  => true
 
 
490
    }
 
 
491
 
457
 
492
    def setType(tpe: Type): this.type = {
458
    def setType(tpe: Type): this.type = {
493
      tree setType tpe
459
      tree setType tpe