File tree Expand file tree Collapse file tree 3 files changed +75
-0
lines changed
tests/run-macros/quoted-liftable-derivation-macro Expand file tree Collapse file tree 3 files changed +75
-0
lines changed Original file line number Diff line number Diff line change
1
+ import scala .compiletime .{erasedValue , summonFrom }
2
+ import scala .deriving ._
3
+ import scala .quoted ._
4
+ import scala .quoted .matching ._
5
+
6
+
7
+ trait Lft [T ]:
8
+ def toExpr (x : T ): QuoteContext ?=> Expr [T ]
9
+
10
+ object Lft {
11
+ given Lft [Int ]:
12
+ def toExpr (x : Int ) = Expr (x)
13
+
14
+ inline given derived [T ](using inline m : Mirror .Of [T ]) as Lft [T ] = $ { derivedExpr(' m ) }
15
+
16
+ private def derivedExpr [T ](mirrorExpr : Expr [Mirror .Of [T ]])(using qctx : QuoteContext , tpe : Type [T ]): Expr [Lft [T ]] = {
17
+ def elemTypesLfts (tp : Type [_]): List [Expr [Lft [_]]] =
18
+ tp match
19
+ case ' [ $head *: $tail ] =>
20
+ summonExpr(using ' [Lft [$head]]).getOrElse(qctx.throwError(s " Could not find given Lft[ ${head.show}] " )) :: elemTypesLfts(tail)
21
+ case ' [ Unit ] => Nil
22
+
23
+ mirrorExpr match {
24
+ case ' { $mirrorExpr : Mirror .Sum { type MirroredElemTypes = $mirroredElemTypes } } =>
25
+ val liftableExprs = elemTypesLfts(mirroredElemTypes)
26
+ ' {
27
+ new Lft [T ]:
28
+ def toExpr (x : T ) =
29
+ val mirror = $mirrorExpr
30
+ val liftable = $ {Expr .ofSeq(liftableExprs)}.apply(mirror.ordinal(x)).asInstanceOf [Lft [T ]] // TODO generate switch
31
+ liftable.toExpr(x)
32
+ }
33
+
34
+ case ' { $mirrorExpr : Mirror .Product { type MirroredElemTypes = $mirroredElemTypes } } =>
35
+ val liftableExprs = Expr .ofList(elemTypesLfts(mirroredElemTypes))
36
+ ' {
37
+ new Lft [T ]:
38
+ def toExpr (x : T ) =
39
+ val liftables = $liftableExprs
40
+ val lifted = Expr .ofSeq(liftables.zipWithIndex.map { (liftable, i) =>
41
+ liftable.asInstanceOf [Lft [AnyRef ]].toExpr(productElement(x, i))
42
+ })
43
+ val liftedProduct = ' { new ArrayProduct (Array [AnyRef ]($lifted : _* )) }
44
+ val mirror = summonExpr(using ' [Mirror .ProductOf [T ]]).get
45
+ ' { $mirror.fromProduct($liftedProduct) }
46
+ }
47
+ }
48
+ }
49
+
50
+ }
Original file line number Diff line number Diff line change
1
+
2
+ sealed trait Opt [+ T ] derives Lft
3
+ case class Sm [T ](t : T ) extends Opt [T ] derives Lft
4
+ case object Nn extends Opt [Nothing ] derives Lft
5
+
6
+ object Lib {
7
+
8
+ import scala .quoted ._
9
+ import Opt .{given _ }
10
+
11
+ inline def smTwo = $ {smTwoExpr}
12
+ inline def none = $ {noneExpr}
13
+
14
+ private def smTwoExpr (using QuoteContext ): Expr [Opt [Int ]] =
15
+ summon[Lft [Sm [Int ]]].toExpr(Sm (2 ))
16
+
17
+ private def noneExpr (using QuoteContext ): Expr [Opt [Int ]] =
18
+ summon[Lft [Nn .type ]].toExpr(Nn )
19
+ }
20
+
Original file line number Diff line number Diff line change
1
+ object Test extends App {
2
+ import Opt ._
3
+ assert(Lib .smTwo == Sm (2 ))
4
+ assert(Lib .none == Nn )
5
+ }
You can’t perform that action at this time.
0 commit comments