@@ -5,26 +5,9 @@ import scala.annotation.tailrec
55
66// -- Classes and Objects of the Derivation Framework ----------------------------------
77
8- /** Simulates the scala.reflect package */
8+ /** Core classes. In the current implementation these are in the scala.reflect package */
99object Deriving {
1010
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-
2811 /** The Generic class hierarchy allows typelevel access to
2912 * enums, case classes and objects, and their sealed parents.
3013 */
@@ -48,22 +31,47 @@ object Deriving {
4831 erased def alternative (n : Int ): Generic [_ <: T ] = ???
4932 }
5033
51- /** A Generic for a product type */
34+ /** The Generic for a product type */
5235 abstract class Product [T ] extends Generic [T ] {
36+
37+ /** The types of the elements */
5338 type ElemTypes <: Tuple
39+
40+ /** The name of the whole product type */
5441 type CaseLabel <: String
42+
43+ /** The names of the product elements */
5544 type ElemLabels <: Tuple
5645
46+ /** Create a new instance of type `T` with elements taken from product `p`. */
5747 def fromProduct (p : scala.Product ): T
5848 }
5949
50+ /** The Generic for a singleton */
6051 trait Singleton [T ] extends Generic [T ] {
52+
53+ /** The name of the singleton */
54+ type CaseLabel <: String
55+
56+ /** The represented value */
6157 inline def singletonValue = implicit match {
6258 case ev : ValueOf [T ] => ev.value
6359 }
64- type CaseLabel <: String
6560 }
6661 }
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 ]
6775}
6876import Deriving ._
6977
@@ -183,6 +191,18 @@ object Right extends Generic.Product[Right[_]] {
183191// -- Type classes ------------------------------------------------------------
184192
185193// 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).
186206
187207// Equality typeclass
188208trait Eq [T ] {
@@ -286,13 +306,9 @@ object Pickler {
286306
287307 inline def unpickleProduct [T ](g : Generic .Product [T ])(buf : mutable.ListBuffer [Int ]): T = {
288308 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))
296312 }
297313
298314 inline def unpickleCases [T ](g : Generic .Sum [T ], n : Int )(buf : mutable.ListBuffer [Int ], ord : Int ): T =
0 commit comments