File tree Expand file tree Collapse file tree 3 files changed +73
-0
lines changed
tests/run-macros/quoted-liftable-derivation-macro Expand file tree Collapse file tree 3 files changed +73
-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
+
5
+ trait Lft [T ]:
6
+ def toExpr (x : T ): Quotes ?=> Expr [T ]
7
+
8
+ object Lft {
9
+ given Lft [Int ] with
10
+ def toExpr (x : Int ) = Expr (x)
11
+
12
+ inline given derived [T ](using inline m : Mirror .Of [T ]): Lft [T ] = $ { derivedExpr(' m ) }
13
+
14
+ private def derivedExpr [T ](mirrorExpr : Expr [Mirror .Of [T ]])(using qctx : Quotes , tpe : Type [T ]): Expr [Lft [T ]] = {
15
+ mirrorExpr match {
16
+ case ' { $mirrorExpr : Mirror .Sum { type MirroredElemTypes = mirroredElemTypes } } =>
17
+ val liftableExprs = elemTypesLfts[mirroredElemTypes]
18
+ ' {
19
+ new Lft [T ]:
20
+ def toExpr (x : T ) =
21
+ val mirror = $mirrorExpr
22
+ val liftable = $ {Expr .ofSeq(liftableExprs)}.apply(mirror.ordinal(x)).asInstanceOf [Lft [T ]] // TODO generate switch
23
+ liftable.toExpr(x)
24
+ }
25
+
26
+ case ' { $mirrorExpr : Mirror .Product { type MirroredElemTypes = mirroredElemTypes } } =>
27
+ val liftableExprs = Expr .ofList(elemTypesLfts[mirroredElemTypes])
28
+ ' {
29
+ new Lft [T ]:
30
+ def toExpr (x : T ) =
31
+ val liftables = $liftableExprs
32
+ val lifted = Expr .ofSeq(liftables.zipWithIndex.map { (liftable, i) =>
33
+ liftable.asInstanceOf [Lft [AnyRef ]].toExpr(??? ) // (productElement(x, i))
34
+ })
35
+ val liftedProduct = ' { Tuple .fromArray(Array ($lifted : _* )) }
36
+ val mirror = Expr .summon(using ' [Mirror .ProductOf [T ]]).get
37
+ ' { $mirror.fromProduct($liftedProduct) }
38
+ }
39
+ }
40
+ }
41
+
42
+ private def elemTypesLfts [X : Type ](using Quotes ): List [Expr [Lft [_]]] =
43
+ Type .of[X ] match
44
+ case ' [ head *: tail ] =>
45
+ Expr .summon(using ' [Lft [head]]).getOrElse(quotes.reflect.report.throwError(s " Could not find given Lft[ ${Type .show[head]}] " )) :: elemTypesLfts[tail]
46
+ case ' [ Unit ] => Nil
47
+
48
+ }
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 Quotes ): Expr [Opt [Int ]] =
15
+ summon[Lft [Sm [Int ]]].toExpr(Sm (2 ))
16
+
17
+ private def noneExpr (using Quotes ): 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