Skip to content

Commit

Permalink
Add reverse method to NonEmptyTuple
Browse files Browse the repository at this point in the history
  • Loading branch information
danicheg committed Oct 15, 2021
1 parent 0967522 commit 3e3f57b
Show file tree
Hide file tree
Showing 4 changed files with 226 additions and 0 deletions.
14 changes: 14 additions & 0 deletions library/src/scala/Tuple.scala
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,14 @@ object Tuple {
*/
type IsMappedBy[F[_]] = [X <: Tuple] =>> X =:= Map[InverseMap[X, F], F]

/** Type of the reversed tuple */
@experimental
type Reverse[X <: Tuple] <: Tuple = X match {
case EmptyTuple => EmptyTuple
case x *: xs =>
Concat[Reverse[xs], x *: EmptyTuple]
}

/** Transforms a tuple `(T1, ..., Tn)` into `(T1, ..., Ti)`. */
type Take[T <: Tuple, N <: Int] <: Tuple = N match {
case 0 => EmptyTuple
Expand Down Expand Up @@ -301,6 +309,12 @@ sealed trait NonEmptyTuple extends Tuple {
inline def tail[This >: this.type <: NonEmptyTuple]: Tail[This] =
runtime.Tuples.tail(this).asInstanceOf[Tail[This]]

/** Given a tuple `(a1, ..., am)`, returns the reversed tuple `(am, ..., a1)`
* consisting all its elements.
*/
@experimental
inline def reverse[This >: this.type <: NonEmptyTuple]: Reverse[This] =
runtime.Tuples.reverse(this).asInstanceOf[Reverse[This]]
}

@showAsInfix
Expand Down
70 changes: 70 additions & 0 deletions library/src/scala/runtime/Tuples.scala
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,76 @@ object Tuples {
}
}

// Reverse for TupleXXL
private def xxlReverse(xxl: TupleXXL): Tuple = {
if (xxl.productArity == 22) {
val elems = xxl.elems
Tuple22(
elems(21), elems(20), elems(19), elems(18), elems(17), elems(16),
elems(15), elems(14), elems(13), elems(12), elems(11), elems(10),
elems(9), elems(8), elems(7), elems(6), elems(5), elems(4),
elems(3), elems(2), elems(1), elems(0)
)
} else {
TupleXXL.fromIArray(xxl.elems.reverse.asInstanceOf[IArray[Object]]).asInstanceOf[Tuple]
}
}

// Reverse for Tuple1 to Tuple22
private def specialCaseReverse(self: Tuple): Tuple = {
(self: Any) match {
case self: Tuple1[_] =>
self
case self: Tuple2[_, _] =>
Tuple2(self._2, self._1)
case self: Tuple3[_, _, _] =>
Tuple3(self._3, self._2, self._1)
case self: Tuple4[_, _, _, _] =>
Tuple4(self._4, self._3, self._2, self._1)
case self: Tuple5[_, _, _, _, _] =>
Tuple5(self._5, self._4, self._3, self._2, self._1)
case self: Tuple6[_, _, _, _, _, _] =>
Tuple6(self._6, self._5, self._4, self._3, self._2, self._1)
case self: Tuple7[_, _, _, _, _, _, _] =>
Tuple7(self._7, self._6, self._5, self._4, self._3, self._2, self._1)
case self: Tuple8[_, _, _, _, _, _, _, _] =>
Tuple8(self._8, self._7, self._6, self._5, self._4, self._3, self._2, self._1)
case self: Tuple9[_, _, _, _, _, _, _, _, _] =>
Tuple9(self._9, self._8, self._7, self._6, self._5, self._4, self._3, self._2, self._1)
case self: Tuple10[_, _, _, _, _, _, _, _, _, _] =>
Tuple10(self._10, self._9, self._8, self._7, self._6, self._5, self._4, self._3, self._2, self._1)
case self: Tuple11[_, _, _, _, _, _, _, _, _, _, _] =>
Tuple11(self._11, self._10, self._9, self._8, self._7, self._6, self._5, self._4, self._3, self._2, self._1)
case self: Tuple12[_, _, _, _, _, _, _, _, _, _, _, _] =>
Tuple12(self._12, self._11, self._10, self._9, self._8, self._7, self._6, self._5, self._4, self._3, self._2, self._1)
case self: Tuple13[_, _, _, _, _, _, _, _, _, _, _, _, _] =>
Tuple13(self._13, self._12, self._11, self._10, self._9, self._8, self._7, self._6, self._5, self._4, self._3, self._2, self._1)
case self: Tuple14[_, _, _, _, _, _, _, _, _, _, _, _, _, _] =>
Tuple14(self._14, self._13, self._12, self._11, self._10, self._9, self._8, self._7, self._6, self._5, self._4, self._3, self._2, self._1)
case self: Tuple15[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _] =>
Tuple15(self._15, self._14, self._13, self._12, self._11, self._10, self._9, self._8, self._7, self._6, self._5, self._4, self._3, self._2, self._1)
case self: Tuple16[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] =>
Tuple16(self._16, self._15, self._14, self._13, self._12, self._11, self._10, self._9, self._8, self._7, self._6, self._5, self._4, self._3, self._2, self._1)
case self: Tuple17[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] =>
Tuple17(self._17, self._16, self._15, self._14, self._13, self._12, self._11, self._10, self._9, self._8, self._7, self._6, self._5, self._4, self._3, self._2, self._1)
case self: Tuple18[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] =>
Tuple18(self._18, self._17, self._16, self._15, self._14, self._13, self._12, self._11, self._10, self._9, self._8, self._7, self._6, self._5, self._4, self._3, self._2, self._1)
case self: Tuple19[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] =>
Tuple19(self._19, self._18, self._17, self._16, self._15, self._14, self._13, self._12, self._11, self._10, self._9, self._8, self._7, self._6, self._5, self._4, self._3, self._2, self._1)
case self: Tuple20[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] =>
Tuple20(self._20, self._19, self._18, self._17, self._16, self._15, self._14, self._13, self._12, self._11, self._10, self._9, self._8, self._7, self._6, self._5, self._4, self._3, self._2, self._1)
case self: Tuple21[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] =>
Tuple21(self._21, self._20, self._19, self._18, self._17, self._16, self._15, self._14, self._13, self._12, self._11, self._10, self._9, self._8, self._7, self._6, self._5, self._4, self._3, self._2, self._1)
case self: Tuple22[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] =>
Tuple22(self._22, self._21, self._20, self._19, self._18, self._17, self._16, self._15, self._14, self._13, self._12, self._11, self._10, self._9, self._8, self._7, self._6, self._5, self._4, self._3, self._2, self._1)
}
}

def reverse(self: NonEmptyTuple): Tuple = (self: Any) match {
case xxl: TupleXXL => xxlReverse(xxl)
case _ => specialCaseReverse(self)
}

// Init for Tuple1 to Tuple22
private def specialCaseInit(self: Tuple): Tuple = {
(self: Any) match {
Expand Down
76 changes: 76 additions & 0 deletions tests/run-deep-subtype/Tuple-reverse.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
(0)
(0,0)
(1,0,0)
(2,1,0,0)
(3,2,1,0,0)
(4,3,2,1,0,0)
(5,4,3,2,1,0,0)
(6,5,4,3,2,1,0,0)
(7,6,5,4,3,2,1,0,0)
(8,7,6,5,4,3,2,1,0,0)
(9,8,7,6,5,4,3,2,1,0,0)
(10,9,8,7,6,5,4,3,2,1,0,0)
(11,10,9,8,7,6,5,4,3,2,1,0,0)
(12,11,10,9,8,7,6,5,4,3,2,1,0,0)
(13,12,11,10,9,8,7,6,5,4,3,2,1,0,0)
(14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,0)
(15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,0)
(16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,0)
(17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,0)
(18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,0)
(19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,0)
(20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,0)
(21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,0)
(22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,0)
(23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,0)
(24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,0)
(1)
(2,1)
(3,2,1)
(4,3,2,1)
(5,4,3,2,1)
(6,5,4,3,2,1)
(7,6,5,4,3,2,1)
(8,7,6,5,4,3,2,1)
(9,8,7,6,5,4,3,2,1)
(10,9,8,7,6,5,4,3,2,1)
(11,10,9,8,7,6,5,4,3,2,1)
(12,11,10,9,8,7,6,5,4,3,2,1)
(13,12,11,10,9,8,7,6,5,4,3,2,1)
(14,13,12,11,10,9,8,7,6,5,4,3,2,1)
(15,14,13,12,11,10,9,8,7,6,5,4,3,2,1)
(16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1)
(17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1)
(18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1)
(19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1)
(20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1)
(21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1)
(22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1)
(23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1)
(24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1)
(25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1)
(1)
(2,1)
(3,2,1)
(4,3,2,1)
(5,4,3,2,1)
(6,5,4,3,2,1)
(7,6,5,4,3,2,1)
(8,7,6,5,4,3,2,1)
(9,8,7,6,5,4,3,2,1)
(10,9,8,7,6,5,4,3,2,1)
(11,10,9,8,7,6,5,4,3,2,1)
(12,11,10,9,8,7,6,5,4,3,2,1)
(13,12,11,10,9,8,7,6,5,4,3,2,1)
(14,13,12,11,10,9,8,7,6,5,4,3,2,1)
(15,14,13,12,11,10,9,8,7,6,5,4,3,2,1)
(16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1)
(17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1)
(18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1)
(19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1)
(20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1)
(21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1)
(22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1)
(23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1)
(24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1)
(25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1)
66 changes: 66 additions & 0 deletions tests/run-deep-subtype/Tuple-reverse.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import scala.reflect.ClassTag

object Test {
def main(args: Array[String]): Unit = {

def testArray[T: ClassTag](n: Int, elem: Int => T): Unit = {
val t: Int *: Tuple = 0 *: Tuple.fromArray(Array.tabulate(n)(elem))
println(t.reverse)
}

for (i <- 0 to 25)
testArray(i, j => j)

println(Tuple1(1).reverse)
println((1, 2).reverse)
println((1, 2, 3).reverse)
println((1, 2, 3, 4).reverse)
println((1, 2, 3, 4, 5).reverse)
println((1, 2, 3, 4, 5, 6).reverse)
println((1, 2, 3, 4, 5, 6, 7).reverse)
println((1, 2, 3, 4, 5, 6, 7, 8).reverse)
println((1, 2, 3, 4, 5, 6, 7, 8, 9).reverse)
println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10).reverse)
println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11).reverse)
println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12).reverse)
println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13).reverse)
println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14).reverse)
println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15).reverse)
println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16).reverse)
println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17).reverse)
println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18).reverse)
println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19).reverse)
println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20).reverse)
println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21).reverse)
println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22).reverse)
println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23).reverse)
println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24).reverse)
println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25).reverse)

