@@ -299,30 +299,57 @@ object PatternMatcher {
299299 }
300300
301301 /** 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] ...
303319 */
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)
326353
327354 /** Plan for matching the sequence in `getResult`
328355 *
0 commit comments