Skip to content

Commit

Permalink
Cleanup code in DynamicTuple
Browse files Browse the repository at this point in the history
* Remove dead code
* Remove uses of scala.Tuple.* match types
* Remove `dynamic` prefix from methods in `DynamicTuple`
  • Loading branch information
nicolasstucki committed Feb 17, 2020
1 parent b4e037c commit 9aca3a3
Show file tree
Hide file tree
Showing 16 changed files with 176 additions and 224 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class Apply {

@Benchmark
def tupleApply(): Any = {
DynamicTuple.dynamicApply(tuple, index)
DynamicTuple.apply(tuple, index)
}

@Benchmark
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@ class Concat {

@Benchmark
def tupleConcat(): Tuple = {
DynamicTuple.dynamicConcat(tuple1, tuple2)
DynamicTuple.concat(tuple1, tuple2)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class Cons {

@Benchmark
def tupleCons(): Tuple = {
DynamicTuple.dynamicCons("elem", tuple)
DynamicTuple.cons("elem", tuple)
}

@Benchmark
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,22 @@ class Conversions {

@Benchmark
def tupleToArray(): Array[Object] = {
DynamicTuple.dynamicToArray(tuple)
DynamicTuple.toArray(tuple)
}

@Benchmark
def tupleToIArray(): IArray[Object] = {
DynamicTuple.dynamicToIArray(tuple)
DynamicTuple.toIArray(tuple)
}

@Benchmark
def tupleFromArray(): Tuple = {
DynamicTuple.dynamicFromArray(array)
DynamicTuple.fromArray(array)
}

@Benchmark
def tupleFromIArray(): Tuple = {
DynamicTuple.dynamicFromIArray(iarray)
DynamicTuple.fromIArray(iarray)
}

@Benchmark
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class Map {

@Benchmark
def tupleMap(): Tuple = {
DynamicTuple.dynamicMap[Tuple, Id](tuple, [T] => (x:T) => x.asInstanceOf[String].updated(0, 'a').asInstanceOf[T])
DynamicTuple.map[Id](tuple, [T] => (x:T) => x.asInstanceOf[String].updated(0, 'a').asInstanceOf[T])
}

@Benchmark
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class Tail {

@Benchmark
def tupleTail(): Tuple = {
DynamicTuple.dynamicTail(tuple)
DynamicTuple.tail(tuple)
}

@Benchmark
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class Zip {

@Benchmark
def tupleZip(): Tuple = {
DynamicTuple.dynamicZip(tuple1, tuple2)
DynamicTuple.zip(tuple1, tuple2)
}

@Benchmark
Expand Down
2 changes: 1 addition & 1 deletion bench-run/src/main/scala/tuples/Drop.scala
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class Drop {

@Benchmark
def tupleDrop(): Tuple = {
DynamicTuple.dynamicDrop(tuple, half)
DynamicTuple.drop(tuple, half)
}

@Benchmark
Expand Down
2 changes: 1 addition & 1 deletion bench-run/src/main/scala/tuples/Split.scala
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class Split {

@Benchmark
def tupleSplit(): (Tuple, Tuple) = {
DynamicTuple.dynamicSplitAt(tuple, half)
DynamicTuple.splitAt(tuple, half)
}

@Benchmark
Expand Down
2 changes: 1 addition & 1 deletion bench-run/src/main/scala/tuples/Take.scala
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class Take {

@Benchmark
def tupleTake(): Tuple = {
DynamicTuple.dynamicTake(tuple, half)
DynamicTuple.take(tuple, half)
}

@Benchmark
Expand Down
12 changes: 6 additions & 6 deletions compiler/src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -758,12 +758,12 @@ class Definitions {
@tu lazy val DynamicTupleModuleClass: Symbol = DynamicTupleModule.moduleClass
lazy val DynamicTuple_consIterator: Symbol = DynamicTupleModule.requiredMethod("consIterator")
lazy val DynamicTuple_concatIterator: Symbol = DynamicTupleModule.requiredMethod("concatIterator")
lazy val DynamicTuple_dynamicApply: Symbol = DynamicTupleModule.requiredMethod("dynamicApply")
lazy val DynamicTuple_dynamicCons: Symbol = DynamicTupleModule.requiredMethod("dynamicCons")
lazy val DynamicTuple_dynamicSize: Symbol = DynamicTupleModule.requiredMethod("dynamicSize")
lazy val DynamicTuple_dynamicTail: Symbol = DynamicTupleModule.requiredMethod("dynamicTail")
lazy val DynamicTuple_dynamicConcat: Symbol = DynamicTupleModule.requiredMethod("dynamicConcat")
lazy val DynamicTuple_dynamicToArray: Symbol = DynamicTupleModule.requiredMethod("dynamicToArray")
lazy val DynamicTuple_apply: Symbol = DynamicTupleModule.requiredMethod("apply")
lazy val DynamicTuple_cons: Symbol = DynamicTupleModule.requiredMethod("cons")
lazy val DynamicTuple_size: Symbol = DynamicTupleModule.requiredMethod("size")
lazy val DynamicTuple_tail: Symbol = DynamicTupleModule.requiredMethod("tail")
lazy val DynamicTuple_concat: Symbol = DynamicTupleModule.requiredMethod("concat")
lazy val DynamicTuple_toArray: Symbol = DynamicTupleModule.requiredMethod("toArray")
lazy val DynamicTuple_productToArray: Symbol = DynamicTupleModule.requiredMethod("productToArray")

@tu lazy val TupledFunctionTypeRef: TypeRef = ctx.requiredClassRef("scala.TupledFunction")
Expand Down
39 changes: 19 additions & 20 deletions compiler/src/dotty/tools/dotc/transform/TupleOptimizations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,17 @@ class TupleOptimizations extends MiniPhase with IdentityDenotTransformer {

override def transformApply(tree: tpd.Apply)(implicit ctx: Context): tpd.Tree =
if (!tree.symbol.exists || tree.symbol.owner != defn.DynamicTupleModuleClass) tree
else if (tree.symbol == defn.DynamicTuple_dynamicCons) transformTupleCons(tree)
else if (tree.symbol == defn.DynamicTuple_dynamicTail) transformTupleTail(tree)
else if (tree.symbol == defn.DynamicTuple_dynamicSize) transformTupleSize(tree)
else if (tree.symbol == defn.DynamicTuple_dynamicConcat) transformTupleConcat(tree)
else if (tree.symbol == defn.DynamicTuple_dynamicApply) transformTupleApply(tree)
else if (tree.symbol == defn.DynamicTuple_dynamicToArray) transformTupleToArray(tree)
else if (tree.symbol == defn.DynamicTuple_cons) transformTupleCons(tree)
else if (tree.symbol == defn.DynamicTuple_tail) transformTupleTail(tree)
else if (tree.symbol == defn.DynamicTuple_size) transformTupleSize(tree)
else if (tree.symbol == defn.DynamicTuple_concat) transformTupleConcat(tree)
else if (tree.symbol == defn.DynamicTuple_apply) transformTupleApply(tree)
else if (tree.symbol == defn.DynamicTuple_toArray) transformTupleToArray(tree)
else tree

private def transformTupleCons(tree: tpd.Apply)(implicit ctx: Context): Tree = {
val head :: tail :: Nil = tree.args
defn.tupleTypes(tree.tpe) match {
defn.tupleTypes(tree.tpe.widenTermRefExpr.dealias) match {
case Some(tpes) =>
// Generate a the tuple directly with TupleN+1.apply
val size = tpes.size
Expand All @@ -56,14 +56,14 @@ class TupleOptimizations extends MiniPhase with IdentityDenotTransformer {
}
case _ =>
// No optimization, keep:
// DynamicTuple.dynamicCons:(tail, head)
// DynamicTuple.cons(tail, head)
tree
}
}

private def transformTupleTail(tree: tpd.Apply)(implicit ctx: Context): Tree = {
val Apply(TypeApply(_, tpt :: Nil), tup :: Nil) = tree
defn.tupleTypes(tpt.tpe, MaxTupleArity + 1) match {
val Apply(_, tup :: Nil) = tree
defn.tupleTypes(tup.tpe.widenTermRefExpr.dealias, MaxTupleArity + 1) match {
case Some(tpes) =>
// Generate a the tuple directly with TupleN-1.apply
val size = tpes.size
Expand Down Expand Up @@ -93,7 +93,7 @@ class TupleOptimizations extends MiniPhase with IdentityDenotTransformer {
tup.asInstance(defn.TupleXXLClass.typeRef).select("tailXXL".toTermName)
case None =>
// No optimization, keep:
// DynamicTuple.dynamicTail(tup)
// DynamicTuple.tail(tup)
tree
}
}
Expand All @@ -105,9 +105,8 @@ class TupleOptimizations extends MiniPhase with IdentityDenotTransformer {
}

private def transformTupleConcat(tree: tpd.Apply)(implicit ctx: Context): Tree = {
val Apply(TypeApply(_, selfTp :: thatTp :: Nil), self :: that :: Nil) = tree

(defn.tupleTypes(selfTp.tpe), defn.tupleTypes(that.tpe.widenTermRefExpr)) match {
val Apply(_, self :: that :: Nil) = tree
(defn.tupleTypes(self.tpe.widenTermRefExpr.dealias), defn.tupleTypes(that.tpe.widenTermRefExpr.dealias)) match {
case (Some(tpes1), Some(tpes2)) =>
// Generate a the tuple directly with TupleN+M.apply
val n = tpes1.size
Expand Down Expand Up @@ -135,14 +134,14 @@ class TupleOptimizations extends MiniPhase with IdentityDenotTransformer {
}
case _ =>
// No optimization, keep:
// DynamicTuple.dynamicCons[This, that.type](self, that)
// DynamicTuple.cons(self, that)
tree
}
}

private def transformTupleApply(tree: tpd.Apply)(implicit ctx: Context): Tree = {
val Apply(TypeApply(_, tpt :: nTpt :: Nil), tup :: nTree :: Nil) = tree
(defn.tupleTypes(tpt.tpe), nTpt.tpe) match {
val Apply(_, tup :: nTree :: Nil) = tree
(defn.tupleTypes(tup.tpe.widenTermRefExpr.dealias), nTree.tpe) match {
case (Some(tpes), nTpe: ConstantType) =>
// Get the element directly with TupleM._n+1 or TupleXXL.productElement(n)
val size = tpes.size
Expand All @@ -162,7 +161,7 @@ class TupleOptimizations extends MiniPhase with IdentityDenotTransformer {
tree
case _ =>
// No optimization, keep:
// DynamicTuple.dynamicApply(tup, n)
// DynamicTuple.apply(tup, n)
tree
}
}
Expand All @@ -183,7 +182,7 @@ class TupleOptimizations extends MiniPhase with IdentityDenotTransformer {
tup.asInstance(defn.TupleXXLClass.typeRef).select(nme.toArray)
case None =>
// No optimization, keep:
// DynamicTuple.dynamicToArray(tup)
// DynamicTuple.toArray(tup)
tree
}
}
Expand All @@ -205,7 +204,7 @@ class TupleOptimizations extends MiniPhase with IdentityDenotTransformer {

// TODO outline this code for the 22 alternatives (or less, may not need the smallest ones)?
// This would yield smaller bytecode at the cost of an extra (easily JIT inlinable) call.
// def dynamicTupleN(it: Iterator[Any]): TupleN[Any, ..., Any] = Tuple(it.next(), ..., it.next())
// def tupleN(it: Iterator[Any]): TupleN[Any, ..., Any] = Tuple(it.next(), ..., it.next())
val tpes = List.fill(size)(defn.AnyType)
val elements = (0 until size).map(_ => it.select(nme.next)).toList
knownTupleFromElements(tpes, elements)
Expand Down
32 changes: 16 additions & 16 deletions library/src/scala/Tuple.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,27 @@ sealed trait Tuple extends Any {

/** Create a copy this tuple as an Array */
inline def toArray: Array[Object] =
DynamicTuple.dynamicToArray(this)
DynamicTuple.toArray(this)

/** Create a copy this tuple as an IArray */
inline def toIArray: IArray[Object] =
DynamicTuple.dynamicToIArray(this)
DynamicTuple.toIArray(this)

/** Return a new tuple by prepending the element to `this` tuple.
* This opteration is O(this.size)
*/
inline def *: [H, This >: this.type <: Tuple] (x: H): H *: This =
DynamicTuple.dynamicCons[H, This](x, this)
DynamicTuple.cons(x, this).asInstanceOf[H *: This]

/** Return a new tuple by concatenating `this` tuple with `that` tuple.
* This opteration is O(this.size + that.size)
*/
inline def ++ [This >: this.type <: Tuple](that: Tuple): Concat[This, that.type] =
DynamicTuple.dynamicConcat[This, that.type](this, that)
DynamicTuple.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] =
DynamicTuple.dynamicSize(this)
DynamicTuple.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,
Expand All @@ -41,35 +41,35 @@ sealed trait Tuple extends Any {
* `(A1, B1) *: ... *: (Ai, Bi) *: Tuple`
*/
inline def zip[This >: this.type <: Tuple, T2 <: Tuple](t2: T2): Zip[This, T2] =
DynamicTuple.dynamicZip(this, t2)
DynamicTuple.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] =
DynamicTuple.dynamicMap(this, f)
DynamicTuple.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] =
DynamicTuple.dynamicTake[This, n.type](this, n)
DynamicTuple.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] =
DynamicTuple.dynamicDrop[This, n.type](this, n)
DynamicTuple.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] =
DynamicTuple.dynamicSplitAt[This, n.type](this, n)
DynamicTuple.splitAt(this, n).asInstanceOf[Split[This, n.type]]
}

object Tuple {
Expand Down Expand Up @@ -165,7 +165,7 @@ object Tuple {
case xs: Array[Object] => xs
case xs => xs.map(_.asInstanceOf[Object])
}
DynamicTuple.dynamicFromArray[Tuple](xs2)
DynamicTuple.fromArray(xs2).asInstanceOf[Tuple]
}

/** Convert an immutable array into a tuple of unknown arity and types */
Expand All @@ -176,12 +176,12 @@ object Tuple {
// TODO suport IArray.map
xs.asInstanceOf[Array[T]].map(_.asInstanceOf[Object]).asInstanceOf[IArray[Object]]
}
DynamicTuple.dynamicFromIArray[Tuple](xs2)
DynamicTuple.fromIArray(xs2).asInstanceOf[Tuple]
}

/** Convert a Product into a tuple of unknown arity and types */
def fromProduct(product: Product): Tuple =
runtime.DynamicTuple.dynamicFromProduct[Tuple](product)
runtime.DynamicTuple.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
Expand All @@ -195,17 +195,17 @@ sealed trait NonEmptyTuple extends Tuple {
* Equivalent to productElement but with a precise return type.
*/
inline def apply[This >: this.type <: NonEmptyTuple](n: Int): Elem[This, n.type] =
DynamicTuple.dynamicApply[This, n.type](this, n)
DynamicTuple.apply(this, n).asInstanceOf[Elem[This, n.type]]

/** Get the head of this tuple */
inline def head[This >: this.type <: NonEmptyTuple]: Head[This] =
DynamicTuple.dynamicApply[This, 0](this, 0)
DynamicTuple.apply(this, 0).asInstanceOf[Head[This]]

/** Get the tail of this tuple.
* This opteration is O(this.size)
*/
inline def tail[This >: this.type <: NonEmptyTuple]: Tail[This] =
DynamicTuple.dynamicTail[This](this)
DynamicTuple.tail(this).asInstanceOf[Tail[This]]

}

Expand Down
Loading

0 comments on commit 9aca3a3

Please sign in to comment.