874d2a95b2ae791019dd5e1ce81ab1b94bbd4588 | a3799c585a78ca8ba9bc0c28c76e76842098cf15 | ||
---|---|---|---|
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 |