Skip to content

Commit 6ea98e3

Browse files
committed
More generative operations on Tuples: tail, apply, ++
1 parent d002b3a commit 6ea98e3

File tree

3 files changed

+132
-3
lines changed

3 files changed

+132
-3
lines changed

library/src-scala3/scala/Tuple.scala

Lines changed: 110 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,46 @@ sealed trait Tuple extends Any {
4545
fromArray[resTpe.Type]($consArray(x, toArray))
4646
}
4747
}
48+
49+
rewrite def ++(that: Tuple): Tuple = {
50+
erased val resTpe = Typed(_concat(this, that))
51+
rewrite _size(this) match {
52+
case 0 =>
53+
that
54+
case 1 =>
55+
if (_size(that) == 0) this
56+
else (asInstanceOf[Tuple1[_]]._1 *: that).asInstanceOf[resTpe.Type]
57+
case 2 =>
58+
val t = asInstanceOf[Tuple2[_, _]]
59+
rewrite _size(that) match {
60+
case 0 => this
61+
case 1 =>
62+
val u = that.asInstanceOf[Tuple1[_]]
63+
Tuple3(t._1, t._2, u._1).asInstanceOf[resTpe.Type]
64+
case 2 =>
65+
val u = that.asInstanceOf[Tuple2[_, _]]
66+
Tuple4(t._1, t._2, u._1, u._2).asInstanceOf[resTpe.Type]
67+
case _ =>
68+
genericConcat[resTpe.Type](this, that)
69+
}
70+
case 3 =>
71+
val t = asInstanceOf[Tuple3[_, _, _]]
72+
rewrite _size(that) match {
73+
case 0 => this
74+
case 1 =>
75+
val u = that.asInstanceOf[Tuple1[_]]
76+
Tuple4(t._1, t._2, t._3, u._1).asInstanceOf[resTpe.Type]
77+
case _ =>
78+
genericConcat[resTpe.Type](this, that)
79+
}
80+
case _ =>
81+
if (_size(that) == 0) this
82+
else genericConcat[resTpe.Type](this, that)
83+
}
84+
}
85+
86+
rewrite def genericConcat[T <: Tuple](xs: Tuple, ys: Tuple): Tuple =
87+
fromArray[T](xs.toArray ++ ys.toArray)
4888
}
4989

