Skip to content

Commit a69c3ca

Browse files
committed
WIP
1 parent e419209 commit a69c3ca

File tree

3 files changed

+69
-33
lines changed

3 files changed

+69
-33
lines changed

tests/run-macros/i8007/Macro_1.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import scala.quoted._
33
import scala.quoted.matching._
44

55
object Macro1 {
6-
case class Person(name: String, age: Int)
76

87
def mirrorFields[T](t: Type[T])(given qctx: QuoteContext): List[String] =
98
t match {

tests/run-macros/i8007/Macro_3.scala

Lines changed: 55 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,54 +2,77 @@ import scala.deriving._
22
import scala.quoted._
33
import 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

tests/run-macros/i8007/Test_4.scala

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,18 @@
11
import Macro1._
22
import Macro2._
33
import Macro3._
4+
import scala.deriving._
5+
6+
case class Person(name: String, age: Int)
7+
8+
enum Opt[+T] derives Eq {
9+
case Sm(t: T)
10+
case Nn
11+
}
412

513
@main def Test() = {
14+
import Opt._
15+
616
val t1 = test1(Person("Test", 23))
717
println(t1)
818
println
@@ -18,4 +28,8 @@ import Macro3._
1828
val t4 = test3(Person("Test", 23), Person("Test", 24))
1929
println(t4) // false
2030
println
31+
32+
val t5 = test3(Sm(Person("Test", 23)), Sm(Person("Test", 23)))
33+
println(t5) // true
34+
println
2135
}

0 commit comments

Comments
 (0)