@@ -4,72 +4,85 @@ import scala.annotation.tailrec
44trait Deriving {
55 import Deriving ._
66
7- protected def caseNames : Array [String ]
7+ /** A mirror of case with ordinal number `ordinal` and elements as given by `Product` */
8+ def mirror [T ](ordinal : Int , product : Product ): CaseMirror [T ] =
9+ new CaseMirror (this , ordinal, product)
10+
11+ /** A mirror with elements given as an array */
12+ def mirror [T ](ordinal : Int , elems : Array [AnyRef ]): CaseMirror [T ] =
13+ mirror(ordinal, new ArrayProduct (elems))
14+
15+ /** A mirror with an initial empty array of `numElems` elements, to be filled in. */
16+ def mirror [T ](ordinal : Int , numElems : Int ): CaseMirror [T ] =
17+ mirror(ordinal, new Array [AnyRef ](numElems))
18+
19+ /** A mirror of a case with no elements */
20+ def mirror [T ](ordinal : Int ): CaseMirror [T ] =
21+ mirror(ordinal, EmptyProduct )
22+
23+ /** The case and element labels of the described ADT as encoded strings. */
24+ protected def caseLabels : Array [String ]
825
926 private final val separator = '\000 '
1027
11- private def cname (ordinal : Int , idx : Int ): String = {
12- val cnames = caseNames (ordinal)
28+ private def label (ordinal : Int , idx : Int ): String = {
29+ val labels = caseLabels (ordinal)
1330 @ tailrec def separatorPos (from : Int ): Int =
14- if (from == cnames .length || cnames (from) == separator) from
31+ if (from == labels .length || labels (from) == separator) from
1532 else separatorPos(from + 1 )
16- @ tailrec def findName (count : Int , idx : Int ): String =
17- if (idx == cnames .length) " "
18- else if (count == 0 ) cnames .substring(idx, separatorPos(idx))
19- else findName (if (cnames (idx) == separator) count - 1 else count, idx + 1 )
20- findName (idx, 0 )
33+ @ tailrec def findLabel (count : Int , idx : Int ): String =
34+ if (idx == labels .length) " "
35+ else if (count == 0 ) labels .substring(idx, separatorPos(idx))
36+ else findLabel (if (labels (idx) == separator) count - 1 else count, idx + 1 )
37+ findLabel (idx, 0 )
2138 }
22-
23- def caseName (ordinal : Int ): String = cname(ordinal, 0 )
24- def elementName (ordinal : Int , idx : Int ) = cname(ordinal, idx + 1 )
2539}
2640
2741// Generic deriving infrastructure
2842object Deriving {
2943
30- /** The shape of an ADT in a sum of products representation */
31- enum Shape {
32- /** A sum with alternative types `Alts` */
33- case Cases [Alts <: Tuple ]
34-
35- /** A product type `T` with element types `Elems` */
36- case Case [T , Elems <: Tuple ]
37- }
38-
3944 /** A generic representation of a case in an ADT
45+ * @param deriving The companion object of the ADT
4046 * @param ordinal The ordinal value of the case in the list of the ADT's cases
4147 * @param elems The elements of the case
4248 */
4349 class CaseMirror [+ T ](val deriving : Deriving , val ordinal : Int , val elems : Product ) {
4450
45- /** A generic case with elements given as an array */
46- def this (deriving : Deriving , ordinal : Int , elems : Array [AnyRef ]) =
47- this (deriving, ordinal, new ArrayProduct (elems))
48-
49- /** A generic case with an initial empty array of `numElems` elements, to be filled in. */
50- def this (deriving : Deriving , ordinal : Int , numElems : Int ) =
51- this (deriving, ordinal, new Array [AnyRef ](numElems))
52-
53- /** A generic case with no elements */
54- def this (deriving : Deriving , ordinal : Int ) =
55- this (deriving, ordinal, EmptyProduct )
56-
5751 /** The `n`'th element of this generic case */
5852 def apply (n : Int ): Any = elems.productElement(n)
5953
60- def caseName : String = deriving.caseName(ordinal)
61- def elementName (idx : Int ) = deriving.elementName(ordinal, idx)
54+ /** The name of the constructor of the case reflected by this mirror */
55+ def caseLabel : String = deriving.label(ordinal, 0 )
56+
57+ /** The label of the `n`'th element of the case reflected by this mirror */
58+ def elementLabel (n : Int ) = deriving.label(ordinal, n + 1 )
6259 }
6360
6461 /** A class for mapping between an ADT value and
6562 * the case mirror that represents the value.
6663 */
6764 abstract class Reflected [T ] {
65+
66+ /** The case mirror corresponding to ADT instance `x` */
6867 def reflect (x : T ): CaseMirror [T ]
69- def reify (c : CaseMirror [T ]): T
68+
69+ /** The ADT instance corresponding to given `mirror` */
70+ def reify (mirror : CaseMirror [T ]): T
71+
72+ /** The companion object of the ADT */
7073 def deriving : Deriving
7174 }
7275
76+ /** The shape of an ADT in a sum of products representation */
77+ enum Shape {
78+
79+ /** A sum with alternative types `Alts` */
80+ case Cases [Alts <: Tuple ]
81+
82+ /** A product type `T` with element types `Elems` */
83+ case Case [T , Elems <: Tuple ]
84+ }
85+
7386 /** Every generic derivation starts with a typeclass instance of this type.
7487 * It informs that type `T` has shape `S` and also allows runtime reflection on `T`.
7588 */
@@ -108,11 +121,11 @@ object Lst extends Deriving {
108121 Shape .Case [Nil .type , Unit ]
109122 )]
110123
111- val NilMirror = new CaseMirror [Nil .type ](Lst , 1 )
124+ val NilMirror = mirror [Nil .type ](1 )
112125
113126 implicit def lstShape [T ]: Shaped [Lst [T ], Shape [T ]] = new {
114127 def reflect (xs : Lst [T ]): CaseMirror [Lst [T ]] = xs match {
115- case xs : Cons [T ] => new CaseMirror [Cons [T ]](Lst , 0 , xs)
128+ case xs : Cons [T ] => mirror [Cons [T ]](0 , xs)
116129 case Nil => NilMirror
117130 }
118131 def reify (c : CaseMirror [Lst [T ]]): Lst [T ] = c.ordinal match {
@@ -122,7 +135,7 @@ object Lst extends Deriving {
122135 def deriving = Lst
123136 }
124137
125- protected val caseNames = Array (" Cons\000 hd\000 tl" , " Nil" )
138+ protected val caseLabels = Array (" Cons\000 hd\000 tl" , " Nil" )
126139
127140 // three clauses that could be generated from a `derives` clause
128141 implicit def LstEq [T : Eq ]: Eq [Lst [T ]] = Eq .derived
@@ -141,13 +154,13 @@ object Pair extends Deriving {
141154
142155 implicit def pairShape [T ]: Shaped [Pair [T ], Shape [T ]] = new {
143156 def reflect (xy : Pair [T ]) =
144- new CaseMirror [Pair [T ]](Pair , 0 , xy)
157+ mirror [Pair [T ]](0 , xy)
145158 def reify (c : CaseMirror [Pair [T ]]): Pair [T ] =
146159 Pair (c(0 ).asInstanceOf , c(1 ).asInstanceOf )
147160 def deriving = Pair
148161 }
149162
150- protected val caseNames = Array (" Pair\000 x\000 y" )
163+ protected val caseLabels = Array (" Pair\000 x\000 y" )
151164
152165 // two clauses that could be generated from a `derives` clause
153166 implicit def PairEq [T : Eq ]: Eq [Pair [T ]] = Eq .derived
@@ -263,11 +276,11 @@ object Pickler {
263276 inline def unpickleCase [T , Elems <: Tuple ](r : Reflected [T ], buf : mutable.ListBuffer [Int ], ordinal : Int ): T = {
264277 inline val size = constValue[Tuple .Size [Elems ]]
265278 inline if (size == 0 )
266- r.reify(new CaseMirror [T ](r.deriving, ordinal))
279+ r.reify(r.deriving.mirror [T ](ordinal))
267280 else {
268281 val elems = new Array [Object ](size)
269282 unpickleElems[Elems ](buf, elems, 0 )
270- r.reify(new CaseMirror [T ](r.deriving, ordinal, elems))
283+ r.reify(r.deriving.mirror [T ](ordinal, elems))
271284 }
272285 }
273286
@@ -301,7 +314,7 @@ object Pickler {
301314 }
302315}
303316
304- // A third typeclass, making use of names
317+ // A third typeclass, making use of labels
305318trait Show [T ] {
306319 def show (x : T ): String
307320}
@@ -316,7 +329,7 @@ object Show {
316329 inline def showElems [Elems <: Tuple ](elems : CaseMirror [_], n : Int ): List [String ] =
317330 inline erasedValue[Elems ] match {
318331 case _ : (elem *: elems1) =>
319- val formal = elems.elementName (n)
332+ val formal = elems.elementLabel (n)
320333 val actual = tryShow[elem](elems(n).asInstanceOf )
321334 s " $formal = $actual" :: showElems[elems1](elems, n + 1 )
322335 case _ : Unit =>
@@ -326,7 +339,7 @@ object Show {
326339 inline def showCase [T , Elems <: Tuple ](r : Reflected [T ], x : T ): String = {
327340 val mirror = r.reflect(x)
328341 val args = showElems[Elems ](mirror, 0 ).mkString(" , " )
329- s " ${mirror.caseName }( $args) "
342+ s " ${mirror.caseLabel }( $args) "
330343 }
331344
332345 inline def showCases [T , Alts <: Tuple ](r : Reflected [T ], x : T ): String =
0 commit comments