5090
object Tuple {
@@ -83,6 +123,20 @@ object Tuple {
83123
case _: (x *: _) => erasedValue[x]
84124
}
85125

126+
private[scala] rewrite def _tail(xs: Tuple): Tuple = rewrite xs match {
127+
case _: (_ *: xs1) => erasedValue[xs1]
128+
}
129+
130+
private[scala] rewrite def _index(xs: Tuple, n: Int): Any = rewrite xs match {
131+
case _: (x *: _) if n == 0 => erasedValue[x]
132+
case _: (_ *: xs1) if n > 0 => _index(erasedValue[xs1], n - 1)
133+
}
134+
135+
private[scala] rewrite def _concat(xs: Tuple, ys: Tuple): Tuple = rewrite xs match {
136+
case _: Unit => ys
137+
case _: (x1 *: xs1) => _pair(erasedValue[x1], _concat(erasedValue[xs1], ys))
138+
}
139+
86140
rewrite def fromArray[T <: Tuple](xs: Array[Object]): T =
87141
rewrite _size(erasedValue[T]) match {
88142
case 0 => ().asInstanceOf[T]
@@ -140,8 +194,63 @@ sealed class *:[+H, +T <: Tuple] extends Tuple {
140194
resVal.asInstanceOf[resTpe.Type]
141195
}
142196

143-
rewrite def tail: T = ???
197+
rewrite def tail: Tuple = {
198+
erased val resTpe = Typed(_tail(this))
199+
rewrite _size(this) match {
200+
case 1 =>
201+
()
202+
case 2 =>
203+
val t = asInstanceOf[Tuple2[_, _]]
204+
Tuple1(t._2).asInstanceOf[resTpe.Type]
205+
case 3 =>
206+
val t = asInstanceOf[Tuple3[_, _, _]]
207+
Tuple2(t._2, t._3).asInstanceOf[resTpe.Type]
208+
case 4 =>
209+
val t = asInstanceOf[Tuple4[_, _, _, _]]
210+
Tuple3(t._2, t._3, t._4).asInstanceOf[resTpe.Type]
211+
case 5 =>
212+
val t = asInstanceOf[Tuple5[_, _, _, _, _]]
213+
Tuple4(t._2, t._3, t._4, t._5).asInstanceOf[resTpe.Type]
214+
case n if n > 5 =>
215+
fromArray[resTpe.Type](toArray.tail)
216+
}
217+
}
144218

219+
rewrite def apply(n: Int): Any = {
220+
erased val resTpe = Typed(_index(this, n))
221+
rewrite _size(this) match {
222+
case 1 =>
223+
val t = asInstanceOf[Tuple1[_]]
224+
rewrite n match {
225+
case 0 => t._1.asInstanceOf[resTpe.Type]
226+
}
227+
case 2 =>
228+
val t = asInstanceOf[Tuple2[_, _]]
229+
rewrite n match {
230+
case 0 => t._1.asInstanceOf[resTpe.Type]
231+
case 1 => t._2.asInstanceOf[resTpe.Type]
232+
}
233+
case 3 =>
234+
val t = asInstanceOf[Tuple3[_, _, _]]
235+
rewrite n match {
236+
case 0 => t._1.asInstanceOf[resTpe.Type]
237+
case 1 => t._2.asInstanceOf[resTpe.Type]
238+
case 2 => t._3.asInstanceOf[resTpe.Type]
239+
}
240+
case 4 =>
241+
val t = asInstanceOf[Tuple4[_, _, _, _]]
242+
rewrite n match {
243+
case 0 => t._1.asInstanceOf[resTpe.Type]
244+
case 1 => t._2.asInstanceOf[resTpe.Type]
245+
case 2 => t._3.asInstanceOf[resTpe.Type]
246+
case 3 => t._4.asInstanceOf[resTpe.Type]
247+
}
248+
case s if s > 4 && s <= $MaxSpecialized && n >= 0 && n < s =>
249+
asInstanceOf[Product].productElement(n).asInstanceOf[resTpe.Type]
250+
case s if s > $MaxSpecialized && n >= 0 && n < s =>
251+
asInstanceOf[TupleXXL].elems(n).asInstanceOf[resTpe.Type]
252+
}
253+
}
145254
}
146255

147256
object *: {

tests/run/tuples1.check

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,24 @@ h1 = 1
1111
h2 = A
1212
h7 = 4
1313
h8 = D
14+
t1 = ()
15+
t2 = (1)
16+
t7 = (C,3,B,2,A,1)
17+
t8 = (4,C,3,B,2,A,1)
18+
a1_0 = 1
19+
a2_0 = A
20+
a3_1 = A
21+
a4_3 = 1
22+
a6_4 = A
23+
a8_0 = D
24+
c0_0 = ()
25+
c0_1 = (1)
26+
c1_0 = (1)
27+
c0_4 = (B,2,A,1)
28+
c4_0 = (B,2,A,1)
29+
c1_1 = (1,1)
30+
c1_8 = (1,D,4,C,3,B,2,A,1)
31+
c2_1 = (A,1,1)
32+
c2_2 = (A,1,A,1)
33+
c2_3 = (A,1,2,A,1)
34+
c3_3 = (2,A,1,2,A,1)

tests/run/tuples1.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ object Test extends App {
1212
val h2 = x2.head; val h2c: String = h2; println(s"h2 = $h2")
1313
val h7 = x7.head; val h7c: Int = h7; println(s"h7 = $h7")
1414
val h8 = x8.head; val h8c: String = h8; println(s"h8 = $h8")
15-
/*
1615
val t1 = x1.tail; val t1c: Unit = t1; println(s"t1 = $t1")
1716
val t2 = x2.tail; val t2c: Int *: Unit = t2; println(s"t2 = $t2")
1817
val t7 = x7.tail; val t7c: String *: Int *: Unit = t7.tail.tail.tail.tail; println(s"t7 = $t7")
@@ -33,5 +32,5 @@ object Test extends App {
3332
val c2_1 = x2 ++ x1; val c2_1c: String *: Int *: Int *: Unit = c2_1; println(s"c2_1 = $c2_1")
3433
val c2_2 = x2 ++ x2; val c2_2c: String *: Int *: String *: Int *: Unit = c2_2; println(s"c2_2 = $c2_2")
3534
val c2_3 = x2 ++ x3; val c2_3c: String *: Int *: Int *: String *: Int *: Unit = c2_3; println(s"c2_3 = $c2_3")
36-
val c3_3 = x3 ++ x3; val c3_3c: Int *: String *: Int *: Int *: String *: Int *: Unit = c3_3; println(s"c3_3 = $c3_3")*/
35+
val c3_3 = x3 ++ x3; val c3_3c: Int *: String *: Int *: Int *: String *: Int *: Unit = c3_3; println(s"c3_3 = $c3_3")
3736
}

0 commit comments

Comments
 (0)