|
| 1 | +import quoted._ |
| 2 | +import SomeEnum._ |
| 3 | + |
| 4 | +trait Liftable[T] { |
| 5 | + /** Lift a value into an expression containing the construction of that value */ |
| 6 | + def toExpr(x: T): QuoteContext ?=> Expr[T] |
| 7 | +} |
| 8 | + |
| 9 | +object Lift: |
| 10 | + def apply[T: Liftable](t: T)(using qctx: QuoteContext, ev: Liftable[T]): Expr[T] = ev.toExpr(t) |
| 11 | + |
| 12 | +sealed abstract class SomeEnum |
| 13 | +object SomeEnum: |
| 14 | + final val Foo = new SomeEnum {} |
| 15 | + final case class Bar[S <: SomeEnum](s: S) extends SomeEnum |
| 16 | + object Bar: |
| 17 | + def apply[S <: SomeEnum](s: S): SomeEnum = new Bar(s) |
| 18 | + |
| 19 | +given LiftFoo as Liftable[Foo.type]: |
| 20 | + def toExpr(x: Foo.type): QuoteContext ?=> Expr[Foo.type] = '{Foo} |
| 21 | + |
| 22 | +given LiftBar[S <: SomeEnum: Type: Liftable] as Liftable[Bar[S]]: |
| 23 | + def toExpr(x: Bar[S]): QuoteContext ?=> Expr[Bar[S]] = '{new Bar(${Lift(x.s)})} |
| 24 | + |
| 25 | +sealed abstract class Lst[+T] |
| 26 | +final case class CONS[+T](head: T, tail: Lst[T]) extends Lst[T] |
| 27 | +case object NIL extends Lst[Nothing] |
| 28 | + |
| 29 | +given IntLiftable[T <: Int] as Liftable[T]: |
| 30 | + def toExpr(x: T): QuoteContext ?=> Expr[T] = qctx ?=> { |
| 31 | + import qctx.tasty._ |
| 32 | + Literal(Constant(x)).seal.asInstanceOf[Expr[T]] |
| 33 | + } |
| 34 | + |
| 35 | +given LiftLst[T: Type: Liftable](using ev1: => Liftable[CONS[T]], ev2: => Liftable[NIL.type]) as Liftable[Lst[T]]: |
| 36 | + def toExpr(xs: Lst[T]): QuoteContext ?=> Expr[Lst[T]] = xs match |
| 37 | + case NIL => ev2.toExpr(NIL) |
| 38 | + case cons @ CONS(_, _) => ev1.toExpr(cons) |
| 39 | + |
| 40 | +given LiftCONS[T: Type: Liftable](using Liftable[Lst[T]]) as Liftable[CONS[T]]: |
| 41 | + def toExpr(x: CONS[T]): QuoteContext ?=> Expr[CONS[T]] = '{CONS(${Lift(x.head)}, ${Lift(x.tail)})} |
| 42 | + |
| 43 | +given LiftNIL as Liftable[NIL.type]: |
| 44 | + def toExpr(x: NIL.type): QuoteContext ?=> Expr[NIL.type] = '{NIL} |
| 45 | + |
| 46 | +def mkLst[T](ts: T*) = ts.foldRight(NIL: Lst[T])(CONS(_,_)) |
| 47 | + |
| 48 | +def quote123: QuoteContext ?=> Expr[Lst[Int]] = Lift(mkLst(1,2,3)) |
| 49 | + |
| 50 | +inline def get123: Lst[Int] = ${ quote123 } |
| 51 | + |
0 commit comments