Skip to content

Commit

Permalink
Add generative operations to tuples
Browse files Browse the repository at this point in the history
  • Loading branch information
odersky committed Aug 14, 2018
1 parent 6445f85 commit 6ec3054
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 10 deletions.
113 changes: 104 additions & 9 deletions library/src-scala3/scala/Tuple.scala
Original file line number Diff line number Diff line change
@@ -1,24 +1,119 @@
package scala
import annotation.showAsInfix
import typelevel._

sealed trait Tuple extends Any {
import Tuple._
rewrite def toArray: Array[Object] = rewrite _size(this) match {
case 0 =>
$emptyArray
case 1 =>
val t = asInstanceOf[Tuple1[Object]]
Array(t._1)
case 2 =>
val t = asInstanceOf[Tuple2[Object, Object]]
Array(t._1, t._2)
case 3 =>
val t = asInstanceOf[Tuple3[Object, Object, Object]]
Array(t._1, t._2, t._3)
case 4 =>
val t = asInstanceOf[Tuple4[Object, Object, Object, Object]]
Array(t._1, t._2, t._3, t._4)
case n if n <= $MaxSpecialized =>
$toArray(this, n)
case n if n > $MaxSpecialized =>
println(n)
asInstanceOf[TupleXXL].elems
}

object typelevel {
erased def erasedValue[T]: T = ???
rewrite def *: [H] (x: H): Tuple = {
erased val resTpe = Typed(_pair(x, this))
rewrite _size(this) match {
case 0 =>
Tuple1(x).asInstanceOf[resTpe.Type]
case 1 =>
Tuple2(x, asInstanceOf[Tuple1[_]]._1).asInstanceOf[resTpe.Type]
case 2 =>
val t = asInstanceOf[Tuple2[_, _]]
Tuple3(x, t._1, t._2).asInstanceOf[resTpe.Type]
case 3 =>
val t = asInstanceOf[Tuple3[_, _, _]]
Tuple4(x, t._1, t._2, t._3).asInstanceOf[resTpe.Type]
case 4 =>
val t = asInstanceOf[Tuple4[_, _, _, _]]
Tuple5(x, t._1, t._2, t._3, t._4).asInstanceOf[resTpe.Type]
case n =>
fromArray[resTpe.Type]($consArray(x, toArray))
}
}
}

import typelevel._
object Tuple {
transparent val $MaxSpecialized = 22

val $emptyArray = Array[Object]()

def $toArray(xs: Tuple, n: Int) = {
val arr = new Array[Object](n)
var i = 0
var it = xs.asInstanceOf[Product].productIterator
while (i < n) {
arr(i) = it.next().asInstanceOf[Object]
i += 1
}
arr
}

def $consArray[H](x: H, elems: Array[Object]): Array[Object] = {
val elems1 = new Array[Object](elems.length + 1)
elems1(0) = x.asInstanceOf[Object]
Array.copy(elems, 0, elems1, 1, elems.length)
elems1
}

private rewrite def _pair[H, T <: Tuple] (x: H, xs: T): Tuple =
erasedValue[H *: T]

sealed trait Tuple extends Any
private rewrite def _size(xs: Tuple): Int =
rewrite xs match {
case _: Unit => 0
case _: *:[_, xs1] => _size(erasedValue[xs1]) + 1
}

rewrite def fromArray[T <: Tuple](xs: Array[Object]): T =
rewrite _size(erasedValue[T]) match {
case 0 => ().asInstanceOf[T]
case 1 => Tuple1(xs(0)).asInstanceOf[T]
case 2 => Tuple2(xs(0), xs(1)).asInstanceOf[T]
case 3 => Tuple3(xs(0), xs(1), xs(2)).asInstanceOf[T]
case 4 => Tuple4(xs(0), xs(1), xs(2), xs(3)).asInstanceOf[T]
case 5 => Tuple5(xs(0), xs(1), xs(2), xs(3), xs(4)).asInstanceOf[T]
case 6 => Tuple6(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5)).asInstanceOf[T]
case 7 => Tuple7(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6)).asInstanceOf[T]
case 8 => Tuple8(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7)).asInstanceOf[T]
case 9 => Tuple9(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7), xs(8)).asInstanceOf[T]
case 10 => Tuple10(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7), xs(8), xs(9)).asInstanceOf[T]
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)).asInstanceOf[T]
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)).asInstanceOf[T]
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)).asInstanceOf[T]
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)).asInstanceOf[T]
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)).asInstanceOf[T]
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)).asInstanceOf[T]
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)).asInstanceOf[T]
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)).asInstanceOf[T]
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)).asInstanceOf[T]
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)).asInstanceOf[T]
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)).asInstanceOf[T]
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)).asInstanceOf[T]
case _ => TupleXXL(xs).asInstanceOf[T]
}
}

@showAsInfix
sealed class *:[+H, +T <: Tuple] extends Tuple {
rewrite def head: H = ???
rewrite def tail: T = ???

rewrite private def _size(xs: Tuple): Int = //rewrite
xs match {
case _: Unit => 0
case _: *:[_, xs1] => _size(erasedValue[xs1]) + 1
}
}

object *: {
Expand Down
6 changes: 6 additions & 0 deletions library/src-scala3/scala/typelevel/package.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package scala

package object typelevel {
erased def erasedValue[T]: T = ???
case class Typed[T](val value: T) { type Type = T }
}
14 changes: 14 additions & 0 deletions library/src/scala/TupleXXL.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package scala

final class TupleXXL private (es: Array[Object]) {
override def toString = elems.mkString("(", ",", ")")
override def hashCode = getClass.hashCode * 41 + elems.deep.hashCode
override def equals(that: Any) = that match {
case that: TupleXXL => this.elems.deep.equals(that.elems.deep)
case _ => false
}
def elems: Array[Object] = es
}
object TupleXXL {
def apply(elems: Array[Object]) = new TupleXXL(elems.clone)
}
1 change: 0 additions & 1 deletion tests/run/Tuple.scala
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ object Tuple {
val e4c: Int = conc1(1)
val e5c: Int = conc2(0)
val e6c: Double = conc2(4)

}

object Test extends App
37 changes: 37 additions & 0 deletions tests/run/tuples1.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
object Test extends App {
val x0 = (); println(x0)
val x1 = 1 *: x0; println(x1)
val x2 = "A" *: x1; println(x2)
val x3 = 2 *: x2; println(x3)
val x4 = "B" *: x3; println(x4)
val x5 = 3 *: x4; println(x5)
val x6 = "C" *: x5; println(x6)
val x7 = 4 *: x6; println(x7)
val x8 = "D" *: x7; println(x8)
/*
val h1 = x1.head; val h1c: Int = h1; println(s"h1 = $h1")
val h2 = x2.head; val h2c: String = h2; println(s"h2 = $h2")
val h7 = x7.head; val h7c: Int = h7; println(s"h7 = $h7")
val h8 = x8.head; val h8c: String = h8; println(s"h8 = $h8")
val t1 = x1.tail; val t1c: Empty = t1; println(s"t1 = $t1")
val t2 = x2.tail; val t2c: Int *: Empty = t2; println(s"t2 = $t2")
val t7 = x7.tail; val t7c: String *: Int *: Empty = t7.tail.tail.tail.tail; println(s"t7 = $t7")
val t8 = x8.tail; val t8c: Int = t8(6); println(s"t8 = $t8")
val a1_0 = x1(0); val a1_0c: Int = a1_0; println(s"a1_0 = $a1_0")
val a2_0 = x2(0); val a2_0c: String = a2_0; println(s"a2_0 = $a2_0")
val a3_1 = x3(1); val a3_1c: String = a3_1; println(s"a3_1 = $a3_1")
val a4_3 = x4(3); val a4_3c: Int = a4_3; println(s"a4_3 = $a4_3")
val a6_4 = x6(4); val a6_4c: String = a6_4; println(s"a6_4 = $a6_4")
val a8_0 = x8(0); val a8_0c: String = a8_0; println(s"a8_0 = $a8_0")
val c0_0 = x0 ++ x0; val c0_0c: Empty = c0_0; println(s"c0_0 = $c0_0")
val c0_1 = x0 ++ x1; val c0_1c: Int *: Empty = c0_1c; println(s"c0_1 = $c0_1")
val c1_0 = x1 ++ x0; val c1_0c: Int *: Empty = c1_0c; println(s"c1_0 = $c1_0")
val c0_4 = x0 ++ x4; val c0_4c: String *: Int *: String *: Int *: Empty = c0_4; println(s"c0_4 = $c0_4")
val c4_0 = x4 ++ x0; val c4_0c: String *: Int *: String *: Int *: Empty = c4_0; println(s"c4_0 = $c4_0")
val c1_1 = x1 ++ x1; val c1_1c: Int *: Int *: Empty = c1_1; println(s"c1_1 = $c1_1")
val c1_8 = x1 ++ x8; val c1_8c: Int *: String *: Int *: String *: Int *: String *: Int *: String *: Int *: Empty = c1_8; println(s"c1_8 = $c1_8")
val c2_1 = x2 ++ x1; val c2_1c: String *: Int *: Int *: Empty = c2_1; println(s"c2_1 = $c2_1")
val c2_2 = x2 ++ x2; val c2_2c: String *: Int *: String *: Int *: Empty = c2_2; println(s"c2_2 = $c2_2")
val c2_3 = x2 ++ x3; val c2_3c: String *: Int *: Int *: String *: Int *: Empty = c2_3; println(s"c2_3 = $c2_3")
val c3_3 = x3 ++ x3; val c3_3c: Int *: String *: Int *: Int *: String *: Int *: Empty = c3_3; println(s"c3_3 = $c3_3")*/
}

0 comments on commit 6ec3054

Please sign in to comment.