@@ -5,26 +5,9 @@ import scala.annotation.tailrec
5
5
6
6
// -- Classes and Objects of the Derivation Framework ----------------------------------
7
7
8
- /** Simulates the scala.reflect package */
8
+ /** Core classes. In the current implementation these are in the scala.reflect package */
9
9
object Deriving {
10
10
11
- object EmptyProduct extends Product {
12
- def canEqual (that : Any ): Boolean = true
13
- def productElement (n : Int ) = throw new IndexOutOfBoundsException
14
- def productArity = 0
15
- }
16
-
17
- /** Helper class to turn arrays into products */
18
- class ArrayProduct (val elems : Array [AnyRef ]) extends Product {
19
- def canEqual (that : Any ): Boolean = true
20
- def productElement (n : Int ) = elems(n)
21
- def productArity = elems.length
22
- override def productIterator : Iterator [Any ] = elems.iterator
23
- def update (n : Int , x : Any ) = elems(n) = x.asInstanceOf [AnyRef ]
24
- }
25
-
26
- def productElement [T ](x : Any , idx : Int ) = x.asInstanceOf [Product ].productElement(idx).asInstanceOf [T ]
27
-
28
11
/** The Generic class hierarchy allows typelevel access to
29
12
* enums, case classes and objects, and their sealed parents.
30
13
*/
@@ -48,22 +31,47 @@ object Deriving {
48
31
erased def alternative (n : Int ): Generic [_ <: T ] = ???
49
32
}
50
33
51
- /** A Generic for a product type */
34
+ /** The Generic for a product type */
52
35
abstract class Product [T ] extends Generic [T ] {
36
+
37
+ /** The types of the elements */
53
38
type ElemTypes <: Tuple
39
+
40
+ /** The name of the whole product type */
54
41
type CaseLabel <: String
42
+
43
+ /** The names of the product elements */
55
44
type ElemLabels <: Tuple
56
45
46
+ /** Create a new instance of type `T` with elements taken from product `p`. */
57
47
def fromProduct (p : scala.Product ): T
58
48
}
59
49
50
+ /** The Generic for a singleton */
60
51
trait Singleton [T ] extends Generic [T ] {
52
+
53
+ /** The name of the singleton */
54
+ type CaseLabel <: String
55
+
56
+ /** The represented value */
61
57
inline def singletonValue = implicit match {
62
58
case ev : ValueOf [T ] => ev.value
63
59
}
64
- type CaseLabel <: String
65
60
}
66
61
}
62
+
63
+ /** Helper class to turn arrays into products */
64
+ class ArrayProduct (val elems : Array [AnyRef ]) extends Product {
65
+ def canEqual (that : Any ): Boolean = true
66
+ def productElement (n : Int ) = elems(n)
67
+ def productArity = elems.length
68
+ override def productIterator : Iterator [Any ] = elems.iterator
69
+ def update (n : Int , x : Any ) = elems(n) = x.asInstanceOf [AnyRef ]
70
+ }
71
+
72
+ /** Helper method to select a product element */
73
+ def productElement [T ](x : Any , idx : Int ) =
74
+ x.asInstanceOf [Product ].productElement(idx).asInstanceOf [T ]
67
75
}
68
76
import Deriving ._
69
77
@@ -183,6 +191,18 @@ object Right extends Generic.Product[Right[_]] {
183
191
// -- Type classes ------------------------------------------------------------
184
192
185
193
// Everything here is hand-written by the authors of the derivable typeclasses
194
+ // The same schema is used throughout.
195
+ //
196
+ // - A typeclass implements an inline `derived` method, given a `Generic` instance.
197
+ // - Each implemented typeclass operation `xyz` calls 4 inline helper methods:
198
+ // 1. `xyzCases` for sums,
199
+ // 2. `xyzProduct` for products,
200
+ // 3. `xyzElems` stepping through the elements of a product,
201
+ // 4. `tryXyz` for searching the implicit to handles a single element.
202
+ // - The first three methods have two parameter lists. The first parameter
203
+ // list contains inline parameters that guide the code generation, whereas
204
+ // the second parameter list contains parameters that show up in the
205
+ // generated code. (This is done just to make things clearer).
186
206
187
207
// Equality typeclass
188
208
trait Eq [T ] {
@@ -286,13 +306,9 @@ object Pickler {
286
306
287
307
inline def unpickleProduct [T ](g : Generic .Product [T ])(buf : mutable.ListBuffer [Int ]): T = {
288
308
inline val size = constValue[Tuple .Size [g.ElemTypes ]]
289
- inline if (size == 0 )
290
- g.fromProduct(EmptyProduct )
291
- else {
292
- val elems = new Array [Object ](size)
293
- unpickleElems[g.ElemTypes ](0 )(buf, elems)
294
- g.fromProduct(ArrayProduct (elems))
295
- }
309
+ val elems = new Array [Object ](size)
310
+ unpickleElems[g.ElemTypes ](0 )(buf, elems)
311
+ g.fromProduct(ArrayProduct (elems))
296
312
}
297
313
298
314
inline def unpickleCases [T ](g : Generic .Sum [T ], n : Int )(buf : mutable.ListBuffer [Int ], ord : Int ): T =
0 commit comments