@@ -3,21 +3,21 @@ import scala.annotation.tailrec
3
3
4
4
// The following command:
5
5
//
6
- // sc typeclass-scaling.scala -Xmax-inlines 100 -Xprint:front -color:never -Yshow-no-inline - pagewidth 1000 >& x
6
+ // sc typeclass-scaling.scala -Xmax-inlines 100 -Xprint:front -color:never -pagewidth 1000 >& x
7
7
//
8
8
// produces an output file with `wc` measures (lines/words/chars):
9
9
//
10
- // 83434 140554 6384738
10
+ // 89327 162884 7220258
11
11
//
12
12
// The command
13
13
//
14
14
// time sc typeclass-scaling.scala -Xmax-inlines 100
15
15
//
16
16
// gives (best of three):
17
17
//
18
- // real 0m16.061s
19
- // user 1m3.608s
20
- // sys 0m1.314s
18
+ // real 0m16.593s
19
+ // user 1m6.337s
20
+ // sys 0m1.344s
21
21
object datatypes {
22
22
import typeclasses ._
23
23
@@ -215,42 +215,45 @@ object typeclasses {
215
215
object Eq {
216
216
import scala .compiletime .erasedValue
217
217
import compiletime ._
218
- import reflect .{ Mirror , Generic }
218
+ import scala . deriving . _
219
219
220
- inline def tryEql [T ](x : T , y : T ) = implicit match {
221
- case eq : Eq [T ] => eq.eql(x, y)
220
+ inline def tryEql [TT ](x : TT , y : TT ) : Boolean = implicit match {
221
+ case eq : Eq [TT ] => eq.eql(x, y)
222
222
}
223
223
224
- inline def eqlElems [Elems <: Tuple ](xs : Mirror , ys : Mirror , n : Int ): Boolean =
224
+ inline def eqlElems [Elems <: Tuple ](n : Int )( x : Any , y : Any ): Boolean =
225
225
inline erasedValue[Elems ] match {
226
226
case _ : (elem *: elems1) =>
227
- tryEql[elem](xs(n). asInstanceOf , ys(n). asInstanceOf ) &&
228
- eqlElems[elems1](xs, ys, n + 1 )
227
+ tryEql[elem](productElement[elem](x, n), productElement[elem](y, n) ) &&
228
+ eqlElems[elems1](n + 1 )(x, y )
229
229
case _ : Unit =>
230
230
true
231
231
}
232
232
233
- inline def eqlCases [Alts <: Tuple ](xm : Mirror , ym : Mirror , n : Int ): Boolean =
233
+ inline def eqlProduct [T ](m : Mirror .ProductOf [T ])(x : Any , y : Any ): Boolean =
234
+ eqlElems[m.MirroredElemTypes ](0 )(x, y)
235
+
236
+ inline def eqlCases [Alts ](n : Int )(x : Any , y : Any , ord : Int ): Boolean =
234
237
inline erasedValue[Alts ] match {
235
- case _ : (Shape .Case [alt, elems] *: alts1) =>
236
- if (xm.ordinal == n) eqlElems[elems](xm, ym, 0 )
237
- else eqlCases[alts1](xm, ym, n + 1 )
238
- case _ : Unit =>
238
+ case _ : (alt *: alts1) =>
239
+ if (ord == n)
240
+ implicit match {
241
+ case m : Mirror .ProductOf [`alt`] => eqlElems[m.MirroredElemTypes ](0 )(x, y)
242
+ }
243
+ else eqlCases[alts1](n + 1 )(x, y, ord)
244
+ case _ : Unit =>
239
245
false
240
246
}
241
247
242
- inline def derived [T ](implicit ev : Generic [T ]): Eq [T ] = new {
243
- def eql (x : T , y : T ): Boolean = {
244
- val xm = ev.reflect(x)
245
- val ym = ev.reflect(y)
246
- inline erasedValue[ev.Shape ] match {
247
- case _ : Shape .Cases [alts] =>
248
- xm.ordinal == ym.ordinal &&
249
- eqlCases[alts](xm, ym, 0 )
250
- case _ : Shape .Case [_, elems] =>
251
- eqlElems[elems](xm, ym, 0 )
248
+ inline def derived [T ](implicit ev : Mirror .Of [T ]): Eq [T ] = new Eq [T ] {
249
+ def eql (x : T , y : T ): Boolean =
250
+ inline ev match {
251
+ case m : Mirror .SumOf [T ] =>
252
+ val ord = m.ordinal(x)
253
+ ord == m.ordinal(y) && eqlCases[m.MirroredElemTypes ](0 )(x, y, ord)
254
+ case m : Mirror .ProductOf [T ] =>
255
+ eqlElems[m.MirroredElemTypes ](0 )(x, y)
252
256
}
253
- }
254
257
}
255
258
256
259
implicit object IntEq extends Eq [Int ] {
@@ -267,79 +270,86 @@ object typeclasses {
267
270
object Pickler {
268
271
import scala .compiletime .{erasedValue , constValue }
269
272
import compiletime ._
270
- import reflect .{ Mirror , Generic }
273
+ import deriving . _
271
274
272
275
def nextInt (buf : mutable.ListBuffer [Int ]): Int = try buf.head finally buf.trimStart(1 )
273
276
274
277
inline def tryPickle [T ](buf : mutable.ListBuffer [Int ], x : T ): Unit = implicit match {
275
278
case pkl : Pickler [T ] => pkl.pickle(buf, x)
276
279
}
277
280
278
- inline def pickleElems [Elems <: Tuple ](buf : mutable.ListBuffer [Int ], elems : Mirror , n : Int ): Unit =
281
+ inline def pickleElems [Elems <: Tuple ](n : Int )( buf : mutable.ListBuffer [Int ], x : Any ): Unit =
279
282
inline erasedValue[Elems ] match {
280
283
case _ : (elem *: elems1) =>
281
- tryPickle[elem](buf, elems(n). asInstanceOf [elem])
282
- pickleElems[elems1](buf, elems, n + 1 )
284
+ tryPickle[elem](buf, productElement [elem](x, n) )
285
+ pickleElems[elems1](n + 1 )(buf, x )
283
286
case _ : Unit =>
284
287
}
285
288
286
- inline def pickleCases [Alts <: Tuple ](buf : mutable.ListBuffer [Int ], xm : Mirror , n : Int ): Unit =
289
+ inline def pickleCases [Alts <: Tuple ](n : Int )( buf : mutable.ListBuffer [Int ], x : Any , ord : Int ): Unit =
287
290
inline erasedValue[Alts ] match {
288
- case _ : (Shape .Case [alt, elems] *: alts1) =>
289
- if (xm.ordinal == n) pickleElems[elems](buf, xm, 0 )
290
- else pickleCases[alts1](buf, xm, n + 1 )
291
+ case _ : (alt *: alts1) =>
292
+ if (ord == n)
293
+ implicit match {
294
+ case m : Mirror .ProductOf [`alt`] => pickleElems[m.MirroredElemTypes ](0 )(buf, x)
295
+ }
296
+ else pickleCases[alts1](n + 1 )(buf, x, ord)
291
297
case _ : Unit =>
292
298
}
293
299
294
300
inline def tryUnpickle [T ](buf : mutable.ListBuffer [Int ]): T = implicit match {
295
301
case pkl : Pickler [T ] => pkl.unpickle(buf)
296
302
}
297
303
298
- inline def unpickleElems [Elems <: Tuple ](buf : mutable.ListBuffer [Int ], elems : Array [ AnyRef ], n : Int ): Unit =
304
+ inline def unpickleElems [Elems <: Tuple ](n : Int )( buf : mutable.ListBuffer [Int ], elems : ArrayProduct ): Unit =
299
305
inline erasedValue[Elems ] match {
300
306
case _ : (elem *: elems1) =>
301
307
elems(n) = tryUnpickle[elem](buf).asInstanceOf [AnyRef ]
302
- unpickleElems[elems1](buf, elems, n + 1 )
308
+ unpickleElems[elems1](n + 1 )(buf, elems )
303
309
case _ : Unit =>
304
310
}
305
311
306
- inline def unpickleCase [T , Elems <: Tuple ](gen : Generic [ T ], buf : mutable.ListBuffer [Int ], ordinal : Int ): T = {
312
+ inline def unpickleCase [T , Elems <: Tuple ](buf : mutable.ListBuffer [Int ], m : Mirror . ProductOf [ T ] ): T = {
307
313
inline val size = constValue[Tuple .Size [Elems ]]
308
314
inline if (size == 0 )
309
- gen.reify(gen.common.mirror(ordinal) )
315
+ m.fromProduct( EmptyProduct )
310
316
else {
311
- val elems = new Array [ Object ] (size)
312
- unpickleElems[Elems ](buf, elems, 0 )
313
- gen.reify(gen.common.mirror(ordinal, elems) )
317
+ val elems = new ArrayProduct (size)
318
+ unpickleElems[Elems ](0 )( buf, elems)
319
+ m.fromProduct( elems)
314
320
}
315
321
}
316
322
317
- inline def unpickleCases [T , Alts <: Tuple ](gen : Generic [ T ], buf : mutable.ListBuffer [Int ], ordinal : Int , n : Int ): T =
323
+ inline def unpickleCases [T , Alts <: Tuple ](n : Int )( buf : mutable.ListBuffer [Int ], ord : Int ): T =
318
324
inline erasedValue[Alts ] match {
319
- case _ : (Shape .Case [_, elems] *: alts1) =>
320
- if (n == ordinal) unpickleCase[T , elems](gen, buf, ordinal)
321
- else unpickleCases[T , alts1](gen, buf, ordinal, n + 1 )
322
- case _ =>
323
- throw new IndexOutOfBoundsException (s " unexpected ordinal number: $ordinal" )
325
+ case _ : (alt *: alts1) =>
326
+ if (ord == n)
327
+ implicit match {
328
+ case m : Mirror .ProductOf [`alt` & T ] =>
329
+ unpickleCase[`alt` & T , m.MirroredElemTypes ](buf, m)
330
+ }
331
+ else unpickleCases[T , alts1](n + 1 )(buf, ord)
332
+ case _ : Unit =>
333
+ throw new IndexOutOfBoundsException (s " unexpected ordinal number: $ord" )
324
334
}
325
335
326
- inline def derived [T ](implicit ev : Generic [T ]): Pickler [T ] = new {
327
- def pickle (buf : mutable.ListBuffer [Int ], x : T ): Unit = {
328
- val xm = ev.reflect(x)
329
- inline erasedValue[ev. Shape ] match {
330
- case _ : Shape . Cases [alts] =>
331
- buf += xm.ordinal
332
- pickleCases[alts]( buf, xm, 0 )
333
- case _ : Shape . Case [_, elems ] =>
334
- pickleElems[elems]( buf, xm, 0 )
336
+ inline def derived [T ](implicit ev : Mirror . Of [T ]): Pickler [T ] = new {
337
+ def pickle (buf : mutable.ListBuffer [Int ], x : T ): Unit =
338
+ inline ev match {
339
+ case m : Mirror . SumOf [ T ] =>
340
+ val ord = m.ordinal(x)
341
+ buf += ord
342
+ pickleCases[m. MirroredElemTypes ]( 0 )( buf, x, ord )
343
+ case m : Mirror . ProductOf [ T ] =>
344
+ pickleElems[m. MirroredElemTypes ]( 0 )( buf, x )
335
345
}
336
- }
337
346
def unpickle (buf : mutable.ListBuffer [Int ]): T =
338
- inline erasedValue[ev.Shape ] match {
339
- case _ : Shape .Cases [alts] =>
340
- unpickleCases[T , alts](ev, buf, nextInt(buf), 0 )
341
- case _ : Shape .Case [_, elems] =>
342
- unpickleCase[T , elems](ev, buf, 0 )
347
+ inline ev match {
348
+ case m : Mirror .SumOf [T ] =>
349
+ val ord = nextInt(buf)
350
+ unpickleCases[T , m.MirroredElemTypes ](0 )(buf, ord)
351
+ case m : Mirror .ProductOf [T ] =>
352
+ unpickleCase[T , m.MirroredElemTypes ](buf, m)
343
353
}
344
354
}
345
355
0 commit comments