|
| 1 | +import scala.quoted._, scala.deriving._ |
| 2 | +import scala.quoted.given |
| 3 | + |
| 4 | +import scala.reflect.ClassTag |
| 5 | + |
| 6 | +import Tuple.{ Head, Tail } |
| 7 | +import scala.compiletime.{ erasedValue, summonFrom } |
| 8 | + |
| 9 | + |
| 10 | +inline def mcr(given m: Mirror.ProductOf[Foo], m2: Mirror.ProductOf[Bar], m3: Mirror.ProductOf[Stuff.FooS], m4: Mirror.ProductOf[Stuff.BarS]): Any = ${mcrImpl(given 'm, 'm2, 'm3, 'm4)} |
| 11 | +def mcrImpl(given m: Expr[Mirror.ProductOf[Foo]], m2: Expr[Mirror.ProductOf[Bar]], m3: Expr[Mirror.ProductOf[Stuff.FooS]], m4: Expr[Mirror.ProductOf[Stuff.BarS]])(given ctx: QuoteContext): Expr[Any] = |
| 12 | + val x: A = Foo(1, "foo") |
| 13 | + val y: Stuff = Stuff.FooS(10) |
| 14 | + Expr(y) |
| 15 | + |
| 16 | +sealed trait A |
| 17 | +case class Foo(x: Int, y: String) extends A |
| 18 | +case class Bar(a: String, b: Double) extends A |
| 19 | + |
| 20 | +enum Stuff { |
| 21 | + case FooS(x: Int) |
| 22 | + case BarS(y: String) |
| 23 | +} |
| 24 | + |
| 25 | +inline def summonInline[T] = summonFrom { case x: T => x } |
| 26 | + |
| 27 | +inline def summonAll[T <: Tuple]: List[?] = inline erasedValue[T] match |
| 28 | + case _: Unit => Nil |
| 29 | + case _: (t *: ts) => summonInline[t] :: summonAll[ts] |
| 30 | + |
| 31 | +inline given productLiftable[T <: Product: Type](given |
| 32 | + m : Mirror.ProductOf[T], |
| 33 | + em: Expr[Mirror.ProductOf[T]]): Liftable[T] = new Liftable[T] { |
| 34 | + def toExpr(x: T) = |
| 35 | + val genRepr = Tuple.fromProductTyped(x) |
| 36 | + val liftables = summonAll[Tuple.Map[m.MirroredElemTypes, Liftable]] |
| 37 | + val elemsWithLiftables = liftables.zip(genRepr.asInstanceOf[Product].productIterator.toList) |
| 38 | + val tupleOfExprs = elemsWithLiftables.map { |
| 39 | + case (l: Liftable[a], x) => l.toExpr(x.asInstanceOf[a]) |
| 40 | + } |
| 41 | + val exprOfTuple = Expr.ofTuple(tupleOfExprs) |
| 42 | + '{$em.fromProduct($exprOfTuple.asInstanceOf[Product])} |
| 43 | +} |
| 44 | + |
| 45 | +inline given sumLiftable[T: Type](given m: Mirror.SumOf[T]): Liftable[T] = new Liftable[T] { |
| 46 | + def toExpr(x: T) = |
| 47 | + val liftables = summonAll[Tuple.Map[m.MirroredElemTypes, Liftable]] |
| 48 | + val tags = summonAll[Tuple.Map[m.MirroredElemTypes, ClassTag]] |
| 49 | + tags.zip(liftables).flatMap { case (t: ClassTag[a], l: Liftable[?]) => |
| 50 | + t.unapply(x).map(xa => l.asInstanceOf[Liftable[a]].toExpr(xa)) } |
| 51 | + .head.asInstanceOf[Expr[T]] |
| 52 | +} |
0 commit comments