Skip to content

Instantly share code, notes, and snippets.

@paulp
Created May 25, 2010 00:17
Show Gist options
  • Save paulp/412593 to your computer and use it in GitHub Desktop.
Save paulp/412593 to your computer and use it in GitHub Desktop.
diff --git a/src/library/scala/reflect/ClassManifest.scala b/src/library/scala/reflect/ClassManifest.scala
index 3b05a58..73ddb01 100644
--- a/src/library/scala/reflect/ClassManifest.scala
+++ b/src/library/scala/reflect/ClassManifest.scala
@@ -72,6 +72,10 @@ trait ClassManifest[T] extends OptManifest[T] with Equals {
def >:>(that: ClassManifest[_]): Boolean =
that <:< this
+ /** Tests for weak conformance.
+ */
+ def weak_<:<(that: ClassManifest[_]): Boolean = this <:< that
+
def canEqual(other: Any) = other match {
case _: ClassManifest[_] => true
case _ => false
diff --git a/src/library/scala/reflect/Manifest.scala b/src/library/scala/reflect/Manifest.scala
index a042b20..53ff0a0 100644
--- a/src/library/scala/reflect/Manifest.scala
+++ b/src/library/scala/reflect/Manifest.scala
@@ -45,7 +45,16 @@ trait Manifest[T] extends ClassManifest[T] with Equals {
@serializable
trait AnyValManifest[T] extends Manifest[T] with Equals {
- import Manifest.{ Any, AnyVal }
+ import Manifest._
+
+ def weakIndex: Int
+ protected def weak_only_<:<(that: ClassManifest[_]) = that match {
+ case Char | Boolean | Unit => false
+ case x: AnyValManifest[_] => weakIndex < x.weakIndex
+ case _ => false
+ }
+
+ override final def weak_<:<(that: ClassManifest[_]) = (this <:< that) || (this weak_only_<:< that)
override def <:<(that: ClassManifest[_]): Boolean = (that eq this) || (that eq Any) || (that eq AnyVal)
override def canEqual(other: Any) = other match {
case _: AnyValManifest[_] => true
@@ -65,8 +74,9 @@ trait AnyValManifest[T] extends Manifest[T] with Equals {
* will be implemented in a later version of this class.
* </p>
*/
-object Manifest {
+object Manifest {
val Byte: AnyValManifest[Byte] = new (AnyValManifest[Byte] @serializable) {
+ val weakIndex = 0
def erasure = java.lang.Byte.TYPE
override def toString = "Byte"
override def newArray(len: Int): Array[Byte] = new Array[Byte](len)
@@ -76,6 +86,7 @@ object Manifest {
}
val Short: AnyValManifest[Short] = new (AnyValManifest[Short] @serializable) {
+ val weakIndex = 1
def erasure = java.lang.Short.TYPE
override def toString = "Short"
override def newArray(len: Int): Array[Short] = new Array[Short](len)
@@ -85,6 +96,11 @@ object Manifest {
}
val Char: AnyValManifest[Char] = new (AnyValManifest[Char] @serializable) {
+ val weakIndex = -1
+ override protected def weak_only_<:<(that: ClassManifest[_]) = that match {
+ case Int | Long | Float | Double => true
+ case _ => false
+ }
def erasure = java.lang.Character.TYPE
override def toString = "Char"
override def newArray(len: Int): Array[Char] = new Array[Char](len)
@@ -94,6 +110,7 @@ object Manifest {
}
val Int: AnyValManifest[Int] = new (AnyValManifest[Int] @serializable) {
+ val weakIndex = 2
def erasure = java.lang.Integer.TYPE
override def toString = "Int"
override def newArray(len: Int): Array[Int] = new Array[Int](len)
@@ -103,6 +120,7 @@ object Manifest {
}
val Long: AnyValManifest[Long] = new (AnyValManifest[Long] @serializable) {
+ val weakIndex = 3
def erasure = java.lang.Long.TYPE
override def toString = "Long"
override def newArray(len: Int): Array[Long] = new Array[Long](len)
@@ -112,6 +130,7 @@ object Manifest {
}
val Float: AnyValManifest[Float] = new (AnyValManifest[Float] @serializable) {
+ val weakIndex = 4
def erasure = java.lang.Float.TYPE
override def toString = "Float"
override def newArray(len: Int): Array[Float] = new Array[Float](len)
@@ -121,6 +140,7 @@ object Manifest {
}
val Double: AnyValManifest[Double] = new (AnyValManifest[Double] @serializable) {
+ val weakIndex = 5
def erasure = java.lang.Double.TYPE
override def toString = "Double"
override def newArray(len: Int): Array[Double] = new Array[Double](len)
@@ -130,6 +150,8 @@ object Manifest {
}
val Boolean: AnyValManifest[Boolean] = new (AnyValManifest[Boolean] @serializable) {
+ val weakIndex = -1
+ override protected def weak_only_<:<(that: ClassManifest[_]) = false
def erasure = java.lang.Boolean.TYPE
override def toString = "Boolean"
override def newArray(len: Int): Array[Boolean] = new Array[Boolean](len)
@@ -139,6 +161,8 @@ object Manifest {
}
val Unit: AnyValManifest[Unit] = new (AnyValManifest[Unit] @serializable) {
+ val weakIndex = -1
+ override protected def weak_only_<:<(that: ClassManifest[_]) = false
def erasure = java.lang.Void.TYPE
override def toString = "Unit"
override def newArray(len: Int): Array[Unit] = new Array[Unit](len)
diff --git a/src/library/scala/reflect/WeakConformance.scala b/src/library/scala/reflect/WeakConformance.scala
new file mode 100644
index 0000000..eb04838
--- /dev/null
+++ b/src/library/scala/reflect/WeakConformance.scala
@@ -0,0 +1,138 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.reflect
+
+object WeakConformance {
+ import Manifest._
+ def numericTypes: List[AnyValManifest[_]] = List(Byte, Char, Short, Int, Long, Float, Double)
+
+ def foldManifests(xs: Traversable[Manifest[_]]): Manifest[_] =
+ xs.reduceLeft { (m1, m2) =>
+ if (m1 weak_<:< m2) m2
+ else if (m2 weak_<:< m1) m1
+ else error(m1 + ", " + m2)
+ }
+
+ def unify[A, B, C](a: A, b: B)(implicit ev: weak_unify[A, B, C]): (C, C) = (ev.aToC(a), ev.bToC(b))
+
+ implicit def weakSameSame[T]: weak_unify[T, T, T] = new weak_unify[T, T, T] {
+ def aToC(x: T): T = x
+ def bToC(x: T): T = x
+ }
+
+ sealed abstract class weak_<:<[A <: AnyVal, B <: AnyVal] extends (A => B)
+ sealed abstract class weak_>:>[A <: AnyVal, B <: AnyVal] extends (B => A)
+ sealed abstract class weak_unify[A, B, C] {
+ def aToC(a: A): C
+ def bToC(b: B): C
+ }
+
+ implicit val weakByteShort: weak_unify[Byte, Short, Short] = new weak_unify[Byte, Short, Short] {
+ def aToC(x: Byte): Short = x
+ def bToC(x: Short): Short = x
+ }
+ implicit val weakByteInt: weak_unify[Byte, Int, Int] = new weak_unify[Byte, Int, Int] {
+ def aToC(x: Byte): Int = x
+ def bToC(x: Int): Int = x
+ }
+ implicit val weakByteLong: weak_unify[Byte, Long, Long] = new weak_unify[Byte, Long, Long] {
+ def aToC(x: Byte): Long = x
+ def bToC(x: Long): Long = x
+ }
+ implicit val weakByteFloat: weak_unify[Byte, Float, Float] = new weak_unify[Byte, Float, Float] {
+ def aToC(x: Byte): Float = x
+ def bToC(x: Float): Float = x
+ }
+ implicit val weakByteDouble: weak_unify[Byte, Double, Double] = new weak_unify[Byte, Double, Double] {
+ def aToC(x: Byte): Double = x
+ def bToC(x: Double): Double = x
+ }
+ implicit val weakCharInt: weak_unify[Char, Int, Int] = new weak_unify[Char, Int, Int] {
+ def aToC(x: Char): Int = x
+ def bToC(x: Int): Int = x
+ }
+ implicit val weakCharLong: weak_unify[Char, Long, Long] = new weak_unify[Char, Long, Long] {
+ def aToC(x: Char): Long = x
+ def bToC(x: Long): Long = x
+ }
+ implicit val weakCharFloat: weak_unify[Char, Float, Float] = new weak_unify[Char, Float, Float] {
+ def aToC(x: Char): Float = x
+ def bToC(x: Float): Float = x
+ }
+ implicit val weakCharDouble: weak_unify[Char, Double, Double] = new weak_unify[Char, Double, Double] {
+ def aToC(x: Char): Double = x
+ def bToC(x: Double): Double = x
+ }
+ implicit val weakShortInt: weak_unify[Short, Int, Int] = new weak_unify[Short, Int, Int] {
+ def aToC(x: Short): Int = x
+ def bToC(x: Int): Int = x
+ }
+ implicit val weakShortLong: weak_unify[Short, Long, Long] = new weak_unify[Short, Long, Long] {
+ def aToC(x: Short): Long = x
+ def bToC(x: Long): Long = x
+ }
+ implicit val weakShortFloat: weak_unify[Short, Float, Float] = new weak_unify[Short, Float, Float] {
+ def aToC(x: Short): Float = x
+ def bToC(x: Float): Float = x
+ }
+ implicit val weakShortDouble: weak_unify[Short, Double, Double] = new weak_unify[Short, Double, Double] {
+ def aToC(x: Short): Double = x
+ def bToC(x: Double): Double = x
+ }
+ implicit val weakIntLong: weak_unify[Int, Long, Long] = new weak_unify[Int, Long, Long] {
+ def aToC(x: Int): Long = x
+ def bToC(x: Long): Long = x
+ }
+ implicit val weakIntFloat: weak_unify[Int, Float, Float] = new weak_unify[Int, Float, Float] {
+ def aToC(x: Int): Float = x
+ def bToC(x: Float): Float = x
+ }
+ implicit val weakIntDouble: weak_unify[Int, Double, Double] = new weak_unify[Int, Double, Double] {
+ def aToC(x: Int): Double = x
+ def bToC(x: Double): Double = x
+ }
+ implicit val weakLongFloat: weak_unify[Long, Float, Float] = new weak_unify[Long, Float, Float] {
+ def aToC(x: Long): Float = x
+ def bToC(x: Float): Float = x
+ }
+ implicit val weakLongDouble: weak_unify[Long, Double, Double] = new weak_unify[Long, Double, Double] {
+ def aToC(x: Long): Double = x
+ def bToC(x: Double): Double = x
+ }
+ implicit val weakFloatDouble: weak_unify[Float, Double, Double] = new weak_unify[Float, Double, Double] {
+ def aToC(x: Float): Double = x
+ def bToC(x: Double): Double = x
+ }
+
+ def generateWeakUnify = {
+ for (m1 <- numericTypes ; m2 <- numericTypes) {
+ val conforms = m1 match {
+ case Char => List(Int, Long, Double, Float) contains m2
+ case _ => m1.weakIndex < m2.weakIndex
+ }
+
+ val template =
+ """|implicit val weak%s%s: %s = new %s {
+ | def aToC(x: %s): %s = x
+ | def bToC(x: %s): %s = x
+ |}"""
+
+ val typeString = "weak_unify[%s, %s, %s]".format(m1, m2, m2)
+
+ if (conforms) {
+ println(template.stripMargin.format(
+ m1, m2,
+ typeString, typeString,
+ m1, m2,
+ m2, m2
+ ))
+ }
+ }
+ }
+}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment