@@ -2,54 +2,77 @@ import scala.deriving._
22import scala .quoted ._
33import scala .quoted .matching ._
44
5- object Macro3 {
5+ trait Eq [T ] {
6+ def eqv (x : T , y : T ): Boolean
7+ }
8+
9+ object Eq {
10+ given Eq [String ] {
11+ def eqv (x : String , y : String ) = x == y
12+ }
613
7- trait Eq [T ] {
8- def eqv (x : T , y : T ) : Boolean
14+ given Eq [Int ] {
15+ def eqv (x : Int , y : Int ) = x == y
916 }
1017
11- object Eq {
12- given Eq [String ] {
13- def eqv (x : String , y : String ) = x == y
18+ def eqProduct [ T ]( body : ( T , T ) => Boolean ) : Eq [ T ] =
19+ new Eq [T ] {
20+ def eqv (x : T , y : T ) : Boolean = body(x, y)
1421 }
1522
16- given Eq [Int ] {
17- def eqv (x : Int , y : Int ) = x == y
23+ def eqSum [T ](body : (T , T ) => Boolean ): Eq [T ] =
24+ new Eq [T ] {
25+ def eqv (x : T , y : T ): Boolean = body(x, y)
1826 }
1927
20- def eqProduct [T ](body : (T , T ) => Boolean ): Eq [T ] =
21- new Eq [T ] {
22- def eqv (x : T , y : T ): Boolean = body(x, y)
23- }
28+ def summonAll [T ](t : Type [T ])(given qctx : QuoteContext ): List [Expr [Eq [_]]] = t match {
29+ case ' [$tpe *: $tpes] =>
30+ println(tpe.show)
31+ summonExpr(given ' [Eq [$tpe]]).get :: summonAll(tpes)
32+ case ' [Unit ] => Nil
33+ }
2434
25- def summonAll [T ](t : Type [T ])(given qctx : QuoteContext ): List [Expr [Eq [_]]] = t match {
26- case ' [$tpe *: $tpes] => summonExpr(given ' [Eq [$tpe]]).get :: summonAll(tpes)
27- case ' [Unit ] => Nil
28- }
35+ def derived [T : Type ](ev : Expr [Mirror .Of [T ]])(given qctx : QuoteContext ): Expr [Eq [T ]] = {
36+ import qctx .tasty .{_ , given }
2937
30- def derived [T : Type ](ev : Expr [Mirror .Of [T ]])(given qctx : QuoteContext ): Expr [Eq [T ]] = {
31- import qctx .tasty .{_ , given }
38+ ev match {
39+ case ' { $m : Mirror .ProductOf [T ] { type MirroredElemTypes = $elementTypes }} =>
40+ val elemInstances = summonAll(elementTypes)
41+ val eqProductBody : (Expr [T ], Expr [T ]) => Expr [Boolean ] = (x, y) => {
42+ elemInstances.zipWithIndex.foldLeft(Expr (true : Boolean )) {
43+ case (acc, (elem, index)) =>
44+ val e1 = ' {$x.asInstanceOf [Product ].productElement($ {Expr (index)})}
45+ val e2 = ' {$y.asInstanceOf [Product ].productElement($ {Expr (index)})}
3246
33- val elementTypes = ev match {
34- case ' { $m : Mirror .ProductOf [T ] { type MirroredElemTypes = $elem } } => elem
35- }
47+ ' { $acc && $elem.asInstanceOf [Eq [Any ]].eqv($e1, $e2) }
48+ }
49+ }
50+ ' {
51+ eqProduct((x : T , y : T ) => $ {eqProductBody(' x , ' y )})
52+ }
3653
37- val elemInstances = summonAll(elementTypes)
54+ case ' { $m : Mirror .SumOf [T ] { type MirroredElemTypes = $elementTypes }} =>
55+ val elemInstances = summonAll(elementTypes)
56+ val eqSumBody : (Expr [T ], Expr [T ]) => Expr [Boolean ] = (x, y) => {
57+ val ordx = ' { $m.ordinal($x) }
58+ val ordy = ' { $m.ordinal($y) }
3859
39- val eqProductBody : (Expr [T ], Expr [T ]) => Expr [Boolean ] = (x, y) => {
40- elemInstances.zipWithIndex.foldLeft(Expr (true : Boolean )) {
41- case (acc, (elem, index)) =>
42- val e1 = ' {$x.asInstanceOf [Product ].productElement($ {Expr (index)})}
43- val e2 = ' {$y.asInstanceOf [Product ].productElement($ {Expr (index)})}
44- ' { $acc && $elem.asInstanceOf [Eq [Any ]].eqv($e1, $e2) }
60+ val elements = Expr .ofList(elemInstances)
61+ ' {
62+ $ordx == $ordy && $elements($ordx).asInstanceOf [Eq [Any ]].eqv($x, $y)
63+ }
4564 }
46- }
4765
48- ' {
49- eqProduct ((x : T , y : T ) => $ {eqProductBody (' x , ' y )})
50- }
66+ ' {
67+ eqSum ((x : T , y : T ) => $ {eqSumBody (' x , ' y )})
68+ }
5169 }
5270 }
71+ }
72+
73+ object Macro3 {
74+
75+
5376
5477 inline def test3 [T ](value : => T , value2 : => T ): Boolean = $ { test3Impl(' value , ' value2 ) }
5578
0 commit comments