Skip to content

Commit

Permalink
Specialize liftable for Arrays and IArrays
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolasstucki committed Jul 30, 2019
1 parent 195597e commit dc465c1
Show file tree
Hide file tree
Showing 6 changed files with 179 additions and 5 deletions.
59 changes: 54 additions & 5 deletions library/src-bootstrapped/scala/quoted/Liftable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,62 @@ object Liftable {
}
}

given IArrayIsLiftable[T: Type: Liftable: ClassTag] as Liftable[IArray[T]] = new Liftable[IArray[T]] {
def toExpr(iarray: IArray[T]): given QuoteContext => Expr[IArray[T]] = '{
val array = new Array[T](${iarray.length.toExpr})(ClassTag(${the[ClassTag[T]].runtimeClass.toExpr}))
${ Expr.block(List.tabulate(iarray.length)(i => '{ array(${i.toExpr}) = ${iarray(i).toExpr} }), '{ array.asInstanceOf[IArray[T]] }) }
}
given ArrayOfBooleanIsLiftable as Liftable[Array[Boolean]] = new Liftable[Array[Boolean]] {
def toExpr(array: Array[Boolean]): given QuoteContext => Expr[Array[Boolean]] =
if (array.length == 0) '{ Array.emptyBooleanArray }
else '{ Array(${array(0).toExpr}, ${array.toSeq.tail.toExpr}: _*) }
}

given ArrayOfByteIsLiftable as Liftable[Array[Byte]] = new Liftable[Array[Byte]] {
def toExpr(array: Array[Byte]): given QuoteContext => Expr[Array[Byte]] =
if (array.length == 0) '{ Array.emptyByteArray }
else '{ Array(${array(0).toExpr}, ${array.toSeq.tail.toExpr}: _*) }
}

given ArrayOfShortIsLiftable as Liftable[Array[Short]] = new Liftable[Array[Short]] {
def toExpr(array: Array[Short]): given QuoteContext => Expr[Array[Short]] =
if (array.length == 0) '{ Array.emptyShortArray }
else '{ Array(${array(0).toExpr}, ${array.toSeq.tail.toExpr}: _*) }
}

given ArrayOfCharIsLiftable as Liftable[Array[Char]] = new Liftable[Array[Char]] {
def toExpr(array: Array[Char]): given QuoteContext => Expr[Array[Char]] =
if (array.length == 0) '{ Array.emptyCharArray }
else '{ Array(${array(0).toExpr}, ${array.toSeq.tail.toExpr}: _*) }
}

given ArrayOfIntIsLiftable as Liftable[Array[Int]] = new Liftable[Array[Int]] {
def toExpr(array: Array[Int]): given QuoteContext => Expr[Array[Int]] =
if (array.length == 0) '{ Array.emptyIntArray }
else '{ Array(${array(0).toExpr}, ${array.toSeq.tail.toExpr}: _*) }
}

given ArrayOfLongIsLiftable as Liftable[Array[Long]] = new Liftable[Array[Long]] {
def toExpr(array: Array[Long]): given QuoteContext => Expr[Array[Long]] =
if (array.length == 0) '{ Array.emptyLongArray }
else '{ Array(${array(0).toExpr}, ${array.toSeq.tail.toExpr}: _*) }
}

given ArrayOfFloatIsLiftable as Liftable[Array[Float]] = new Liftable[Array[Float]] {
def toExpr(array: Array[Float]): given QuoteContext => Expr[Array[Float]] =
if (array.length == 0) '{ Array.emptyFloatArray }
else '{ Array(${array(0).toExpr}, ${array.toSeq.tail.toExpr}: _*) }
}

given ArrayOfDoubleIsLiftable as Liftable[Array[Double]] = new Liftable[Array[Double]] {
def toExpr(array: Array[Double]): given QuoteContext => Expr[Array[Double]] =
if (array.length == 0) '{ Array.emptyDoubleArray }
else '{ Array(${array(0).toExpr}, ${array.toSeq.tail.toExpr}: _*) }
}

given IArrayIsLiftable[T: Type] as Liftable[IArray[T]] given (ltArray: Liftable[Array[T]]) = new Liftable[IArray[T]] {
def toExpr(iarray: IArray[T]): given QuoteContext => Expr[IArray[T]] =
'{ ${ltArray.toExpr(iarray.asInstanceOf[Array[T]])}.asInstanceOf[IArray[T]] }
}

private def asIArrayExpr[T: Type](arr: Expr[Array[T]]) given QuoteContext: Expr[IArray[T]] =
'{ $arr.asInstanceOf[IArray[T]] }

given [T: Type: Liftable] as Liftable[Seq[T]] = new Liftable[Seq[T]] {
def toExpr(xs: Seq[T]): given QuoteContext => Expr[Seq[T]] =
xs.map(the[Liftable[T]].toExpr).toExprOfSeq
Expand Down
23 changes: 23 additions & 0 deletions tests/run-with-compiler/quote-lib.scala
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,32 @@ object Test {
val iarray: IArray[Int] = IArray(1, 2, 3)
val liftedIArray: Expr[IArray[Int]] = iarray

val iarray2: IArray[String] = IArray("a", "b", "c")
iarray2.toExpr

IArray(false).toExpr
IArray(1: Byte).toExpr
IArray(1: Short).toExpr
IArray(1).toExpr
IArray(1L).toExpr
IArray(1.1f).toExpr
IArray(1.1d).toExpr
IArray('a').toExpr
IArray((1, 3)).toExpr

val array: Array[Int] = Array(1, 2, 3)
val liftedArray: Expr[Array[Int]] = array

Array(false).toExpr
Array(1: Byte).toExpr
Array(1: Short).toExpr
Array(1).toExpr
Array(1L).toExpr
Array(1.1f).toExpr
Array(1.1d).toExpr
Array('a').toExpr
Array((1, 3)).toExpr

val some: Option[Int] = Some(2)
val none: Option[Int] = Some(2)
val liftedSome: Expr[Option[Int]] = some
Expand Down
19 changes: 19 additions & 0 deletions tests/run-with-compiler/quote-lift-Array.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[]
[]
[]
[]
[]
[]
[]
[]
[]

[true]
[1, 2]
[2, 3]
[a, b]
[4, 5]
[6, 7]
[2.1, 3.2]
[2.2, 3.3]
[abc, xyz]
32 changes: 32 additions & 0 deletions tests/run-with-compiler/quote-lift-Array.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import scala.quoted._
import scala.quoted.autolift._

object Test {
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)
def main(args: Array[String]): Unit = run {
'{
def p[T](arr: Array[T]): Unit = {
println(arr.asInstanceOf[Array[_]].mkString("[", ", ", "]"))
}
p(${Array.empty[Boolean]})
p(${Array.empty[Byte]})
p(${Array.empty[Short]})
p(${Array.empty[Char]})
p(${Array.empty[Int]})
p(${Array.empty[Long]})
p(${Array.empty[Float]})
p(${Array.empty[Double]})
p(${Array.empty[String]})
println()
p(${Array(true)})
p(${Array[Byte](1, 2)})
p(${Array[Short](2, 3)})
p(${Array[Char]('a', 'b')})
p(${Array[Int](4, 5)})
p(${Array[Long](6L, 7L)})
p(${Array[Float](2.1f, 3.2f)})
p(${Array[Double](2.2, 3.3)})
p(${Array("abc", "xyz")})
}
}
}
19 changes: 19 additions & 0 deletions tests/run-with-compiler/quote-lift-IArray.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[]
[]
[]
[]
[]
[]
[]
[]
[]

[true]
[1, 2]
[2, 3]
[a, b]
[4, 5]
[6, 7]
[2.1, 3.2]
[2.2, 3.3]
[abc, xyz]
32 changes: 32 additions & 0 deletions tests/run-with-compiler/quote-lift-IArray.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import scala.quoted._
import scala.quoted.autolift._

object Test {
implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader)
def main(args: Array[String]): Unit = run {
'{
def p[T](arr: IArray[T]): Unit = {
println(arr.asInstanceOf[Array[_]].mkString("[", ", ", "]"))
}
p(${IArray.empty[Boolean]})
p(${IArray.empty[Byte]})
p(${IArray.empty[Short]})
p(${IArray.empty[Char]})
p(${IArray.empty[Int]})
p(${IArray.empty[Long]})
p(${IArray.empty[Float]})
p(${IArray.empty[Double]})
p(${IArray.empty[String]})
println()
p(${IArray(true)})
p(${IArray[Byte](1, 2)})
p(${IArray[Short](2, 3)})
p(${IArray[Char]('a', 'b')})
p(${IArray[Int](4, 5)})
p(${IArray[Long](6L, 7L)})
p(${IArray[Float](2.1f, 3.2f)})
p(${IArray[Double](2.2, 3.3)})
p(${IArray("abc", "xyz")})
}
}
}

0 comments on commit dc465c1

Please sign in to comment.