summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@typesafe.com>2014-01-17 12:07:45 -0800
committerAdriaan Moors <adriaan.moors@typesafe.com>2014-01-17 12:07:45 -0800
commitdf329bde7a9a4fcb8e4d69559d83032ee4a5e8b8 (patch)
tree05c22da5a046bae68ba52788e36ce3978049d612
parent930d895caae2dd0d098ea39679e663ce22caa9b2 (diff)
parent03e9e95f57b011336736d0e7ca64b90bb55e38a5 (diff)
downloadscala-df329bde7a9a4fcb8e4d69559d83032ee4a5e8b8.tar.gz
scala-df329bde7a9a4fcb8e4d69559d83032ee4a5e8b8.tar.bz2
scala-df329bde7a9a4fcb8e4d69559d83032ee4a5e8b8.zip
Merge pull request #3373 from densh/topic/std-liftable-refinement
A few minor changes to standard liftable instances and liftable support
-rw-r--r--src/compiler/scala/tools/reflect/quasiquotes/Holes.scala17
-rw-r--r--src/reflect/scala/reflect/api/BuildUtils.scala8
-rw-r--r--src/reflect/scala/reflect/api/StandardLiftables.scala35
-rw-r--r--src/reflect/scala/reflect/internal/BuildUtils.scala4
-rw-r--r--src/reflect/scala/reflect/internal/StdNames.scala4
-rw-r--r--test/files/scalacheck/quasiquotes/LiftableProps.scala50
6 files changed, 87 insertions, 31 deletions
diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala b/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala
index f5bcaf68e0..8a54519401 100644
--- a/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala
+++ b/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala
@@ -115,8 +115,7 @@ trait Holes { self: Quasiquotes =>
val lifter = inferLiftable(tpe)
assert(lifter != EmptyTree, s"couldnt find a liftable for $tpe")
val lifted = Apply(lifter, List(tree))
- val targetType = Select(u, tpnme.Tree)
- atPos(tree.pos)(TypeApply(Select(lifted, nme.asInstanceOf_), List(targetType)))
+ atPos(tree.pos)(lifted)
}
protected def iterated(card: Cardinality, tpe: Type, elementTransform: Tree => Tree = identity)(tree: Tree): Tree = {
@@ -167,16 +166,15 @@ trait Holes { self: Quasiquotes =>
/** Full support for unliftable implies that it's possible to interleave
* deconstruction with higher cardinality and unlifting of the values.
* In particular extraction of List[Tree] as List[T: Unliftable] requires
- * helper extractors that would do the job: UnliftHelper1[T]. Similarly
- * List[List[Tree]] needs UnliftHelper2[T].
+ * helper extractors that would do the job: UnliftListElementwise[T]. Similarly
+ * List[List[Tree]] needs UnliftListOfListsElementwise[T].
*
* See also "unlift list" tests in UnapplyProps.scala
*/
object unlifters {
private var records = List.empty[(Type, Cardinality)]
- // Request an UnliftHelperN[T] where n == card and T == tpe.
- // If card == 0 then helper is not needed and plain instance
- // of unliftable is returned.
+ // Materialize unlift helper that does elementwise
+ // unlifting for corresponding cardinality and type.
def spawn(tpe: Type, card: Cardinality): Option[Tree] = {
val unlifter = inferUnliftable(tpe)
if (unlifter == EmptyTree) None
@@ -191,7 +189,10 @@ trait Holes { self: Quasiquotes =>
def preamble(): List[Tree] =
records.zipWithIndex.map { case ((tpe, card), idx) =>
val name = TermName(nme.QUASIQUOTE_UNLIFT_HELPER + idx)
- val helperName = card match { case DotDot => nme.UnliftHelper1 case DotDotDot => nme.UnliftHelper2 }
+ val helperName = card match {
+ case DotDot => nme.UnliftListElementwise
+ case DotDotDot => nme.UnliftListOfListsElementwise
+ }
val lifter = inferUnliftable(tpe)
assert(helperName.isTermName)
// q"val $name: $u.build.${helperName.toTypeName} = $u.build.$helperName($lifter)"
diff --git a/src/reflect/scala/reflect/api/BuildUtils.scala b/src/reflect/scala/reflect/api/BuildUtils.scala
index 6971175f88..10c2def72a 100644
--- a/src/reflect/scala/reflect/api/BuildUtils.scala
+++ b/src/reflect/scala/reflect/api/BuildUtils.scala
@@ -246,13 +246,13 @@ private[reflect] trait BuildUtils { self: Universe =>
def unapply(tree: Tree): Option[(List[Tree], Tree)]
}
- def UnliftHelper1[T](unliftable: Unliftable[T]): UnliftHelper1[T]
- trait UnliftHelper1[T] {
+ def UnliftListElementwise[T](unliftable: Unliftable[T]): UnliftListElementwise[T]
+ trait UnliftListElementwise[T] {
def unapply(lst: List[Tree]): Option[List[T]]
}
- def UnliftHelper2[T](unliftable: Unliftable[T]): UnliftHelper2[T]
- trait UnliftHelper2[T] {
+ def UnliftListOfListsElementwise[T](unliftable: Unliftable[T]): UnliftListOfListsElementwise[T]
+ trait UnliftListOfListsElementwise[T] {
def unapply(lst: List[List[Tree]]): Option[List[List[T]]]
}
diff --git a/src/reflect/scala/reflect/api/StandardLiftables.scala b/src/reflect/scala/reflect/api/StandardLiftables.scala
index 6756d5e114..5a03996dd9 100644
--- a/src/reflect/scala/reflect/api/StandardLiftables.scala
+++ b/src/reflect/scala/reflect/api/StandardLiftables.scala
@@ -11,16 +11,16 @@ trait StandardLiftables { self: Universe =>
private def callCollection(name: Name)(args: List[Tree]) = callScala(nme.collection, nme.immutable, name)(args)
private def liftAsLiteral[T]: Liftable[T] = Liftable { v => Literal(Constant(v)) }
- implicit def liftByte[T <: Byte]: Liftable[T] = liftAsLiteral[T]
- implicit def liftShort[T <: Short]: Liftable[T] = liftAsLiteral[T]
- implicit def liftChar[T <: Char]: Liftable[T] = liftAsLiteral[T]
- implicit def liftInt[T <: Int]: Liftable[T] = liftAsLiteral[T]
- implicit def liftLong[T <: Long]: Liftable[T] = liftAsLiteral[T]
- implicit def liftFloat[T <: Float]: Liftable[T] = liftAsLiteral[T]
- implicit def liftDouble[T <: Double]: Liftable[T] = liftAsLiteral[T]
- implicit def liftBoolean: Liftable[Boolean] = liftAsLiteral[Boolean]
- implicit def liftUnit: Liftable[Unit] = liftAsLiteral[Unit]
- implicit def liftString: Liftable[String] = liftAsLiteral[String]
+ implicit def liftByte[T <: Byte]: Liftable[T] = liftAsLiteral[T]
+ implicit def liftShort[T <: Short]: Liftable[T] = liftAsLiteral[T]
+ implicit def liftChar[T <: Char]: Liftable[T] = liftAsLiteral[T]
+ implicit def liftInt[T <: Int]: Liftable[T] = liftAsLiteral[T]
+ implicit def liftLong[T <: Long]: Liftable[T] = liftAsLiteral[T]
+ implicit def liftFloat[T <: Float]: Liftable[T] = liftAsLiteral[T]
+ implicit def liftDouble[T <: Double]: Liftable[T] = liftAsLiteral[T]
+ implicit def liftBoolean[T <: Boolean]: Liftable[T] = liftAsLiteral[T]
+ implicit def liftUnit: Liftable[Unit] = liftAsLiteral[Unit]
+ implicit def liftString[T <: String]: Liftable[T] = liftAsLiteral[T]
implicit def liftScalaSymbol: Liftable[scala.Symbol] = Liftable { v =>
callScala(nme.Symbol)(Literal(Constant(v.name)) :: Nil)
@@ -35,16 +35,22 @@ trait StandardLiftables { self: Universe =>
implicit def liftArray[T: Liftable]: Liftable[Array[T]] = Liftable { arr => callScala(nme.Array)(arr.map(lift(_)).toList) }
implicit def liftVector[T: Liftable]: Liftable[Vector[T]] = Liftable { vect => callCollection(nme.Vector)(vect.map(lift(_)).toList) }
implicit def liftList[T: Liftable]: Liftable[List[T]] = Liftable { lst => callCollection(nme.List)(lst.map(lift(_))) }
+ implicit def liftNil: Liftable[Nil.type] = Liftable { _ => selectScala(nme.collection, nme.immutable, nme.Nil) }
implicit def liftMap[K: Liftable, V: Liftable]: Liftable[Map[K, V]] = Liftable { m => callCollection(nme.Map)(m.toList.map(lift(_))) }
implicit def liftSet[T: Liftable]: Liftable[Set[T]] = Liftable { s => callCollection(nme.Set)(s.toList.map(lift(_))) }
+ implicit def liftSome[T: Liftable]: Liftable[Some[T]] = Liftable { case Some(v) => callScala(nme.Some)(lift(v) :: Nil) }
+ implicit def liftNone: Liftable[None.type] = Liftable { _ => selectScala(nme.None) }
implicit def liftOption[T: Liftable]: Liftable[Option[T]] = Liftable {
- case Some(v) => callScala(nme.Some)(lift(v) :: Nil)
- case None => selectScala(nme.None)
+ case some: Some[T] => lift(some)
+ case none: None.type => lift(none)
}
+
+ implicit def liftLeft[L: Liftable, R]: Liftable[Left[L, R]] = Liftable { case Left(v) => callScala(nme.util, nme.Left)(lift(v) :: Nil) }
+ implicit def liftRight[L, R: Liftable]: Liftable[Right[L, R]] = Liftable { case Right(v) => callScala(nme.util, nme.Right)(lift(v) :: Nil) }
implicit def liftEither[L: Liftable, R: Liftable]: Liftable[Either[L, R]] = Liftable {
- case Left(l) => callScala(nme.util, nme.Left)(lift(l) :: Nil)
- case Right(r) => callScala(nme.util, nme.Right)(lift(r) :: Nil)
+ case left: Left[L, R] => lift(left)
+ case right: Right[L, R] => lift(right)
}
implicit def liftTuple1[T1](implicit liftT1: Liftable[T1]): Liftable[Tuple1[T1]] = Liftable { t =>
@@ -220,6 +226,7 @@ trait StandardLiftables { self: Universe =>
val List = TermName("List")
val Map = TermName("Map")
val None = TermName("None")
+ val Nil = TermName("Nil")
val Right = TermName("Right")
val Set = TermName("Set")
val Some = TermName("Some")
diff --git a/src/reflect/scala/reflect/internal/BuildUtils.scala b/src/reflect/scala/reflect/internal/BuildUtils.scala
index 0a81bfa2a5..9b19dc11cb 100644
--- a/src/reflect/scala/reflect/internal/BuildUtils.scala
+++ b/src/reflect/scala/reflect/internal/BuildUtils.scala
@@ -455,14 +455,14 @@ trait BuildUtils { self: SymbolTable =>
}
}
- def UnliftHelper1[T](unliftable: Unliftable[T]) = new UnliftHelper1[T] {
+ def UnliftListElementwise[T](unliftable: Unliftable[T]) = new UnliftListElementwise[T] {
def unapply(lst: List[Tree]): Option[List[T]] = {
val unlifted = lst.flatMap { unliftable.unapply(_) }
if (unlifted.length == lst.length) Some(unlifted) else None
}
}
- def UnliftHelper2[T](unliftable: Unliftable[T]) = new UnliftHelper2[T] {
+ def UnliftListOfListsElementwise[T](unliftable: Unliftable[T]) = new UnliftListOfListsElementwise[T] {
def unapply(lst: List[List[Tree]]): Option[List[List[T]]] = {
val unlifted = lst.map { l => l.flatMap { unliftable.unapply(_) } }
if (unlifted.flatten.length == lst.flatten.length) Some(unlifted) else None
diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala
index a54aa1f6e8..ed3e7dbc4c 100644
--- a/src/reflect/scala/reflect/internal/StdNames.scala
+++ b/src/reflect/scala/reflect/internal/StdNames.scala
@@ -763,8 +763,8 @@ trait StdNames {
val unapplySeq: NameType = "unapplySeq"
val unbox: NameType = "unbox"
val universe: NameType = "universe"
- val UnliftHelper1: NameType = "UnliftHelper1"
- val UnliftHelper2: NameType = "UnliftHelper2"
+ val UnliftListElementwise: NameType = "UnliftListElementwise"
+ val UnliftListOfListsElementwise: NameType = "UnliftListOfListsElementwise"
val update: NameType = "update"
val updateDynamic: NameType = "updateDynamic"
val value: NameType = "value"
diff --git a/test/files/scalacheck/quasiquotes/LiftableProps.scala b/test/files/scalacheck/quasiquotes/LiftableProps.scala
index 539375d905..bd631b8734 100644
--- a/test/files/scalacheck/quasiquotes/LiftableProps.scala
+++ b/test/files/scalacheck/quasiquotes/LiftableProps.scala
@@ -5,51 +5,62 @@ object LiftableProps extends QuasiquoteProperties("liftable") {
property("splice byte") = test {
val c: Byte = 0
assert(q"$c" ≈ Literal(Constant(c)))
+ assert(q"${0: Byte}" ≈ Literal(Constant(c)))
}
property("splice short") = test {
val c: Short = 0
assert(q"$c" ≈ Literal(Constant(c)))
+ assert(q"${0: Short}" ≈ Literal(Constant(c)))
}
property("splice char") = test {
val c: Char = 'c'
assert(q"$c" ≈ Literal(Constant(c)))
+ assert(q"${'c'}" ≈ Literal(Constant(c)))
}
property("splice int") = test {
val c: Int = 0
assert(q"$c" ≈ Literal(Constant(c)))
+ assert(q"${0: Int}" ≈ Literal(Constant(c)))
}
property("splice long") = test {
val c: Long = 0
assert(q"$c" ≈ Literal(Constant(c)))
+ assert(q"${0: Long}" ≈ Literal(Constant(c)))
}
property("splice float") = test {
val c: Float = 0.0f
assert(q"$c" ≈ Literal(Constant(c)))
+ assert(q"${0.0f: Float}" ≈ Literal(Constant(c)))
}
property("splice double") = test {
val c: Double = 0.0
assert(q"$c" ≈ Literal(Constant(c)))
+ assert(q"${0.0: Double}" ≈ Literal(Constant(c)))
}
property("splice boolean") = test {
val c: Boolean = false
assert(q"$c" ≈ Literal(Constant(c)))
+ assert(q"${true}" ≈ Literal(Constant(true)))
+ assert(q"${false}" ≈ Literal(Constant(false)))
}
property("splice string") = test {
val c: String = "s"
assert(q"$c" ≈ Literal(Constant(c)))
+ assert(q"${"s"}" ≈ Literal(Constant(c)))
}
property("splice unit") = test {
val c: Unit = ()
assert(q"$c" ≈ Literal(Constant(c)))
+ assert(q"${()}" ≈ Literal(Constant(c)))
}
property("lift symbol") = test {
@@ -111,4 +122,41 @@ object LiftableProps extends QuasiquoteProperties("liftable") {
assert(q"${(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21)}" ≈ q"(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21)")
assert(q"${(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22)}" ≈ q"(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22)")
}
-} \ No newline at end of file
+
+ property("lift nil") = test {
+ val nil = Nil
+ assert(q"$nil" ≈ q"scala.collection.immutable.Nil")
+ }
+
+ property("lift some") = test {
+ val some1 = Some(1)
+ assert(q"$some1" ≈ q"scala.Some(1)")
+ val some2: Option[Int] = Some(1)
+ assert(q"$some2" ≈ q"scala.Some(1)")
+ }
+
+ property("lift none") = test {
+ val none1 = None
+ assert(q"$none1" ≈ q"scala.None")
+ val none2: Option[Int] = None
+ assert(q"$none2" ≈ q"scala.None")
+ }
+
+ property("lift left") = test {
+ val left1 = Left(1)
+ assert(q"$left1" ≈ q"scala.util.Left(1)")
+ val left2: Left[Int, Int] = Left(1)
+ assert(q"$left2" ≈ q"scala.util.Left(1)")
+ val left3: Either[Int, Int] = Left(1)
+ assert(q"$left3" ≈ q"scala.util.Left(1)")
+ }
+
+ property("lift right") = test {
+ val right1 = Right(1)
+ assert(q"$right1" ≈ q"scala.util.Right(1)")
+ val right2: Right[Int, Int] = Right(1)
+ assert(q"$right2" ≈ q"scala.util.Right(1)")
+ val right3: Either[Int, Int] = Right(1)
+ assert(q"$right3" ≈ q"scala.util.Right(1)")
+ }
+}