@@ -2,54 +2,77 @@ import scala.deriving._
2
2
import scala .quoted ._
3
3
import scala .quoted .matching ._
4
4
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
+ }
6
13
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
9
16
}
10
17
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)
14
21
}
15
22
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)
18
26
}
19
27
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
+ }
24
34
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 }
29
37
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)})}
32
46
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
+ }
36
53
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) }
38
59
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
+ }
45
64
}
46
- }
47
65
48
- ' {
49
- eqProduct ((x : T , y : T ) => $ {eqProductBody (' x , ' y )})
50
- }
66
+ ' {
67
+ eqSum ((x : T , y : T ) => $ {eqSumBody (' x , ' y )})
68
+ }
51
69
}
52
70
}
71
+ }
72
+
73
+ object Macro3 {
74
+
75
+
53
76
54
77
inline def test3 [T ](value : => T , value2 : => T ): Boolean = $ { test3Impl(' value , ' value2 ) }
55
78
0 commit comments