Skip to content

Commit dcddc4b

Browse files
committed
Simplify test
1 parent b0b2383 commit dcddc4b

File tree

1 file changed

+28
-134
lines changed

1 file changed

+28
-134
lines changed

tests/run/typeclass-derivation2b.scala

Lines changed: 28 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -5,95 +5,32 @@ import scala.annotation.tailrec
55
// The real typeclass derivation is tested in typeclass-derivation3.scala.
66
object TypeLevel {
77

8-
/** A generic representation of a case in an ADT
9-
* @param deriving The companion object of the ADT
10-
* @param ordinal The ordinal value of the case in the list of the ADT's cases
11-
* @param elems The elements of the case
12-
*/
13-
class Mirror(val ordinal: Int, val elems: Product) {
14-
15-
/** The `n`'th element of this generic case */
16-
def apply(n: Int): Any = elems.productElement(n)
17-
}
18-
198
object EmptyProduct extends Product {
209
def canEqual(that: Any): Boolean = true
2110
def productElement(n: Int) = throw new IndexOutOfBoundsException
2211
def productArity = 0
2312
}
2413

25-
object Mirror {
26-
27-
/** A mirror of case with ordinal number `ordinal` and elements as given by `Product` */
28-
def apply(ordinal: Int, product: Product): Mirror =
29-
new Mirror(ordinal, product)
30-
31-
/** A mirror with elements given as an array */
32-
def apply(ordinal: Int, elems: Array[AnyRef]): Mirror =
33-
apply(ordinal, new ArrayProduct(elems))
34-
35-
/** A mirror with an initial empty array of `numElems` elements, to be filled in. */
36-
def apply(ordinal: Int, numElems: Int): Mirror =
37-
apply(ordinal, new Array[AnyRef](numElems))
38-
39-
/** A mirror of a case with no elements */
40-
def apply(ordinal: Int): Mirror =
41-
apply(ordinal, EmptyProduct)
42-
43-
/** Helper class to turn arrays into products */
44-
private class ArrayProduct(val elems: Array[AnyRef]) extends Product {
45-
def canEqual(that: Any): Boolean = true
46-
def productElement(n: Int) = elems(n)
47-
def productArity = elems.length
48-
override def productIterator: Iterator[Any] = elems.iterator
49-
def update(n: Int, x: Any) = elems(n) = x.asInstanceOf[AnyRef]
50-
}
51-
52-
/** Helper object */
53-
private object EmptyProduct extends Product {
54-
def canEqual(that: Any): Boolean = true
55-
def productElement(n: Int) = throw new IndexOutOfBoundsException
56-
def productArity = 0
57-
}
58-
}
59-
60-
/** The shape of an ADT.
61-
* This is eithe a product (`Case`) or a sum (`Cases`) of products.
62-
*/
63-
enum Shape {
64-
65-
/** A sum with alternative types `Alts` */
66-
case Cases[Alts <: Tuple]
67-
68-
/** A product type `T` with element types `Elems` */
69-
case Case[T, Elems <: Tuple]
14+
/** Helper class to turn arrays into products */
15+
class ArrayProduct(val elems: Array[AnyRef]) extends Product {
16+
def canEqual(that: Any): Boolean = true
17+
def productElement(n: Int) = elems(n)
18+
def productArity = elems.length
19+
override def productIterator: Iterator[Any] = elems.iterator
20+
def update(n: Int, x: Any) = elems(n) = x.asInstanceOf[AnyRef]
7021
}
7122

72-
/** Every generic derivation starts with a typeclass instance of this type.
73-
* It informs that type `T` has shape `S` and also implements runtime reflection on `T`.
74-
*/
7523
abstract class Generic[T] {
76-
/** The shape of the `T` */
77-
type Shape <: TypeLevel.Shape
78-
79-
80-
/** The case mirror corresponding to ADT instance `x` */
81-
def reflect(x: T): Mirror
82-
83-
/** The ADT instance corresponding to given `mirror` */
84-
def reify(mirror: Mirror): T
85-
}
86-
87-
abstract class Generic2[T] {
8824
type Shape <: Tuple
8925
}
9026

91-
abstract class GenericSum[S] extends Generic2[S] {
27+
abstract class GenericSum[S] extends Generic[S] {
9228
def ordinal(x: S): Int
9329
def alternative(n: Int): GenericProduct[_ <: S] = ???
9430
}
9531

96-
abstract class GenericProduct[P] extends Generic2[P] {
32+
abstract class GenericProduct[P] extends Generic[P] {
33+
type Prod = P
9734
def toProduct(x: P): Product
9835
def fromProduct(p: Product): P
9936
}
@@ -106,22 +43,7 @@ object Lst {
10643
// common compiler-generated infrastructure
10744
import TypeLevel._
10845

109-
class GenericLst[T] extends Generic[Lst[T]] {
110-
type Shape = Shape.Cases[(
111-
Shape.Case[Cons[T], (T, Lst[T])],
112-
Shape.Case[Nil.type, Unit]
113-
)]
114-
def reflect(xs: Lst[T]): Mirror = xs match {
115-
case xs: Cons[T] => Mirror(0, xs)
116-
case Nil => Mirror(1)
117-
}
118-
def reify(c: Mirror): Lst[T] = c.ordinal match {
119-
case 0 => Cons[T](c(0).asInstanceOf, c(1).asInstanceOf)
120-
case 1 => Nil
121-
}
122-
}
123-
124-
class Generic2Lst[T] extends GenericSum[Lst[T]] {
46+
class GenericLst[T] extends GenericSum[Lst[T]] {
12547
override type Shape = (Cons[T], Nil.type)
12648
def ordinal(x: Lst[T]) = x match {
12749
case x: Cons[_] => 0
@@ -135,7 +57,6 @@ object Lst {
13557
}
13658

13759
implicit def GenericLst[T]: GenericLst[T] = new GenericLst[T]
138-
implicit def Generic2Lst[T]: Generic2Lst[T] = new Generic2Lst[T]
13960

14061
case class Cons[T](hd: T, tl: Lst[T]) extends Lst[T]
14162

@@ -144,7 +65,8 @@ object Lst {
14465
type Shape = (T, Lst[T])
14566
def toProduct(x: Cons[T]): Product = x
14667
def fromProduct(p: Product): Cons[T] =
147-
Cons(p.productElement(0).asInstanceOf, p.productElement(1).asInstanceOf)
68+
Cons(p.productElement(0).asInstanceOf[T],
69+
p.productElement(1).asInstanceOf[Cons[T]])
14870
}
14971
implicit def GenericCons[T]: GenericCons[T] = new GenericCons[T]
15072
}
@@ -176,69 +98,41 @@ object Eq {
17698
case eq: Eq[T] => eq.eql(x, y)
17799
}
178100

179-
inline def eqlElems[Elems <: Tuple](xm: Mirror, ym: Mirror, n: Int): Boolean =
101+
inline def eqlElems[Elems <: Tuple](x: Product, y: Product, n: Int): Boolean =
180102
inline erasedValue[Elems] match {
181103
case _: (elem *: elems1) =>
182-
tryEql[elem](xm(n).asInstanceOf, ym(n).asInstanceOf) &&
183-
eqlElems[elems1](xm, ym, n + 1)
104+
tryEql[elem](
105+
x.productElement(n).asInstanceOf[elem],
106+
y.productElement(n).asInstanceOf[elem]) &&
107+
eqlElems[elems1](x, y, n + 1)
184108
case _: Unit =>
185109
true
186110
}
187111

188-
inline def eqlCases[Alts <: Tuple](xm: Mirror, ym: Mirror, n: Int): Boolean =
189-
inline erasedValue[Alts] match {
190-
case _: (Shape.Case[alt, elems] *: alts1) =>
191-
if (xm.ordinal == n) eqlElems[elems](xm, ym, 0)
192-
else eqlCases[alts1](xm, ym, n + 1)
193-
case _: Unit =>
194-
false
195-
}
196-
197-
inline def eqlProducts[Elems <: Tuple](x: Product, y: Product, n: Int): Boolean =
198-
inline erasedValue[Elems] match {
199-
case _: (elem *: elems1) =>
200-
tryEql[elem](x.productElement(n).asInstanceOf, y.productElement(n).asInstanceOf) &&
201-
eqlProducts[elems1](x, y, n + 1)
202-
case _: Unit =>
203-
true
204-
}
205-
206-
inline def eqlAlts[T, Alts <: Tuple](x: T, y: T, genSum: GenericSum[T], ord: Int, inline n: Int): Boolean =
112+
inline def eqlCases[T, Alts <: Tuple](x: T, y: T, genSum: GenericSum[T], ord: Int, inline n: Int): Boolean =
207113
inline erasedValue[Alts] match {
208114
case _: (alt *: alts1) =>
209115
if (ord == n)
210116
inline genSum.alternative(n) match {
211-
case genProd => eqlProducts[genProd.Shape](
212-
genProd.toProduct(x.asInstanceOf),
213-
genProd.toProduct(y.asInstanceOf), 0)
117+
case cas =>
118+
eqlElems[cas.Shape](
119+
cas.toProduct(x.asInstanceOf[cas.Prod]),
120+
cas.toProduct(y.asInstanceOf[cas.Prod]),
121+
0)
214122
}
215-
else eqlAlts[T, alts1](x, y, genSum, ord, n + 1)
123+
else eqlCases[T, alts1](x, y, genSum, ord, n + 1)
216124
case _: Unit =>
217125
false
218126
}
219127

220-
inline def derived[T](implicit ev: Generic2[T]): Eq[T] = new Eq[T] {
128+
inline def derived[T](implicit ev: Generic[T]): Eq[T] = new Eq[T] {
221129
def eql(x: T, y: T): Boolean = {
222130
inline ev match {
223131
case evv: GenericSum[T] =>
224132
val ord = evv.ordinal(x)
225-
ord == evv.ordinal(y) && eqlAlts[T, evv.Shape](x, y, evv, ord, 0)
133+
ord == evv.ordinal(y) && eqlCases[T, evv.Shape](x, y, evv, ord, 0)
226134
case evv: GenericProduct[T] =>
227-
eqlProducts[evv.Shape](evv.toProduct(x), evv.toProduct(y), 0)
228-
}
229-
}
230-
}
231-
232-
inline def derived2[T, S <: Shape](implicit ev: Generic[T]): Eq[T] = new {
233-
def eql(x: T, y: T): Boolean = {
234-
val xm = ev.reflect(x)
235-
val ym = ev.reflect(y)
236-
inline erasedValue[ev.Shape] match {
237-
case _: Shape.Cases[alts] =>
238-
xm.ordinal == ym.ordinal &&
239-
eqlCases[alts](xm, ym, 0)
240-
case _: Shape.Case[_, elems] =>
241-
eqlElems[elems](xm, ym, 0)
135+
eqlElems[evv.Shape](evv.toProduct(x), evv.toProduct(y), 0)
242136
}
243137
}
244138
}

0 commit comments

Comments
 (0)