diff --git a/library/src/scala/Tuple.scala b/library/src-bootstrapped/scala/Tuple.scala similarity index 100% rename from library/src/scala/Tuple.scala rename to library/src-bootstrapped/scala/Tuple.scala diff --git a/library/src/scala/deriving.scala b/library/src-bootstrapped/scala/deriving.scala similarity index 100% rename from library/src/scala/deriving.scala rename to library/src-bootstrapped/scala/deriving.scala diff --git a/library/src/scala/runtime/Tuple.scala b/library/src-bootstrapped/scala/runtime/Tuple.scala similarity index 100% rename from library/src/scala/runtime/Tuple.scala rename to library/src-bootstrapped/scala/runtime/Tuple.scala diff --git a/library/src-non-bootstrapped/scala/Tuple.scala b/library/src-non-bootstrapped/scala/Tuple.scala new file mode 100644 index 000000000000..e1a24ab83849 --- /dev/null +++ b/library/src-non-bootstrapped/scala/Tuple.scala @@ -0,0 +1,217 @@ +package scala +import annotation.showAsInfix +import compiletime._ +import internal._ + +// non-bootstrapped + +/** Tuple of arbitrary arity */ +sealed trait Tuple extends Any { + import Tuple._ + + /** Create a copy this tuple as an Array */ + inline def toArray: Array[Object] = + scala.runtime.Tuple.toArray(this) + + /** Create a copy this tuple as an IArray */ + inline def toIArray: IArray[Object] = + scala.runtime.Tuple.toIArray(this) + + /** Return a new tuple by prepending the element to `this` tuple. + * This operation is O(this.size) + */ + inline def *: [H, This >: this.type <: Tuple] (x: H): H *: This = + scala.runtime.Tuple.cons(x, this).asInstanceOf[H *: This] + + /** Return a new tuple by concatenating `this` tuple with `that` tuple. + * This operation is O(this.size + that.size) + */ + inline def ++ [This >: this.type <: Tuple](that: Tuple): Concat[This, that.type] = + scala.runtime.Tuple.concat(this, that).asInstanceOf[Concat[This, that.type]] + + /** Return the size (or arity) of the tuple */ + inline def size[This >: this.type <: Tuple]: Size[This] = + scala.runtime.Tuple.size(this).asInstanceOf[Size[This]] + + /** Given two tuples, `(a1, ..., an)` and `(a1, ..., an)`, returns a tuple + * `((a1, b1), ..., (an, bn))`. If the two tuples have different sizes, + * the extra elements of the larger tuple will be disregarded. + * The result is typed as `((A1, B1), ..., (An, Bn))` if at least one of the + * tuple types has a `Unit` tail. Otherwise the result type is + * `(A1, B1) *: ... *: (Ai, Bi) *: Tuple` + */ + inline def zip[This >: this.type <: Tuple, T2 <: Tuple](t2: T2): Zip[This, T2] = + scala.runtime.Tuple.zip(this, t2).asInstanceOf[Zip[This, T2]] + + /** Called on a tuple `(a1, ..., an)`, returns a new tuple `(f(a1), ..., f(an))`. + * The result is typed as `(F[A1], ..., F[An])` if the tuple type is fully known. + * If the tuple is of the form `a1 *: ... *: Tuple` (that is, the tail is not known + * to be the cons type. + */ + inline def map[F[_]](f: [t] => t => F[t]): Map[this.type, F] = + scala.runtime.Tuple.map(this, f).asInstanceOf[Map[this.type, F]] + + /** Given a tuple `(a1, ..., am)`, returns the tuple `(a1, ..., an)` consisting + * of its first n elements. + */ + inline def take[This >: this.type <: Tuple](n: Int): Take[This, n.type] = + scala.runtime.Tuple.take(this, n).asInstanceOf[Take[This, n.type]] + + + /** Given a tuple `(a1, ..., am)`, returns the tuple `(an+1, ..., am)` consisting + * all its elements except the first n ones. + */ + inline def drop[This >: this.type <: Tuple](n: Int): Drop[This, n.type] = + scala.runtime.Tuple.drop(this, n).asInstanceOf[Drop[This, n.type]] + + /** Given a tuple `(a1, ..., am)`, returns a pair of the tuple `(a1, ..., an)` + * consisting of the first n elements, and the tuple `(an+1, ..., am)` consisting + * of the remaining elements. + */ + inline def splitAt[This >: this.type <: Tuple](n: Int): Split[This, n.type] = + scala.runtime.Tuple.splitAt(this, n).asInstanceOf[Split[This, n.type]] +} + +object Tuple { + + /** Type of the head of a tuple */ + type Head[X <: NonEmptyTuple] = X match { + case x *: _ => x + } + + /** Type of the tail of a tuple */ + type Tail[X <: NonEmptyTuple] <: Tuple = X match { + case _ *: xs => xs + } + + /** Type of the concatenation of two tuples */ + type Concat[X <: Tuple, +Y <: Tuple] <: Tuple = X match { + case Unit => Y + case x1 *: xs1 => x1 *: Concat[xs1, Y] + } + + /** Type of the element a position N in the tuple X */ + type Elem[X <: Tuple, N <: Int] = X match { + case x *: xs => + N match { + case 0 => x + case S[n1] => Elem[xs, n1] + } + } + + /** Literal constant Int size of a tuple */ + type Size[X <: Tuple] <: Int = X match { + case Unit => 0 + case x *: xs => S[Size[xs]] + } + + /** Converts a tuple `(T1, ..., Tn)` to `(F[T1], ..., F[Tn])` */ + type Map[Tup <: Tuple, F[_]] <: Tuple = Tup match { + case Unit => Unit + case h *: t => F[h] *: Map[t, F] + } + + /** Given two tuples, `A1 *: ... *: An * At` and `B1 *: ... *: Bn *: Bt` + * where at least one of `At` or `Bt` is `Unit` or `Tuple`, + * returns the tuple type `(A1, B1) *: ... *: (An, Bn) *: Ct` + * where `Ct` is `Unit` if `At` or `Bt` is `Unit`, otherwise `Ct` is `Tuple`. + */ + type Zip[T1 <: Tuple, T2 <: Tuple] <: Tuple = (T1, T2) match { + case (h1 *: t1, h2 *: t2) => (h1, h2) *: Zip[t1, t2] + case (Unit, _) => Unit + case (_, Unit) => Unit + case _ => Tuple + } + + /** Converts a tuple `(F[T1], ..., F[Tn])` to `(T1, ... Tn)` */ + type InverseMap[X <: Tuple, F[_]] <: Tuple = X match { + case F[x] *: t => x *: InverseMap[t, F] + case Unit => Unit + } + + /** Implicit evidence. IsMappedBy[F][X] is present in the implicit scope iff + * X is a tuple for which each element's type is constructed via `F`. E.g. + * (F[A1], ..., F[An]), but not `(F[A1], B2, ..., F[An])` where B2 does not + * have the shape of `F[A]`. + */ + type IsMappedBy[F[_]] = [X <: Tuple] =>> X =:= Map[InverseMap[X, F], F] + + /** Transforms a tuple `(T1, ..., Tn)` into `(T1, ..., Ti)`. */ + type Take[T <: Tuple, N <: Int] <: Tuple = N match { + case 0 => Unit + case S[n1] => T match { + case Unit => Unit + case x *: xs => x *: Take[xs, n1] + } + } + + /** Transforms a tuple `(T1, ..., Tn)` into `(Ti+1, ..., Tn)`. */ + type Drop[T <: Tuple, N <: Int] <: Tuple = N match { + case 0 => T + case S[n1] => T match { + case Unit => Unit + case x *: xs => Drop[xs, n1] + } + } + + /** Splits a tuple (T1, ..., Tn) into a pair of two tuples `(T1, ..., Ti)` and + * `(Ti+1, ..., Tn)`. + */ + type Split[T <: Tuple, N <: Int] = (Take[T, N], Drop[T, N]) + + /** Convert an array into a tuple of unknown arity and types */ + def fromArray[T](xs: Array[T]): Tuple = { + val xs2 = xs match { + case xs: Array[Object] => xs + case xs => xs.map(_.asInstanceOf[Object]) + } + scala.runtime.Tuple.fromArray(xs2).asInstanceOf[Tuple] + } + + /** Convert an immutable array into a tuple of unknown arity and types */ + def fromIArray[T](xs: IArray[T]): Tuple = { + val xs2: IArray[Object] = xs match { + case xs: IArray[Object] => xs + case xs => + // TODO support IArray.map + xs.asInstanceOf[Array[T]].map(_.asInstanceOf[Object]).asInstanceOf[IArray[Object]] + } + scala.runtime.Tuple.fromIArray(xs2).asInstanceOf[Tuple] + } + + /** Convert a Product into a tuple of unknown arity and types */ + def fromProduct(product: Product): Tuple = + scala.runtime.Tuple.fromProduct(product) + + def fromProductTyped[P <: Product](p: P)(using m: scala.deriving.Mirror.ProductOf[P]): m.MirroredElemTypes = + Tuple.fromArray(p.productIterator.toArray).asInstanceOf[m.MirroredElemTypes] // TODO use toIArray of Object to avoid double/triple array copy +} + +/** Tuple of arbitrary non-zero arity */ +sealed trait NonEmptyTuple extends Tuple with Product { + import Tuple._ + + /** Get the i-th element of this tuple. + * Equivalent to productElement but with a precise return type. + */ + inline def apply[This >: this.type <: NonEmptyTuple](n: Int): Elem[This, n.type] = + scala.runtime.Tuple.apply(this, n).asInstanceOf[Elem[This, n.type]] + + /** Get the head of this tuple */ + inline def head[This >: this.type <: NonEmptyTuple]: Head[This] = + scala.runtime.Tuple.apply(this, 0).asInstanceOf[Head[This]] + + /** Get the tail of this tuple. + * This operation is O(this.size) + */ + inline def tail[This >: this.type <: NonEmptyTuple]: Tail[This] = + scala.runtime.Tuple.tail(this).asInstanceOf[Tail[This]] + +} + +@showAsInfix +sealed abstract class *:[+H, +T <: Tuple] extends NonEmptyTuple + +object *: { + def unapply[H, T <: Tuple](x: H *: T): (H, T) = (x.head, x.tail) +} diff --git a/library/src-non-bootstrapped/scala/deriving.scala b/library/src-non-bootstrapped/scala/deriving.scala new file mode 100644 index 000000000000..ddb7ec33a8c5 --- /dev/null +++ b/library/src-non-bootstrapped/scala/deriving.scala @@ -0,0 +1,74 @@ +package scala + +// non bootstrapped + +object deriving { + + /** Mirrors allows typelevel access to enums, case classes and objects, and their sealed parents. + */ + sealed trait Mirror { + + /** The mirrored *-type */ + type MirroredMonoType + + /** The name of the type */ + type MirroredLabel <: String + + /** The names of the product elements */ + type MirroredElemLabels <: Tuple + } + + object Mirror { + + /** The Mirror for a sum type */ + trait Sum extends Mirror { self => + /** The ordinal number of the case class of `x`. For enums, `ordinal(x) == x.ordinal` */ + def ordinal(x: MirroredMonoType): Int + } + + /** The Mirror for a product type */ + trait Product extends Mirror { + + /** Create a new instance of type `T` with elements taken from product `p`. */ + def fromProduct(p: scala.Product): MirroredMonoType + } + + trait Singleton extends Product { + type MirroredMonoType = this.type + type MirroredType = this.type + type MirroredElemTypes = Unit + type MirroredElemLabels = Unit + def fromProduct(p: scala.Product) = this + } + + /** A proxy for Scala 2 singletons, which do not inherit `Singleton` directly */ + class SingletonProxy(val value: AnyRef) extends Product { + type MirroredMonoType = value.type + type MirroredType = value.type + type MirroredElemTypes = Unit + type MirroredElemLabels = Unit + def fromProduct(p: scala.Product) = value + } + + type Of[T] = Mirror { type MirroredType = T; type MirroredMonoType = T ; type MirroredElemTypes <: Tuple } + type ProductOf[T] = Mirror.Product { type MirroredType = T; type MirroredMonoType = T ; type MirroredElemTypes <: Tuple } + type SumOf[T] = Mirror.Sum { type MirroredType = T; type MirroredMonoType = T; type MirroredElemTypes <: Tuple } + } + + /** Helper class to turn arrays into products */ + class ArrayProduct(val elems: Array[AnyRef]) extends Product { + def this(size: Int) = this(new Array[AnyRef](size)) + def canEqual(that: Any): Boolean = true + def productElement(n: Int) = elems(n) + def productArity = elems.length + override def productIterator: Iterator[Any] = elems.iterator + def update(n: Int, x: Any) = elems(n) = x.asInstanceOf[AnyRef] + } + + /** The empty product */ + object EmptyProduct extends ArrayProduct(Array.emptyObjectArray) + + /** Helper method to select a product element */ + def productElement[T](x: Any, idx: Int) = + x.asInstanceOf[Product].productElement(idx).asInstanceOf[T] +} diff --git a/library/src-non-bootstrapped/scala/runtime/Tuple.scala b/library/src-non-bootstrapped/scala/runtime/Tuple.scala new file mode 100644 index 000000000000..01623439412e --- /dev/null +++ b/library/src-non-bootstrapped/scala/runtime/Tuple.scala @@ -0,0 +1,468 @@ +package scala.runtime + +// non-bootstrapped + +object Tuple { + + inline val MaxSpecialized = 22 + + def toArray(self: Tuple): Array[Object] = (self: Any) match { + case self: TupleXXL => self.toArray + case self: Product => productToArray(self) + case self: Unit => Array.emptyObjectArray + } + + def toIArray(self: Tuple): IArray[Object] = (self: Any) match { + case self: TupleXXL => self.elems + case self: Product => productToArray(self).asInstanceOf[IArray[Object]] + case self: Unit => Array.emptyObjectArray.asInstanceOf[IArray[Object]] + } + + def productToArray(self: Product): Array[Object] = { + val arr = new Array[Object](self.productArity) + var i = 0 + while (i < arr.length) { + arr(i) = self.productElement(i).asInstanceOf[Object] + i += 1 + } + arr + } + + def fromArray(xs: Array[Object]): Tuple = xs.length match { + case 0 => () + case 1 => Tuple1(xs(0)) + case 2 => Tuple2(xs(0), xs(1)) + case 3 => Tuple3(xs(0), xs(1), xs(2)) + case 4 => Tuple4(xs(0), xs(1), xs(2), xs(3)) + case 5 => Tuple5(xs(0), xs(1), xs(2), xs(3), xs(4)) + case 6 => Tuple6(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5)) + case 7 => Tuple7(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6)) + case 8 => Tuple8(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7)) + case 9 => Tuple9(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7), xs(8)) + case 10 => Tuple10(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7), xs(8), xs(9)) + case 11 => Tuple11(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7), xs(8), xs(9), xs(10)) + case 12 => Tuple12(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7), xs(8), xs(9), xs(10), xs(11)) + case 13 => Tuple13(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7), xs(8), xs(9), xs(10), xs(11), xs(12)) + case 14 => Tuple14(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7), xs(8), xs(9), xs(10), xs(11), xs(12), xs(13)) + case 15 => Tuple15(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7), xs(8), xs(9), xs(10), xs(11), xs(12), xs(13), xs(14)) + case 16 => Tuple16(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7), xs(8), xs(9), xs(10), xs(11), xs(12), xs(13), xs(14), xs(15)) + case 17 => Tuple17(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7), xs(8), xs(9), xs(10), xs(11), xs(12), xs(13), xs(14), xs(15), xs(16)) + case 18 => Tuple18(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7), xs(8), xs(9), xs(10), xs(11), xs(12), xs(13), xs(14), xs(15), xs(16), xs(17)) + case 19 => Tuple19(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7), xs(8), xs(9), xs(10), xs(11), xs(12), xs(13), xs(14), xs(15), xs(16), xs(17), xs(18)) + case 20 => Tuple20(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7), xs(8), xs(9), xs(10), xs(11), xs(12), xs(13), xs(14), xs(15), xs(16), xs(17), xs(18), xs(19)) + case 21 => Tuple21(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7), xs(8), xs(9), xs(10), xs(11), xs(12), xs(13), xs(14), xs(15), xs(16), xs(17), xs(18), xs(19), xs(20)) + case 22 => Tuple22(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7), xs(8), xs(9), xs(10), xs(11), xs(12), xs(13), xs(14), xs(15), xs(16), xs(17), xs(18), xs(19), xs(20), xs(21)) + case _ => TupleXXL.fromIArray(xs.clone().asInstanceOf[IArray[Object]]).asInstanceOf[Tuple] + } + + def fromIArray(xs: IArray[Object]): Tuple = + if (xs.length <= 22) fromArray(xs.asInstanceOf[Array[Object]]) + else TupleXXL.fromIArray(xs).asInstanceOf[Tuple] + + def fromProduct(xs: Product): Tuple = (xs.productArity match { + case 1 => + xs match { + case xs: Tuple1[_] => xs + case xs => Tuple1(xs.productElement(0)) + } + case 2 => + xs match { + case xs: Tuple2[_, _] => xs + case xs => Tuple2(xs.productElement(0), xs.productElement(1)) + } + case 3 => + xs match { + case xs: Tuple3[_, _, _] => xs + case xs => Tuple3(xs.productElement(0), xs.productElement(1), xs.productElement(2)) + } + case 4 => + xs match { + case xs: Tuple4[_, _, _, _] => xs + case xs => Tuple4(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3)) + } + case 5 => + xs match { + case xs: Tuple5[_, _, _, _, _] => xs + case xs => Tuple5(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3), xs.productElement(4)) + } + case 6 => + xs match { + case xs: Tuple6[_, _, _, _, _, _] => xs + case xs => Tuple6(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3), xs.productElement(4), xs.productElement(5)) + } + case 7 => + xs match { + case xs: Tuple7[_, _, _, _, _, _, _] => xs + case xs => Tuple7(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3), xs.productElement(4), xs.productElement(5), xs.productElement(6)) + } + case 8 => + xs match { + case xs: Tuple8[_, _, _, _, _, _, _, _] => xs + case xs => Tuple8(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3), xs.productElement(4), xs.productElement(5), xs.productElement(6), xs.productElement(7)) + } + case 9 => + xs match { + case xs: Tuple9[_, _, _, _, _, _, _, _, _] => xs + case xs => Tuple9(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3), xs.productElement(4), xs.productElement(5), xs.productElement(6), xs.productElement(7), xs.productElement(8)) + } + case 10 => + xs match { + case xs: Tuple10[_, _, _, _, _, _, _, _, _, _] => xs + case xs => Tuple10(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3), xs.productElement(4), xs.productElement(5), xs.productElement(6), xs.productElement(7), xs.productElement(8), xs.productElement(9)) + } + case 11 => + xs match { + case xs: Tuple11[_, _, _, _, _, _, _, _, _, _, _] => xs + case xs => Tuple11(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3), xs.productElement(4), xs.productElement(5), xs.productElement(6), xs.productElement(7), xs.productElement(8), xs.productElement(9), xs.productElement(10)) + } + case 12 => + xs match { + case xs: Tuple12[_, _, _, _, _, _, _, _, _, _, _, _] => xs + case xs => Tuple12(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3), xs.productElement(4), xs.productElement(5), xs.productElement(6), xs.productElement(7), xs.productElement(8), xs.productElement(9), xs.productElement(10), xs.productElement(11)) + } + case 13 => + xs match { + case xs: Tuple13[_, _, _, _, _, _, _, _, _, _, _, _, _] => xs + case xs => Tuple13(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3), xs.productElement(4), xs.productElement(5), xs.productElement(6), xs.productElement(7), xs.productElement(8), xs.productElement(9), xs.productElement(10), xs.productElement(11), xs.productElement(12)) + } + case 14 => + xs match { + case xs: Tuple14[_, _, _, _, _, _, _, _, _, _, _, _, _, _] => xs + case xs => Tuple14(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3), xs.productElement(4), xs.productElement(5), xs.productElement(6), xs.productElement(7), xs.productElement(8), xs.productElement(9), xs.productElement(10), xs.productElement(11), xs.productElement(12), xs.productElement(13)) + } + case 15 => + xs match { + case xs: Tuple15[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => xs + case xs => Tuple15(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3), xs.productElement(4), xs.productElement(5), xs.productElement(6), xs.productElement(7), xs.productElement(8), xs.productElement(9), xs.productElement(10), xs.productElement(11), xs.productElement(12), xs.productElement(13), xs.productElement(14)) + } + case 16 => + xs match { + case xs: Tuple16[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => xs + case xs => Tuple16(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3), xs.productElement(4), xs.productElement(5), xs.productElement(6), xs.productElement(7), xs.productElement(8), xs.productElement(9), xs.productElement(10), xs.productElement(11), xs.productElement(12), xs.productElement(13), xs.productElement(14), xs.productElement(15)) + } + case 17 => + xs match { + case xs: Tuple17[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => xs + case xs => Tuple17(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3), xs.productElement(4), xs.productElement(5), xs.productElement(6), xs.productElement(7), xs.productElement(8), xs.productElement(9), xs.productElement(10), xs.productElement(11), xs.productElement(12), xs.productElement(13), xs.productElement(14), xs.productElement(15), xs.productElement(16)) + } + case 18 => + xs match { + case xs: Tuple18[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => xs + case xs => Tuple18(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3), xs.productElement(4), xs.productElement(5), xs.productElement(6), xs.productElement(7), xs.productElement(8), xs.productElement(9), xs.productElement(10), xs.productElement(11), xs.productElement(12), xs.productElement(13), xs.productElement(14), xs.productElement(15), xs.productElement(16), xs.productElement(17)) + } + case 19 => + xs match { + case xs: Tuple19[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => xs + case xs => Tuple19(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3), xs.productElement(4), xs.productElement(5), xs.productElement(6), xs.productElement(7), xs.productElement(8), xs.productElement(9), xs.productElement(10), xs.productElement(11), xs.productElement(12), xs.productElement(13), xs.productElement(14), xs.productElement(15), xs.productElement(16), xs.productElement(17), xs.productElement(18)) + } + case 20 => + xs match { + case xs: Tuple20[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => xs + case xs => Tuple20(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3), xs.productElement(4), xs.productElement(5), xs.productElement(6), xs.productElement(7), xs.productElement(8), xs.productElement(9), xs.productElement(10), xs.productElement(11), xs.productElement(12), xs.productElement(13), xs.productElement(14), xs.productElement(15), xs.productElement(16), xs.productElement(17), xs.productElement(18), xs.productElement(19)) + } + case 21 => + xs match { + case xs: Tuple21[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => xs + case xs => Tuple21(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3), xs.productElement(4), xs.productElement(5), xs.productElement(6), xs.productElement(7), xs.productElement(8), xs.productElement(9), xs.productElement(10), xs.productElement(11), xs.productElement(12), xs.productElement(13), xs.productElement(14), xs.productElement(15), xs.productElement(16), xs.productElement(17), xs.productElement(18), xs.productElement(19), xs.productElement(20)) + } + case 22 => + xs match { + case xs: Tuple22[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => xs + case xs => Tuple22(xs.productElement(0), xs.productElement(1), xs.productElement(2), xs.productElement(3), xs.productElement(4), xs.productElement(5), xs.productElement(6), xs.productElement(7), xs.productElement(8), xs.productElement(9), xs.productElement(10), xs.productElement(11), xs.productElement(12), xs.productElement(13), xs.productElement(14), xs.productElement(15), xs.productElement(16), xs.productElement(17), xs.productElement(18), xs.productElement(19), xs.productElement(20), xs.productElement(21)) + } + case _ => + (xs match { + case xs: TupleXXL => xs + case xs => TupleXXL.fromIArray(xs.productIterator.map(_.asInstanceOf[Object]).toArray.asInstanceOf[IArray[Object]]) // TODO use Iterator.toIArray + }).asInstanceOf[Tuple] + }) + + // Cons for Tuple1 to Tuple22 + private def specialCaseCons(x: Any, self: Tuple): Tuple = { + (self: Any) match { + case self: Unit => + Tuple1(x) + case self: Tuple1[_] => + Tuple2(x, self._1) + case self: Tuple2[_, _] => + Tuple3(x, self._1, self._2) + case self: Tuple3[_, _, _] => + Tuple4(x, self._1, self._2, self._3) + case self: Tuple4[_, _, _, _] => + Tuple5(x, self._1, self._2, self._3, self._4) + case self: Tuple5[_, _, _, _, _] => + Tuple6(x, self._1, self._2, self._3, self._4, self._5) + case self: Tuple6[_, _, _, _, _, _] => + Tuple7(x, self._1, self._2, self._3, self._4, self._5, self._6) + case self: Tuple7[_, _, _, _, _, _, _] => + Tuple8(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7) + case self: Tuple8[_, _, _, _, _, _, _, _] => + Tuple9(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8) + case self: Tuple9[_, _, _, _, _, _, _, _, _] => + Tuple10(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9) + case self: Tuple10[_, _, _, _, _, _, _, _, _, _] => + Tuple11(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10) + case self: Tuple11[_, _, _, _, _, _, _, _, _, _, _] => + Tuple12(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11) + case self: Tuple12[_, _, _, _, _, _, _, _, _, _, _, _] => + Tuple13(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12) + case self: Tuple13[_, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple14(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13) + case self: Tuple14[_, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple15(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14) + case self: Tuple15[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple16(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15) + case self: Tuple16[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple17(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16) + case self: Tuple17[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple18(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17) + case self: Tuple18[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple19(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18) + case self: Tuple19[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple20(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19) + case self: Tuple20[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple21(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20) + case self: Tuple21[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple22(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20, self._21) + case self: Tuple22[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + val arr: Array[Object] = Array( + x.asInstanceOf[Object], self._1.asInstanceOf[Object], self._2.asInstanceOf[Object], + self._3.asInstanceOf[Object], self._4.asInstanceOf[Object], self._5.asInstanceOf[Object], + self._6.asInstanceOf[Object], self._7.asInstanceOf[Object], self._8.asInstanceOf[Object], + self._9.asInstanceOf[Object], self._10.asInstanceOf[Object], self._11.asInstanceOf[Object], + self._12.asInstanceOf[Object], self._13.asInstanceOf[Object], self._14.asInstanceOf[Object], + self._15.asInstanceOf[Object], self._16.asInstanceOf[Object], self._17.asInstanceOf[Object], + self._18.asInstanceOf[Object], self._19.asInstanceOf[Object], self._20.asInstanceOf[Object], + self._21.asInstanceOf[Object], self._22.asInstanceOf[Object], + ) + TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]]).asInstanceOf[Tuple] + } + } + + // Cons for TupleXXL + private def xxlCons(x: Any, xxl: TupleXXL): TupleXXL = { + val arr = new Array[Object](xxl.productArity + 1) + arr(0) = x.asInstanceOf[Object] + System.arraycopy(xxl.elems, 0, arr, 1, xxl.productArity) + TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]]) + } + + def cons(x: Any, self: Tuple): Tuple = (self: Any) match { + case xxl: TupleXXL => xxlCons(x, xxl).asInstanceOf[Tuple] + case _ => specialCaseCons(x, self) + } + + def concat[This <: Tuple, That <: Tuple](self: This, that: That): Tuple = { + val selfSize: Int = self.size + // If one of the tuples is empty, we can leave early + if selfSize == 0 then + return that + + val thatSize: Int = that.size + if thatSize == 0 then + return self + + val arr = new Array[Object](selfSize + thatSize) + + // Copies the tuple to an array, at the given offset + inline def copyToArray[T <: Tuple](tuple: T, size: Int, array: Array[Object], offset: Int): Unit = (tuple: Any) match { + case xxl: TupleXXL => + System.arraycopy(xxl.elems, 0, array, offset, size) + case _ => + tuple.asInstanceOf[Product].productIterator.asInstanceOf[Iterator[Object]] + .copyToArray(array, offset, size) + } + + // In the general case, we copy the two tuples to an array, and convert it back to a tuple + copyToArray(self, selfSize, arr, 0) + copyToArray(that, thatSize, arr, selfSize) + fromIArray(arr.asInstanceOf[IArray[Object]]) + } + + def size(self: Tuple): Int = (self: Any) match { + case self: Unit => 0 + case self: Product => self.productArity + } + + // Tail for Tuple1 to Tuple22 + private def specialCaseTail(self: Tuple): Tuple = { + (self: Any) match { + case self: Tuple1[_] => + () + case self: Tuple2[_, _] => + Tuple1(self._2) + case self: Tuple3[_, _, _] => + Tuple2(self._2, self._3) + case self: Tuple4[_, _, _, _] => + Tuple3(self._2, self._3, self._4) + case self: Tuple5[_, _, _, _, _] => + Tuple4(self._2, self._3, self._4, self._5) + case self: Tuple6[_, _, _, _, _, _] => + Tuple5(self._2, self._3, self._4, self._5, self._6) + case self: Tuple7[_, _, _, _, _, _, _] => + Tuple6(self._2, self._3, self._4, self._5, self._6, self._7) + case self: Tuple8[_, _, _, _, _, _, _, _] => + Tuple7(self._2, self._3, self._4, self._5, self._6, self._7, self._8) + case self: Tuple9[_, _, _, _, _, _, _, _, _] => + Tuple8(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9) + case self: Tuple10[_, _, _, _, _, _, _, _, _, _] => + Tuple9(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10) + case self: Tuple11[_, _, _, _, _, _, _, _, _, _, _] => + Tuple10(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11) + case self: Tuple12[_, _, _, _, _, _, _, _, _, _, _, _] => + Tuple11(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12) + case self: Tuple13[_, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple12(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13) + case self: Tuple14[_, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple13(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14) + case self: Tuple15[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple14(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15) + case self: Tuple16[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple15(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16) + case self: Tuple17[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple16(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17) + case self: Tuple18[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple17(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18) + case self: Tuple19[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple18(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19) + case self: Tuple20[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple19(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20) + case self: Tuple21[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple20(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20, self._21) + case self: Tuple22[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple21(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20, self._21, self._22) + } + } + + // Tail for TupleXXL + private def xxlTail(xxl: TupleXXL): Tuple = { + if (xxl.productArity == 23) { + val elems = xxl.elems + Tuple22( + elems(1), elems(2), elems(3), elems(4), elems(5), elems(6), elems(7), + elems(8), elems(9), elems(10), elems(11), elems(12), elems(13), elems(14), + elems(15), elems(16), elems(17), elems(18), elems(19), elems(20), + elems(21), elems(22) + ) + } else { + val arr = new Array[Object](xxl.elems.length - 1) + System.arraycopy(xxl.elems, 1, arr, 0, xxl.elems.length - 1) + TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]]).asInstanceOf[Tuple] + } + } + + def tail(self: NonEmptyTuple): Tuple = (self: Any) match { + case xxl: TupleXXL => xxlTail(xxl) + case _ => specialCaseTail(self) + } + + def apply(self: NonEmptyTuple, n: Int): Any = { + (self: Any) match { + // case self: Unit => throw new IndexOutOfBoundsException(n.toString) + case self: Product => self.productElement(n) + } + } + + // Benchmarks showed that this is faster than doing (it1 zip it2).copyToArray(...) + private def zipIterators(it1: Iterator[Any], it2: Iterator[Any], size: Int): IArray[Object] = { + val arr = new Array[Object](size) + var i = 0 + while (i < size) { + arr(i) = (it1.next(), it2.next()) + i += 1 + } + arr.asInstanceOf[IArray[Object]] + } + + def zip(t1: Tuple, t2: Tuple): Tuple = { + val t1Size: Int = t1.size + val t2Size: Int = t2.size + val size = Math.min(t1Size, t2Size) + if size == 0 then () + else Tuple.fromIArray( + zipIterators( + t1.asInstanceOf[Product].productIterator, + t2.asInstanceOf[Product].productIterator, + size + ) + ) + } + + def map[F[_]](self: Tuple, f: [t] => t => F[t]): Tuple = (self: Any) match { + case self: Unit => () + case _ => fromIArray(self.asInstanceOf[Product].productIterator.map(f(_).asInstanceOf[Object]).toArray.asInstanceOf[IArray[Object]]) // TODO use toIArray + } + + def take(self: Tuple, n: Int): Tuple = { + if (n < 0) throw new IndexOutOfBoundsException(n.toString) + val selfSize: Int = self.size + val actualN = Math.min(n, selfSize) + + if (actualN == 0) () + else { + val arr = (self: Any) match { + case xxl: TupleXXL => + xxl.elems.asInstanceOf[Array[Object]].take(actualN) + case _ => + val arr = new Array[Object](actualN) + self.asInstanceOf[Product].productIterator.asInstanceOf[Iterator[Object]] + .copyToArray(arr, 0, actualN) + arr + } + + fromIArray(arr.asInstanceOf[IArray[Object]]) + } + } + + def drop(self: Tuple, n: Int): Tuple = { + if (n < 0) throw new IndexOutOfBoundsException(n.toString) + val size = self.size + val actualN = Math.min(n, size) + val rem = size - actualN + + if (rem == 0) () + else { + val arr = (self: Any) match { + case xxl: TupleXXL => + xxl.elems.asInstanceOf[Array[Object]].drop(actualN) + case _ => + val arr = new Array[Object](rem) + self.asInstanceOf[Product].productIterator.asInstanceOf[Iterator[Object]] + .drop(actualN).copyToArray(arr, 0, rem) + arr + } + + fromIArray(arr.asInstanceOf[IArray[Object]]) + } + } + + def splitAt(self: Tuple, n: Int): (Tuple, Tuple) = { + if (n < 0) throw new IndexOutOfBoundsException(n.toString) + val size = self.size + val actualN = Math.min(n, size) + val (arr1, arr2) = (self: Any) match { + case () => (Array.empty[Object], Array.empty[Object]) + case xxl: TupleXXL => + xxl.elems.asInstanceOf[Array[Object]].splitAt(actualN) + case _ => + val arr1 = new Array[Object](actualN) + val arr2 = new Array[Object](size - actualN) + val it = self.asInstanceOf[Product].productIterator.asInstanceOf[Iterator[Object]] + it.copyToArray(arr1, 0, actualN) + it.copyToArray(arr2, 0, size - actualN) + (arr1, arr2) + } + + ( + fromIArray(arr1.asInstanceOf[IArray[Object]]), + fromIArray(arr2.asInstanceOf[IArray[Object]]) + ) + } + + def consIterator(head: Any, tail: Tuple): Iterator[Any] = + Iterator.single(head) ++ tail.asInstanceOf[Product].productIterator + + def concatIterator(tup1: Tuple, tup2: Tuple): Iterator[Any] = + tup1.asInstanceOf[Product].productIterator ++ tup2.asInstanceOf[Product].productIterator + +}