Skip to content

Commit 57cdace

Browse files
Liftable derivation WIP
1 parent b4bc28f commit 57cdace

File tree

2 files changed

+53
-0
lines changed

2 files changed

+53
-0
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
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+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@main def Test = println(mcr)

0 commit comments

Comments
 (0)