@@ -299,30 +299,57 @@ object PatternMatcher {
299
299
}
300
300
301
301
/** Plan for matching the sequence in `getResult` against sequence elements
302
- * and a possible last varargs argument `args`.
302
+ * `args`. Sequence elements may contain a varargs argument.
303
+ * Example:
304
+ *
305
+ * lst match case Seq(1, xs*, 2, 3) => ...
306
+ *
307
+ * generates code which is equivalent to:
308
+ *
309
+ * if lst != null then
310
+ * if lst.lengthCompare >= 1 then
311
+ * if lst(0) == 1 then
312
+ * val x1 = lst.drop(1)
313
+ * val xs = x1.dropRight(2)
314
+ * val x2 = lst.takeRight(2)
315
+ * if x2.lengthCompare >= 2 then
316
+ * if x2(0) == 2 then
317
+ * if x2(1) == 3 then
318
+ * return[matchResult] ...
303
319
*/
304
- def unapplySeqPlan (getResult : Symbol , args : List [Tree ]): Plan = args.lastOption match {
305
- case Some (VarArgPattern (arg)) =>
306
- val matchRemaining =
307
- if (args.length == 1 ) {
308
- val toSeq = ref(getResult)
309
- .select(defn.Seq_toSeq .matchingMember(getResult.info))
310
- letAbstract(toSeq) { toSeqResult =>
311
- patternPlan(toSeqResult, arg, onSuccess)
312
- }
313
- }
314
- else {
315
- val dropped = ref(getResult)
316
- .select(defn.Seq_drop .matchingMember(getResult.info))
317
- .appliedTo(Literal (Constant (args.length - 1 )))
318
- letAbstract(dropped) { droppedResult =>
319
- patternPlan(droppedResult, arg, onSuccess)
320
- }
321
- }
322
- matchElemsPlan(getResult, args.init, exact = false , matchRemaining)
323
- case _ =>
324
- matchElemsPlan(getResult, args, exact = true , onSuccess)
325
- }
320
+ def unapplySeqPlan (getResult : Symbol , args : List [Tree ]): Plan =
321
+ val (leading, varargAndRest) = args.span:
322
+ case VarArgPattern (_) => false
323
+ case _ => true
324
+ varargAndRest match
325
+ case VarArgPattern (arg) :: trailing =>
326
+ val remaining =
327
+ if leading.isEmpty then
328
+ ref(getResult)
329
+ .select(defn.Seq_toSeq .matchingMember(getResult.info))
330
+ else
331
+ ref(getResult)
332
+ .select(defn.Seq_drop .matchingMember(getResult.info))
333
+ .appliedTo(Literal (Constant (leading.length)))
334
+ val matchRemaining =
335
+ letAbstract(remaining): remainingResult =>
336
+ if trailing.isEmpty then
337
+ patternPlan(remainingResult, arg, onSuccess)
338
+ else
339
+ val seq = ref(remainingResult)
340
+ .select(defn.Seq_dropRight .matchingMember(remainingResult.info))
341
+ .appliedTo(Literal (Constant (trailing.length)))
342
+ letAbstract(seq): seqResult =>
343
+ val rest = ref(remainingResult)
344
+ .select(defn.Seq_takeRight .matchingMember(remainingResult.info))
345
+ .appliedTo(Literal (Constant (trailing.length)))
346
+ val matchTrailing =
347
+ letAbstract(rest): trailingResult =>
348
+ matchElemsPlan(trailingResult, trailing, exact = true , onSuccess)
349
+ patternPlan(seqResult, arg, matchTrailing)
350
+ matchElemsPlan(getResult, leading, exact = false , matchRemaining)
351
+ case _ =>
352
+ matchElemsPlan(getResult, args, exact = true , onSuccess)
326
353
327
354
/** Plan for matching the sequence in `getResult`
328
355
*
0 commit comments