1
- package test
1
+ package test {
2
2
3
3
import annotation .showAsInfix
4
4
5
5
class TypeLevel {
6
6
type Tuple
7
7
type Empty <: Tuple
8
- type Pair [+ H , + T <: Tuple ] <: Tuple
8
+
9
+ @ showAsInfix type *: [+ H , + T <: Tuple ] <: Tuple
9
10
erased def erasedValue [T ]: T = ???
10
11
case class Typed [T ](val value : T ) { type Type = T }
11
12
}
12
13
14
+ class TupleXXL (val elems : Array [Object ])
15
+
13
16
object Tuples {
14
17
val typelevel = new TypeLevel
15
18
import typelevel ._
16
19
17
- transparent def _empty : typelevel.Tuple = erasedValue[Empty ]
18
- transparent def _pair [H , T <: typelevel.Tuple ] (x : H , xs : T ): typelevel.Tuple = erasedValue[Pair [H , T ]]
20
+ final val MaxSpecialized = 7 // 22 in real life
21
+
22
+ transparent def _empty : Tuple = erasedValue[Empty ]
23
+ transparent def _pair [H , T <: Tuple ] (x : H , xs : T ): Tuple = erasedValue[H *: T ]
24
+
25
+ def unit = ().asInstanceOf [Empty ]
19
26
20
- transparent def _size (xs : typelevel. Tuple ): Int = xs match {
21
- case _ : typelevel. Empty => 0
22
- case _ : typelevel. Pair [_, xs1] => _size(erasedValue[xs1]) + 1
27
+ transparent def _size (xs : Tuple ): Int = xs match {
28
+ case _ : Empty => 0
29
+ case _ : (_ *: xs1) => _size(erasedValue[xs1]) + 1
23
30
}
24
31
25
- val x = _size(erasedValue[Pair [Int , Pair [String , Empty ]]])
26
- /*
32
+ erased val xs2 = erasedValue[Int *: String *: Empty ]
33
+
34
+ erased val s = _size(xs2)
35
+
27
36
transparent def _index (xs : Tuple , n : Int ): Any = xs match {
28
- case x *: _ if n == 0 => x
29
- case _ *: xs1 if n > 0 => _index(xs1, n - 1)
37
+ case _ : (x *: _) if n == 0 => erasedValue[x]
38
+ case _ : (_ *: xs1) if n > 0 => _index(erasedValue[xs1], n - 1 )
39
+ }
40
+
41
+ transparent def _head (xs : Tuple ): Any = xs match {
42
+ case _ : (x *: _) => erasedValue[x]
30
43
}
31
44
45
+ transparent def _tail (xs : Tuple ): Tuple = xs match {
46
+ case _ : (_ *: xs1) => erasedValue[xs1]
47
+ }
48
+
49
+ transparent def _concat (xs : Tuple , ys : Tuple ): Tuple = xs match {
50
+ case _ : Empty => ys
51
+ case _ : (x1 *: xs1) => _pair(erasedValue[x1], _concat(erasedValue[xs1], ys))
52
+ }
53
+
54
+ erased val e0 = _index(xs2, 0 )
55
+ erased val e1 = _index(xs2, 1 )
56
+
57
+ transparent def fromArray [T <: Tuple ](xs : Array [Object ]): T =
58
+ _size(erasedValue[T ]) match {
59
+ case 0 => ().asInstanceOf [T ]
60
+ case 1 => Tuple1 (xs(0 )).asInstanceOf [T ]
61
+ case 2 => Tuple2 (xs(0 ), xs(1 )).asInstanceOf [T ]
62
+ case 3 => Tuple3 (xs(0 ), xs(1 ), xs(2 )).asInstanceOf [T ]
63
+ case 4 => Tuple4 (xs(0 ), xs(1 ), xs(2 ), xs(3 )).asInstanceOf [T ]
64
+ case 5 => Tuple5 (xs(0 ), xs(1 ), xs(2 ), xs(3 ), xs(4 )).asInstanceOf [T ]
65
+ case 6 => Tuple6 (xs(0 ), xs(1 ), xs(2 ), xs(3 ), xs(4 ), xs(5 )).asInstanceOf [T ]
66
+ case 7 => Tuple7 (xs(0 ), xs(1 ), xs(2 ), xs(3 ), xs(4 ), xs(5 ), xs(6 )).asInstanceOf [T ]
67
+ case _ => new TupleXXL (xs).asInstanceOf [T ]
68
+ }
69
+
70
+ val emptyArray = Array [Object ]()
71
+
72
+ transparent implicit def tupleDeco (xs : Tuple ): TupleOps = new TupleOps (xs)
73
+
32
74
class TupleOps (val xs : Tuple ) extends AnyVal {
33
75
34
- transparent def *: [H] (x: H): Tuple = new *:(x, xs)
35
- transparent def size: Int = _size(xs)
76
+ transparent def toArray : Array [Object ] = _size(xs) match {
77
+ case 0 =>
78
+ emptyArray
79
+ case 1 =>
80
+ val t = xs.asInstanceOf [Tuple1 [Object ]]
81
+ Array (t._1)
82
+ case 2 =>
83
+ val t = xs.asInstanceOf [Tuple2 [Object , Object ]]
84
+ Array (t._1, t._2)
85
+ case 3 =>
86
+ val t = xs.asInstanceOf [Tuple3 [Object , Object , Object ]]
87
+ Array (t._1, t._2, t._3)
88
+ case 4 =>
89
+ val t = xs.asInstanceOf [Tuple4 [Object , Object , Object , Object ]]
90
+ Array (t._1, t._2, t._3, t._4)
91
+ case 5 =>
92
+ val t = xs.asInstanceOf [Tuple5 [Object , Object , Object , Object , Object ]]
93
+ Array (t._1, t._2, t._3, t._4, t._5)
94
+ case 6 =>
95
+ val t = xs.asInstanceOf [Tuple6 [Object , Object , Object , Object , Object , Object ]]
96
+ Array (t._1, t._2, t._3, t._4, t._5, t._6)
97
+ case 7 =>
98
+ val t = xs.asInstanceOf [Tuple7 [Object , Object , Object , Object , Object , Object , Object ]]
99
+ Array (t._1, t._2, t._3, t._4, t._5, t._6, t._7)
100
+ case _ =>
101
+ xs.asInstanceOf [TupleXXL ].elems
102
+ }
103
+
104
+ transparent def *: [H ] (x : H ): Tuple = {
105
+ erased val resTpe = Typed (_pair(x, xs))
106
+ _size(xs) match {
107
+ case 0 =>
108
+ Tuple1 (x).asInstanceOf [resTpe.Type ]
109
+ case 1 =>
110
+ Tuple2 (x, xs.asInstanceOf [Tuple1 [_]]._1).asInstanceOf [resTpe.Type ]
111
+ case 2 =>
112
+ val t = xs.asInstanceOf [Tuple2 [_, _]]
113
+ Tuple3 (x, t._1, t._2).asInstanceOf [resTpe.Type ]
114
+ case 3 =>
115
+ val t = xs.asInstanceOf [Tuple3 [_, _, _]]
116
+ Tuple4 (x, t._1, t._2, t._3).asInstanceOf [resTpe.Type ]
117
+ case 4 =>
118
+ val t = xs.asInstanceOf [Tuple4 [_, _, _, _]]
119
+ Tuple5 (x, t._1, t._2, t._3, t._4).asInstanceOf [resTpe.Type ]
120
+ case n =>
121
+ fromArray[resTpe.Type ](prepend(x, toArray))
122
+ }
123
+ }
124
+
125
+ private def prepend [H ](x : H , elems : Array [Object ]): Array [Object ] = {
126
+ val elems1 = new Array [Object ](elems.length + 1 )
127
+ elems1(0 ) = x.asInstanceOf [Object ]
128
+ Array .copy(elems, 0 , elems1, 1 , elems.length)
129
+ elems1
130
+ }
131
+
132
+ transparent def head : Any = {
133
+ erased val resTpe = Typed (_head(xs))
134
+ _size(xs) match {
135
+ case 1 =>
136
+ val t = xs.asInstanceOf [Tuple1 [_]]
137
+ t._1.asInstanceOf [resTpe.Type ]
138
+ case 2 =>
139
+ val t = xs.asInstanceOf [Tuple2 [_, _]]
140
+ t._1.asInstanceOf [resTpe.Type ]
141
+ case 3 =>
142
+ val t = xs.asInstanceOf [Tuple3 [_, _, _]]
143
+ t._1.asInstanceOf [resTpe.Type ]
144
+ case 4 =>
145
+ val t = xs.asInstanceOf [Tuple4 [_, _, _, _]]
146
+ t._1.asInstanceOf [resTpe.Type ]
147
+ case n if n > 4 && n <= MaxSpecialized =>
148
+ xs.asInstanceOf [Product ].productElement(0 ).asInstanceOf [resTpe.Type ]
149
+ case n if n > MaxSpecialized =>
150
+ val t = xs.asInstanceOf [TupleXXL ]
151
+ t.elems(0 ).asInstanceOf [resTpe.Type ]
152
+ }
153
+ }
154
+
155
+ transparent def tail : Any = {
156
+ erased val resTpe = Typed (_tail(xs))
157
+ _size(xs) match {
158
+ case 1 =>
159
+ unit
160
+ case 2 =>
161
+ val t = xs.asInstanceOf [Tuple2 [_, _]]
162
+ Tuple1 (t._2).asInstanceOf [resTpe.Type ]
163
+ case 3 =>
164
+ val t = xs.asInstanceOf [Tuple3 [_, _, _]]
165
+ Tuple2 (t._2, t._3).asInstanceOf [resTpe.Type ]
166
+ case 4 =>
167
+ val t = xs.asInstanceOf [Tuple4 [_, _, _, _]]
168
+ Tuple3 (t._2, t._3, t._4).asInstanceOf [resTpe.Type ]
169
+ case 5 =>
170
+ val t = xs.asInstanceOf [Tuple5 [_, _, _, _, _]]
171
+ Tuple4 (t._2, t._3, t._4, t._5).asInstanceOf [resTpe.Type ]
172
+ case n if n > 5 =>
173
+ fromArray[resTpe.Type ](toArray.tail)
174
+ }
175
+ }
36
176
37
177
transparent def apply (n : Int ): Any = {
38
- erased val typed = Typed(_index(xs, n))
39
- val result = _size(xs) match {
178
+ erased val resTpe = Typed (_index(xs, n))
179
+ _size(xs) match {
40
180
case 1 =>
181
+ val t = xs.asInstanceOf [Tuple1 [_]]
41
182
n match {
42
- case 1 => xs. asInstanceOf[Tuple1[_]].__1
183
+ case 0 => t._1. asInstanceOf [resTpe. Type ]
43
184
}
44
185
case 2 =>
186
+ val t = xs.asInstanceOf [Tuple2 [_, _]]
45
187
n match {
46
- case 1 => xs. asInstanceOf[Tuple2[_, _]].__1
47
- case 2 => xs. asInstanceOf[Tuple2[_, _]].__2
188
+ case 0 => t._1. asInstanceOf [resTpe. Type ]
189
+ case 1 => t._2. asInstanceOf [resTpe. Type ]
48
190
}
49
191
case 3 =>
192
+ val t = xs.asInstanceOf [Tuple3 [_, _, _]]
50
193
n match {
51
- case 1 => xs. asInstanceOf[Tuple3[_, _, _]].__1
52
- case 2 => xs. asInstanceOf[Tuple3[_, _, _]].__2
53
- case 3 => xs. asInstanceOf[Tuple3[_, _, _]].__3
194
+ case 0 => t._1. asInstanceOf [resTpe. Type ]
195
+ case 1 => t._2. asInstanceOf [resTpe. Type ]
196
+ case 2 => t._3. asInstanceOf [resTpe. Type ]
54
197
}
55
198
case 4 =>
199
+ val t = xs.asInstanceOf [Tuple4 [_, _, _, _]]
56
200
n match {
57
- case 1 => xs. asInstanceOf[Tuple4[_, _, _, _]].__1
58
- case 2 => xs. asInstanceOf[Tuple4[_, _, _, _]].__2
59
- case 3 => xs. asInstanceOf[Tuple4[_, _, _, _]].__3
60
- case 4 => xs. asInstanceOf[Tuple4[_, _, _, _]].__4
201
+ case 0 => t._1. asInstanceOf [resTpe. Type ]
202
+ case 1 => t._2. asInstanceOf [resTpe. Type ]
203
+ case 2 => t._3. asInstanceOf [resTpe. Type ]
204
+ case 3 => t._4. asInstanceOf [resTpe. Type ]
61
205
}
206
+ case s if s > 4 && s <= MaxSpecialized && n >= 0 && n < s =>
207
+ xs.asInstanceOf [Product ].productElement(n).asInstanceOf [resTpe.Type ]
208
+ case s if s > MaxSpecialized && n >= 0 && n < s =>
209
+ xs.asInstanceOf [TupleXXL ].elems(n).asInstanceOf [resTpe.Type ]
62
210
}
63
- result.asInstanceOf[typed.Type]
64
211
}
65
- transparent def **: (ys: Tuple): Tuple = ys match {
66
- case Empty => xs
67
- case y *: ys1 => y *: (ys1 **: xs)
68
- }
69
- transparent def head = xs match {
70
- case x *: _ => x
71
- }
72
- transparent def tail = xs match {
73
- case _ *: xs => xs
74
- }
75
- }
76
212
77
- val emptyArray = Array[Object]()
78
-
79
- transparent def toObj(t: Any) = t.asInstanceOf[Object]
213
+ transparent def ++ (ys : Tuple ): Tuple = {
214
+ erased val resTpe = Typed (_concat(xs, ys))
215
+ _size(xs) match {
216
+ case 0 => ys
217
+ case 1 =>
218
+ if (_size(ys) == 0 ) xs
219
+ else xs.head *: ys
220
+ case 2 =>
221
+ val t = xs.asInstanceOf [Tuple2 [_, _]]
222
+ _size(ys) match {
223
+ case 0 => xs
224
+ case 1 =>
225
+ val u = ys.asInstanceOf [Tuple1 [_]]
226
+ Tuple3 (t._1, t._2, u._1).asInstanceOf [resTpe.Type ]
227
+ case 2 =>
228
+ val u = ys.asInstanceOf [Tuple2 [_, _]]
229
+ Tuple4 (t._1, t._2, u._1, u._2).asInstanceOf [resTpe.Type ]
230
+ case _ =>
231
+ genericConcat[resTpe.Type ](xs, ys)
232
+ }
233
+ case 3 =>
234
+ val t = xs.asInstanceOf [Tuple3 [_, _, _]]
235
+ _size(ys) match {
236
+ case 0 => xs
237
+ case 1 =>
238
+ val u = ys.asInstanceOf [Tuple1 [_]]
239
+ Tuple4 (t._1, t._2, t._3, u._1).asInstanceOf [resTpe.Type ]
240
+ case _ =>
241
+ genericConcat[resTpe.Type ](xs, ys)
242
+ }
243
+ case _ =>
244
+ if (_size(ys) == 0 ) xs
245
+ else genericConcat[resTpe.Type ](xs, ys)
246
+ }
247
+ }
80
248
81
- transparent def toArray(t: Tuple): Array[Object] = t.size match {
82
- case 0 => emptyArray
83
- case 1 => Array(toObj(t(0)))
84
- case 2 => Array(toObj(t(0)), toObj(t(1)))
85
- case 3 => Array(toObj(t(0)), toObj(t(1)), toObj(t(2)))
86
- case 4 => Array(toObj(t(0)), toObj(t(1)), toObj(t(2)), toObj(t(3)))
249
+ transparent def genericConcat [T <: Tuple ](xs : Tuple , ys : Tuple ): Tuple =
250
+ fromArray[T ](xs.toArray ++ ys.toArray)
87
251
}
88
-
89
- transparent implicit def tupleDeco(xs: Tuple): TupleOps = new TupleOps(xs)
90
-
91
- transparent def apply(): Tuple = Empty
92
- transparent def apply(x1: Any): Tuple = x1 *: Empty
93
- transparent def apply(x1: Any, x2: Any) = x1 *: x2 *: Empty
94
- transparent def apply(x1: Any, x2: Any, x3: Any) = x1 *: x2 *: x3 *: Empty
95
-
96
- val xs0 = Tuple()
97
- val xs1 = Tuple(2)
98
- val xs2 = Tuple(2, "a")
99
- val xs3 = Tuple(true, 1, 2.0)
100
- transparent val s0 = xs0.size; val s0c: 0 = s0
101
- transparent val s1 = xs1.size; val s1c: 1 = s1
102
- transparent val s2 = xs2.size; val s2c: 2 = s2
103
- transparent val s3 = xs3.size; val s3c: 3 = s3
104
- val e0 = xs3(0); val e0c: Boolean = e0
105
- val e1 = xs3(1); val e1c: Int = e1
106
- val e2 = xs3(2); val e2c: Double = e2
107
-
108
- val conc0 = xs0 **: xs3
109
- val conc1 = xs3 **: xs0
110
- val conc2 = xs2 **: xs3
111
- val e3c: Int = conc0(1)
112
- val e4c: Int = conc1(1)
113
- val e5c: Int = conc2(0)
114
- val e6c: Double = conc2(4)
115
- */
116
252
}
117
- /*
118
- class Tuple1[+T1](val __1: T1) extends *:(__1, Empty)
119
- class Tuple2[+T1, +T2](val __1: T1, val __2: T2) extends *:(__1, *:(__2, Empty))
120
- class Tuple3[+T1, +T2, +T3](val __1: T1, val __2: T2, val __3: T3) extends *:(__1, *:(__2, *:(__3, Empty)))
121
- class Tuple4[+T1, +T2, +T3, +T4](val __1: T1, val __2: T2, val __3: T3, val __4: T4) extends *:(__1, *:(__2, *:(__3, *:(__4, Empty))))
122
-
123
- object Test extends App
124
- */
253
+ }
254
+ object Test extends App {
255
+ import test ._
256
+ import Tuples ._
257
+ import typelevel ._
258
+ val x0 = unit
259
+ val x1 = 1 *: x0
260
+ val x2 = " A" *: x1
261
+ val x3 = 2 *: x2
262
+ val x4 = " B" *: x3
263
+ val x5 = 3 *: x4
264
+ val x6 = " C" *: x5
265
+ val x7 = 4 *: x6
266
+ val x8 = " D" *: x7
267
+ val h1 = x1.head; val h1c : Int = h1
268
+ val h2 = x2.head; val h2c : String = h2
269
+ val h7 = x7.head; val h7c : Int = h7
270
+ val h8 = x8.head; val h8c : String = h8
271
+ val t1 = x1.tail; val t1c : Empty = t1
272
+ val t2 = x2.tail; val t2c : Int *: Empty = t2
273
+ val t7 = x7.tail; val t7c : String *: Int *: Empty = t7.tail.tail.tail.tail
274
+ val t8 = x8.tail; val t8c : Int = t8(6 )
275
+ val a1_0 = x1(0 ); val a1_0c : Int = a1_0
276
+ val a2_0 = x2(0 ); val a2_0c : String = a2_0
277
+ val a3_1 = x3(1 ); val a3_1c : String = a3_1
278
+ val a4_3 = x4(3 ); val a4_3c : Int = a4_3
279
+ val a6_4 = x6(4 ); val a6_4c : String = a6_4
280
+ val a8_0 = x8(0 ); val a8_0c : String = a8_0
281
+ val c0_0 = x0 ++ x0; val c0_0c : Empty = c0_0
282
+ val c0_1 = x0 ++ x1; val c0_1c : Int *: Empty = c0_1c
283
+ val c1_0 = x1 ++ x0; val c1_0c : Int *: Empty = c1_0c
284
+ val c0_4 = x0 ++ x4; val c0_4c : String *: Int *: String *: Int *: Empty = c0_4
285
+ val c4_0 = x4 ++ x0; val c4_0c : String *: Int *: String *: Int *: Empty = c4_0
286
+ val c1_1 = x1 ++ x1; val c1_1c : Int *: Int *: Empty = c1_1
287
+ val c1_8 = x1 ++ x8; val c1_8c : Int *: String *: Int *: String *: Int *: String *: Int *: String *: Int *: Empty = c1_8
288
+ val c2_1 = x2 ++ x1; val c2_1c : String *: Int *: Int *: Empty = c2_1
289
+ val c2_2 = x2 ++ x2; val c2_2c : String *: Int *: String *: Int *: Empty = c2_2
290
+ val c2_3 = x2 ++ x3; val c2_3c : String *: Int *: Int *: String *: Int *: Empty = c2_3
291
+ val c3_3 = x3 ++ x3; val c3_3c : Int *: String *: Int *: Int *: String *: Int *: Empty = c3_3
292
+ }
0 commit comments