println((1 *: Tuple()).reverse)
println((1 *: 2 *: Tuple()).reverse)
println((1 *: 2 *: 3 *: Tuple()).reverse)
println((1 *: 2 *: 3 *: 4 *: Tuple()).reverse)
println((1 *: 2 *: 3 *: 4 *: 5 *: Tuple()).reverse)
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: Tuple()).reverse)
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: Tuple()).reverse)
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: Tuple()).reverse)
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: Tuple()).reverse)
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: Tuple()).reverse)
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: Tuple()).reverse)
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: Tuple()).reverse)
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: Tuple()).reverse)
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: Tuple()).reverse)
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: 15 *: Tuple()).reverse)
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: 15 *: 16 *: Tuple()).reverse)
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: 15 *: 16 *: 17 *: Tuple()).reverse)
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: 15 *: 16 *: 17 *: 18 *: Tuple()).reverse)
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: 15 *: 16 *: 17 *: 18 *: 19 *: Tuple()).reverse)
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: 15 *: 16 *: 17 *: 18 *: 19 *: 20 *: Tuple()).reverse)
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: 15 *: 16 *: 17 *: 18 *: 19 *: 20 *: 21 *: Tuple()).reverse)
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: 15 *: 16 *: 17 *: 18 *: 19 *: 20 *: 21 *: 22 *: Tuple()).reverse)
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: 15 *: 16 *: 17 *: 18 *: 19 *: 20 *: 21 *: 22 *: 23 *: Tuple()).reverse)
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: 15 *: 16 *: 17 *: 18 *: 19 *: 20 *: 21 *: 22 *: 23 *: 24 *: Tuple()).reverse)
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: 15 *: 16 *: 17 *: 18 *: 19 *: 20 *: 21 *: 22 *: 23 *: 24 *: 25 *: Tuple()).reverse)
}
}

0 comments on commit 3e3f57b

Please sign in to comment.