Skip to content

Commit

Permalink
Recontextualize Liftable.toExpr
Browse files Browse the repository at this point in the history
Redefine `Liftable.toExpr` as `def toExpr(x: T): given QuoteContext => Expr[T]`.
This change makes it simpler to implement `Liftable` as the return type can be omitted.
  • Loading branch information
nicolasstucki committed Jul 24, 2019
1 parent 6f59aa9 commit ddc12dd
Show file tree
Hide file tree
Showing 14 changed files with 33 additions and 28 deletions.
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala
Expand Up @@ -204,7 +204,7 @@ class ReifyQuotes extends MacroTransform {
private def pickledQuote(body: Tree, splices: List[Tree], originalTp: Type, isType: Boolean)(implicit ctx: Context) = {

def liftedValue[T](value: T, name: TermName, qctx: Tree) =
ref(defn.LiftableModule).select(name).select("toExpr".toTermName).appliedTo(Literal(Constant(value))).appliedTo(qctx)
ref(defn.LiftableModule).select(name).select("toExpr".toTermName).appliedTo(Literal(Constant(value))).select(nme.apply).appliedTo(qctx)

def pickleAsValue[T](value: T) = {
val qctx = ctx.typer.inferImplicitArg(defn.QuoteContextClass.typeRef, body.span)
Expand Down
6 changes: 3 additions & 3 deletions library/src/scala/quoted/Liftable.scala
Expand Up @@ -6,7 +6,7 @@ package scala.quoted
trait Liftable[T] {

/** Lift a value into an expression containing the construction of that value */
def toExpr(x: T) given QuoteContext: Expr[T]
def toExpr(x: T): given QuoteContext => Expr[T]

}

Expand All @@ -29,15 +29,15 @@ object Liftable {

private class PrimitiveLiftable[T <: Unit | Null | Int | Boolean | Byte | Short | Int | Long | Float | Double | Char | String] extends Liftable[T] {
/** Lift a primitive value `n` into `'{ n }` */
def toExpr(x: T) given (qctx: QuoteContext): Expr[T] = {
def toExpr(x: T) = given qctx => {
import qctx.tasty._
Literal(Constant(x)).seal.asInstanceOf[Expr[T]]
}
}

implicit def ClassIsLiftable[T]: Liftable[Class[T]] = new Liftable[Class[T]] {
/** Lift a `Class[T]` into `'{ classOf[T] }` */
def toExpr(x: Class[T]) given (qctx: QuoteContext): Expr[Class[T]] = {
def toExpr(x: Class[T]) = given qctx => {
import qctx.tasty._
Ref(definitions.Predef_classOf).appliedToType(Type(x)).seal.asInstanceOf[Expr[Class[T]]]
}
Expand Down
6 changes: 1 addition & 5 deletions tests/pos/quote-liftable-list-2.scala
Expand Up @@ -3,11 +3,7 @@ import scala.quoted._
object Test {

implicit def ListIsLiftableOr[T: Type, U: Type]: Liftable[List[T | U]] = new {
def toExpr(xs: List[T | U]) given QuoteContext: Expr[List[T | U]] = '{ Nil: List[T | U] }
}

implicit def ListIsLiftableAnd[T: Type, U: Type]: Liftable[List[T & U]] = new {
def toExpr(xs: List[T & U]) given QuoteContext: Expr[List[T & U]] = '{ Nil: List[T & U] }
def toExpr(xs: List[T | U]) = '{ Nil: List[T | U] }
}

}
9 changes: 9 additions & 0 deletions tests/pos/quote-liftable-list-3.scala
@@ -0,0 +1,9 @@
import scala.quoted._

object Test {

implicit def ListIsLiftableAnd[T: Type, U: Type]: Liftable[List[T & U]] = new {
def toExpr(xs: List[T & U]) = '{ Nil: List[T & U] }
}

}
2 changes: 1 addition & 1 deletion tests/pos/quote-liftable-list.scala
Expand Up @@ -3,7 +3,7 @@ import scala.quoted._
object Test {

implicit def ListIsLiftable[T: Liftable: Type]: Liftable[List[T]] = new {
def toExpr(xs: List[T]) given QuoteContext: Expr[List[T]] = '{ Nil: List[T] }
def toExpr(xs: List[T]) = '{ Nil: List[T] }
}

}
6 changes: 3 additions & 3 deletions tests/pos/quote-liftable.scala
Expand Up @@ -5,7 +5,7 @@ def test given QuoteContext = {
delegate for QuoteContext = ???

implicit def IntIsLiftable: Liftable[Int] = new {
def toExpr(n: Int) given QuoteContext: Expr[Int] = n match {
def toExpr(n: Int) = n match {
case Int.MinValue => '{Int.MinValue}
case _ if n < 0 => '{- ${toExpr(n)}}
case 0 => '{0}
Expand All @@ -15,12 +15,12 @@ def test given QuoteContext = {
}

implicit def BooleanIsLiftable: Liftable[Boolean] = new {
implicit def toExpr(b: Boolean) given QuoteContext: Expr[Boolean] =
implicit def toExpr(b: Boolean) =
if (b) '{true} else '{false}
}

implicit def ListIsLiftable[T: Liftable: Type]: Liftable[List[T]] = new {
def toExpr(xs: List[T]) given QuoteContext: Expr[List[T]] = xs match {
def toExpr(xs: List[T]) = xs match {
case x :: xs1 => '{ ${ implicitly[Liftable[T]].toExpr(x) } :: ${ toExpr(xs1) } }
case Nil => '{Nil: List[T]}
}
Expand Down
Expand Up @@ -112,7 +112,7 @@ object TypeToolbox {

// TODO add to the std lib
private implicit def listIsLiftable[T: Type: Liftable]: Liftable[List[T]] = new Liftable {
def toExpr(list: List[T]) given QuoteContext: Expr[List[T]] = list match {
def toExpr(list: List[T]) = list match {
case x :: xs => '{${x.toExpr} :: ${toExpr(xs)}}
case Nil => '{Nil}
}
Expand Down
2 changes: 1 addition & 1 deletion tests/run-macros/quote-force/quoted_1.scala
Expand Up @@ -13,7 +13,7 @@ object Location {
}

private implicit def ListIsLiftable[T : Liftable : Type]: Liftable[List[T]] = new Liftable[List[T]] {
def toExpr(x: List[T]) given QuoteContext: Expr[List[T]] = x match {
def toExpr(x: List[T]) = x match {
case x :: xs => '{ ${x} :: ${xs} }
case Nil => '{ List.empty[T] }
}
Expand Down
4 changes: 2 additions & 2 deletions tests/run-macros/tasty-interpolation-1/Macro.scala
Expand Up @@ -77,10 +77,10 @@ abstract class MacroStringInterpolator[T] {
}

protected implicit def StringContextIsLiftable: Liftable[StringContext] = new Liftable[StringContext] {
def toExpr(strCtx: StringContext) given QuoteContext: Expr[StringContext] = {
def toExpr(strCtx: StringContext) = {
// TODO define in stdlib?
implicit def ListIsLiftable: Liftable[List[String]] = new Liftable[List[String]] {
override def toExpr(list: List[String]) given QuoteContext: Expr[List[String]] = list match {
override def toExpr(list: List[String]) = list match {
case x :: xs => '{${x.toExpr} :: ${toExpr(xs)}}
case Nil => '{Nil}
}
Expand Down
2 changes: 1 addition & 1 deletion tests/run-macros/tasty-location/quoted_1.scala
Expand Up @@ -19,7 +19,7 @@ object Location {
}

private implicit def ListIsLiftable[T : Liftable : Type]: Liftable[List[T]] = new Liftable[List[T]] {
def toExpr(x: List[T]) given QuoteContext: Expr[List[T]] = x match {
def toExpr(x: List[T]) = x match {
case x :: xs => '{ $x :: $xs }
case Nil => '{ List.empty[T] }
}
Expand Down
2 changes: 1 addition & 1 deletion tests/run-with-compiler/i3847-b.scala
Expand Up @@ -4,7 +4,7 @@ import scala.reflect.ClassTag
object Arrays {
implicit def ArrayIsLiftable[T: Liftable](implicit t: Type[T], qctx: QuoteContext): Liftable[Array[List[T]]] = {
new Liftable[Array[List[T]]] {
def toExpr(arr: Array[List[T]]) given QuoteContext: Expr[Array[List[T]]] = '{
def toExpr(arr: Array[List[T]]) = '{
new Array[List[$t]](${arr.length.toExpr})
// TODO add elements
}
Expand Down
14 changes: 7 additions & 7 deletions tests/run-with-compiler/quote-lib.scala
Expand Up @@ -53,7 +53,7 @@ package liftable {

object Units {
implicit def UnitIsLiftable: Liftable[Unit] = new Liftable[Unit] {
def toExpr(x: Unit) given QuoteContext: Expr[Unit] = '{}
def toExpr(x: Unit) = '{}
}
}

Expand All @@ -74,24 +74,24 @@ package liftable {
object Tuples {

implicit def Tuple1IsLiftable[T1: Liftable](implicit t1: Type[T1]): Liftable[Tuple1[T1]] = new Liftable[Tuple1[T1]] {
def toExpr(x: Tuple1[T1]) given QuoteContext: Expr[Tuple1[T1]] =
def toExpr(x: Tuple1[T1]) =
'{ Tuple1[$t1](${ x._1}) }
}

implicit def Tuple2IsLiftable[T1: Liftable, T2: Liftable](implicit t1: Type[T1], t2: Type[T2]): Liftable[(T1, T2)] = new Liftable[(T1, T2)] {
def toExpr(x: (T1, T2)) given QuoteContext: Expr[(T1, T2)] =
def toExpr(x: (T1, T2)) =
'{ Tuple2[$t1, $t2](${x._1}, ${x._2}) }

}

implicit def Tuple3IsLiftable[T1: Liftable, T2: Liftable, T3: Liftable](implicit t1: Type[T1], t2: Type[T2], t3: Type[T3]): Liftable[(T1, T2, T3)] = new Liftable[(T1, T2, T3)] {
def toExpr(x: (T1, T2, T3)) given QuoteContext: Expr[(T1, T2, T3)] =
def toExpr(x: (T1, T2, T3)) =
'{ Tuple3[$t1, $t2, $t3](${x._1}, ${x._2}, ${x._3}) }

}

implicit def Tuple4IsLiftable[T1: Liftable, T2: Liftable, T3: Liftable, T4: Liftable](implicit t1: Type[T1], t2: Type[T2], t3: Type[T3], t4: Type[T4]): Liftable[(T1, T2, T3, T4)] = new Liftable[(T1, T2, T3, T4)] {
def toExpr(x: (T1, T2, T3, T4)) given QuoteContext: Expr[(T1, T2, T3, T4)] =
def toExpr(x: (T1, T2, T3, T4)) =
'{ Tuple4[$t1, $t2, $t3, $t4](${x._1}, ${x._2}, ${x._3}, ${x._4}) }
}

Expand All @@ -102,7 +102,7 @@ package liftable {

object Lists {
implicit def ListIsLiftable[T: Liftable](implicit t: Type[T]): Liftable[List[T]] = new Liftable[List[T]] {
def toExpr(x: List[T]) given QuoteContext: Expr[List[T]] = x match {
def toExpr(x: List[T]): given QuoteContext => Expr[List[T]] = x match {
case x :: xs => '{ (${xs}).::[$t](${x}) }
case Nil => '{ Nil: List[$t] }
}
Expand All @@ -128,7 +128,7 @@ package liftable {

object Arrays {
implicit def ArrayIsLiftable[T: Liftable](implicit t: Type[T], ct: Expr[ClassTag[T]]): Liftable[Array[T]] = new Liftable[Array[T]] {
def toExpr(arr: Array[T]) given QuoteContext: Expr[Array[T]] = '{ new Array[$t](${arr.length})($ct) }
def toExpr(arr: Array[T]) = '{ new Array[$t](${arr.length})($ct) }
}
}

Expand Down
2 changes: 1 addition & 1 deletion tests/run-with-compiler/shonan-hmm-simple.scala
Expand Up @@ -72,7 +72,7 @@ case class Complex[T](re: T, im: T)

object Complex {
implicit def isLiftable[T: Type: Liftable]: Liftable[Complex[T]] = new Liftable[Complex[T]] {
def toExpr(comp: Complex[T]) given QuoteContext: Expr[Complex[T]] = '{Complex(${comp.re}, ${comp.im})}
def toExpr(comp: Complex[T]) = '{Complex(${comp.re}, ${comp.im})}
}
}

Expand Down
2 changes: 1 addition & 1 deletion tests/run-with-compiler/shonan-hmm/Complex.scala
Expand Up @@ -5,7 +5,7 @@ case class Complex[T](re: T, im: T)

object Complex {
implicit def complexIsLiftable[T: Type: Liftable]: Liftable[Complex[T]] = new Liftable {
def toExpr(c: Complex[T]) given QuoteContext: Expr[Complex[T]] = '{ Complex(${c.re.toExpr}, ${c.im.toExpr}) }
def toExpr(c: Complex[T]) = '{ Complex(${c.re.toExpr}, ${c.im.toExpr}) }
}

def of_complex_expr(x: Expr[Complex[Int]]) given QuoteContext: Complex[Expr[Int]] = Complex('{$x.re}, '{$x.im})
Expand Down

0 comments on commit ddc12dd

Please sign in to comment.