diff options
-rw-r--r-- | src/library/scala/LowPriorityImplicits.scala | 13 | ||||
-rw-r--r-- | src/library/scala/Predef.scala | 24 | ||||
-rw-r--r-- | src/library/scala/Proxy.scala | 34 | ||||
-rw-r--r-- | src/library/scala/math/Numeric.scala | 12 | ||||
-rw-r--r-- | src/library/scala/runtime/RichBoolean.scala | 11 | ||||
-rw-r--r-- | src/library/scala/runtime/RichByte.scala | 13 | ||||
-rw-r--r-- | src/library/scala/runtime/RichChar.scala | 95 | ||||
-rw-r--r-- | src/library/scala/runtime/RichDouble.scala | 54 | ||||
-rw-r--r-- | src/library/scala/runtime/RichFloat.scala | 36 | ||||
-rw-r--r-- | src/library/scala/runtime/RichInt.scala | 38 | ||||
-rw-r--r-- | src/library/scala/runtime/RichLong.scala | 38 | ||||
-rw-r--r-- | src/library/scala/runtime/RichShort.scala | 13 | ||||
-rw-r--r-- | src/library/scala/runtime/ScalaNumberProxy.scala | 80 | ||||
-rw-r--r-- | test/files/run/richWrapperEquals.scala | 10 |
14 files changed, 228 insertions, 243 deletions
diff --git a/src/library/scala/LowPriorityImplicits.scala b/src/library/scala/LowPriorityImplicits.scala index 32bdf7e30d..1b9a65cdaf 100644 --- a/src/library/scala/LowPriorityImplicits.scala +++ b/src/library/scala/LowPriorityImplicits.scala @@ -21,6 +21,19 @@ import collection.generic.CanBuildFrom * @since 2.8 */ class LowPriorityImplicits { + /** We prefer the java.lang.* boxed types to these wrappers in + * any potential conflicts. Conflicts do exist because the wrappers + * need to implement ScalaNumber in order to have a symmetric equals + * method, but that implies implementing java.lang.Number as well. + */ + implicit def byteWrapper(x: Byte) = new runtime.RichByte(x) + implicit def shortWrapper(x: Short) = new runtime.RichShort(x) + implicit def intWrapper(x: Int) = new runtime.RichInt(x) + implicit def charWrapper(c: Char) = new runtime.RichChar(c) + implicit def longWrapper(x: Long) = new runtime.RichLong(x) + implicit def floatWrapper(x: Float) = new runtime.RichFloat(x) + implicit def doubleWrapper(x: Double) = new runtime.RichDouble(x) + implicit def booleanWrapper(x: Boolean) = new runtime.RichBoolean(x) implicit def genericWrapArray[T](xs: Array[T]): WrappedArray[T] = if (xs ne null) WrappedArray.make(xs) else null diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala index bd8f6b6822..2c60a8e8a8 100644 --- a/src/library/scala/Predef.scala +++ b/src/library/scala/Predef.scala @@ -199,19 +199,8 @@ object Predef extends LowPriorityImplicits { // views -------------------------------------------------------------- - implicit def byteWrapper(x: Byte) = new runtime.RichByte(x) - implicit def shortWrapper(x: Short) = new runtime.RichShort(x) - implicit def intWrapper(x: Int) = new runtime.RichInt(x) - implicit def charWrapper(c: Char) = new runtime.RichChar(c) - implicit def longWrapper(x: Long) = new runtime.RichLong(x) - implicit def floatWrapper(x: Float) = new runtime.RichFloat(x) - implicit def doubleWrapper(x: Double) = new runtime.RichDouble(x) - implicit def booleanWrapper(x: Boolean) = new runtime.RichBoolean(x) - implicit def exceptionWrapper(exc: Throwable) = new runtime.RichException(exc) - // tuple zip views - implicit def zipped2ToTraversable[El1, El2](zz: Tuple2[_, _]#Zipped[_, El1, _, El2]): Traversable[(El1, El2)] = new Traversable[(El1, El2)] { def foreach[U](f: ((El1, El2)) => U): Unit = zz foreach Function.untupled(f) @@ -285,6 +274,19 @@ object Predef extends LowPriorityImplicits { implicit def double2Double(x: Double) = java.lang.Double.valueOf(x) implicit def boolean2Boolean(x: Boolean) = java.lang.Boolean.valueOf(x) + // These next eight implicits exist solely to exclude AnyRef methods from the + // eight implicits above so that primitives are not coerced to AnyRefs. They + // only create such conflict for AnyRef methods, so the methods on the java.lang + // boxed types are unambiguously reachable. + implicit def byte2ByteConflict(x: Byte) = new AnyRef + implicit def short2ShortConflict(x: Short) = new AnyRef + implicit def char2CharacterConflict(x: Char) = new AnyRef + implicit def int2IntegerConflict(x: Int) = new AnyRef + implicit def long2LongConflict(x: Long) = new AnyRef + implicit def float2FloatConflict(x: Float) = new AnyRef + implicit def double2DoubleConflict(x: Double) = new AnyRef + implicit def boolean2BooleanConflict(x: Boolean) = new AnyRef + implicit def Byte2byte(x: java.lang.Byte): Byte = x.byteValue implicit def Short2short(x: java.lang.Short): Short = x.shortValue implicit def Character2char(x: java.lang.Character): Char = x.charValue diff --git a/src/library/scala/Proxy.scala b/src/library/scala/Proxy.scala index feac5904a5..b7bf8eeef3 100644 --- a/src/library/scala/Proxy.scala +++ b/src/library/scala/Proxy.scala @@ -6,24 +6,38 @@ ** |/ ** \* */ - - package scala - /** This class implements a simple proxy that forwards all calls to - * methods of class <code>Any</code> to another object <code>self</code>. - * Please note that only those methods can be forwarded that are - * overridable and public. + * the public, non-final methods defined in class "Any" to another + * object self. Those methods are: + * + * def hashCode(): Int + * def equals(other: Any): Boolean + * def toString(): String + * + * Note: forwarding methods in this way will most likely create + * an asymmetric equals method, which is not generally recommended. * * @author Matthias Zenger * @version 1.0, 26/04/2004 */ trait Proxy { def self: Any - override def hashCode: Int = self.## - override def equals(that: Any): Boolean = - if(that == null) false - else that equals self + + override def hashCode: Int = self.hashCode + override def equals(that: Any): Boolean = that match { + case null => false + case x: Equals => (x canEqual self) && (x equals self) + case x => (x equals self) + } override def toString: String = self.toString } + +object Proxy { + /** A proxy which exposes the type it is proxying for via a type parameter. + */ + trait Typed[T] extends Proxy { + def self: T + } +} diff --git a/src/library/scala/math/Numeric.scala b/src/library/scala/math/Numeric.scala index 673461132f..9cf2a15439 100644 --- a/src/library/scala/math/Numeric.scala +++ b/src/library/scala/math/Numeric.scala @@ -104,11 +104,10 @@ object Numeric { } implicit object LongIsIntegral extends LongIsIntegral with Ordering.LongOrdering - trait FloatIsFractional extends Fractional[Float] { + trait FloatIsConflicted extends Numeric[Float] { def plus(x: Float, y: Float): Float = x + y def minus(x: Float, y: Float): Float = x - y def times(x: Float, y: Float): Float = x * y - def div(x: Float, y: Float): Float = x / y def negate(x: Float): Float = -x def fromInt(x: Int): Float = x def toInt(x: Float): Int = x.toInt @@ -116,7 +115,16 @@ object Numeric { def toFloat(x: Float): Float = x def toDouble(x: Float): Double = x } + trait FloatIsFractional extends FloatIsConflicted with Fractional[Float] { + def div(x: Float, y: Float): Float = x / y + } + trait FloatAsIfIntegral extends FloatIsConflicted with Integral[Float] { + def quot(x: Float, y: Float): Float = (BigDecimal(x) / BigDecimal(y)).floatValue + def rem(x: Float, y: Float): Float = (BigDecimal(x) remainder BigDecimal(y)).floatValue + } implicit object FloatIsFractional extends FloatIsFractional with Ordering.FloatOrdering + object FloatAsIfIntegral extends FloatAsIfIntegral with Ordering.FloatOrdering { + } trait DoubleIsConflicted extends Numeric[Double] { def plus(x: Double, y: Double): Double = x + y diff --git a/src/library/scala/runtime/RichBoolean.scala b/src/library/scala/runtime/RichBoolean.scala index bfff5dae94..289f287b19 100644 --- a/src/library/scala/runtime/RichBoolean.scala +++ b/src/library/scala/runtime/RichBoolean.scala @@ -10,13 +10,6 @@ package scala.runtime - -final class RichBoolean(x: Boolean) extends Proxy with Ordered[Boolean] { - - // Proxy.self - def self: Any = x - - // Ordered[Boolean].compare - def compare (y: Boolean): Int = if (x == y) 0 else if (x) 1 else -1 - +final class RichBoolean(val self: Boolean) extends OrderedProxy[Boolean] { + protected val ord = Ordering[Boolean] } diff --git a/src/library/scala/runtime/RichByte.scala b/src/library/scala/runtime/RichByte.scala index 52ec045217..fc3a75a0b8 100644 --- a/src/library/scala/runtime/RichByte.scala +++ b/src/library/scala/runtime/RichByte.scala @@ -6,17 +6,6 @@ ** |/ ** \* */ - - package scala.runtime - -final class RichByte(x: Byte) extends Proxy with Ordered[Byte] { - - // Proxy.self - def self: Any = x - - // Ordered[Byte].compare - def compare (y: Byte): Int = if (x < y) -1 else if (x > y) 1 else 0 - -} +final class RichByte(val self: Byte) extends ScalaWholeNumberProxy[Byte] { } diff --git a/src/library/scala/runtime/RichChar.scala b/src/library/scala/runtime/RichChar.scala index b8324fa221..675af3aada 100644 --- a/src/library/scala/runtime/RichChar.scala +++ b/src/library/scala/runtime/RichChar.scala @@ -6,65 +6,39 @@ ** |/ ** \* */ - - package scala.runtime import java.lang.Character -import collection.immutable.NumericRange - -/** <p> - * For example, in the following code - * </p> - * <pre> - * <b>object</b> test <b>extends</b> Application { - * Console.println(<chr>'\40'</chr>.isWhitespace) - * Console.println('\011'.isWhitespace) - * Console.println('1'.asDigit == 1) - * Console.println('A'.asDigit == 10) - * }</pre> - * <p> - * the implicit conversions are performed using the predefined view - * <a href="../Predef$object.html#charWrapper(scala.Char)" - * target="contentFrame"><code>Predef.charWrapper</code></a>. - * </p> - */ -final class RichChar(x: Char) extends Proxy with Ordered[Char] { - - // Proxy.self - def self: Any = x - - // Ordered[Char].compare - def compare (y: Char): Int = if (x < y) -1 else if (x > y) 1 else 0 - - def asDigit: Int = Character.digit(x, Character.MAX_RADIX) - def isControl: Boolean = Character.isISOControl(x) - def isDigit: Boolean = Character.isDigit(x) - def isLetter: Boolean = Character.isLetter(x) - def isLetterOrDigit: Boolean = Character.isLetterOrDigit(x) - def isWhitespace: Boolean = Character.isWhitespace(x) - def isSpaceChar: Boolean = Character.isSpaceChar(x) - def isHighSurrogate: Boolean = Character.isHighSurrogate(x) - def isLowSurrogate: Boolean = Character.isLowSurrogate(x) - def isSurrogate: Boolean = isHighSurrogate || isLowSurrogate - def isUnicodeIdentifierStart: Boolean = Character.isUnicodeIdentifierStart(x) - def isUnicodeIdentifierPart: Boolean = Character.isUnicodeIdentifierPart(x) - def isIdentifierIgnorable: Boolean = Character.isIdentifierIgnorable(x) - def isMirrored: Boolean = Character.isMirrored(x) - - def isLower: Boolean = Character.isLowerCase(x) - def isUpper: Boolean = Character.isUpperCase(x) - def isTitleCase: Boolean = Character.isTitleCase(x) - - def toLower: Char = Character.toLowerCase(x) - def toUpper: Char = Character.toUpperCase(x) - def toTitleCase: Char = Character.toTitleCase(x) - - def getType: Int = Character.getType(x) - def getNumericValue: Int = Character.getNumericValue(x) - def getDirectionality: Byte = Character.getDirectionality(x) - def reverseBytes: Char = Character.reverseBytes(x) +final class RichChar(val self: Char) extends IntegralProxy[Char] { + def asDigit: Int = Character.digit(self, Character.MAX_RADIX) + + def isControl: Boolean = Character.isISOControl(self) + def isDigit: Boolean = Character.isDigit(self) + def isLetter: Boolean = Character.isLetter(self) + def isLetterOrDigit: Boolean = Character.isLetterOrDigit(self) + def isWhitespace: Boolean = Character.isWhitespace(self) + def isSpaceChar: Boolean = Character.isSpaceChar(self) + def isHighSurrogate: Boolean = Character.isHighSurrogate(self) + def isLowSurrogate: Boolean = Character.isLowSurrogate(self) + def isSurrogate: Boolean = isHighSurrogate || isLowSurrogate + def isUnicodeIdentifierStart: Boolean = Character.isUnicodeIdentifierStart(self) + def isUnicodeIdentifierPart: Boolean = Character.isUnicodeIdentifierPart(self) + def isIdentifierIgnorable: Boolean = Character.isIdentifierIgnorable(self) + def isMirrored: Boolean = Character.isMirrored(self) + + def isLower: Boolean = Character.isLowerCase(self) + def isUpper: Boolean = Character.isUpperCase(self) + def isTitleCase: Boolean = Character.isTitleCase(self) + + def toLower: Char = Character.toLowerCase(self) + def toUpper: Char = Character.toUpperCase(self) + def toTitleCase: Char = Character.toTitleCase(self) + + def getType: Int = Character.getType(self) + def getNumericValue: Int = Character.getNumericValue(self) + def getDirectionality: Byte = Character.getDirectionality(self) + def reverseBytes: Char = Character.reverseBytes(self) // Java 5 Character methods not added: // @@ -81,15 +55,4 @@ final class RichChar(x: Char) extends Proxy with Ordered[Char] { def isLowerCase: Boolean = isLower @deprecated("Use ch.isUpper instead") def isUpperCase: Boolean = isUpper - - /** Create a <code>[Char]</code> over the characters from 'x' to 'limit' - 1 - */ - def until(limit: Char): NumericRange[Char] = - new NumericRange.Exclusive(x, limit, 1.toChar) - - /** Create a <code>IndexedSeqView[Char]</code> over the characters from 'x' to 'limit' - */ - def to(limit: Char): NumericRange[Char] = - new NumericRange.Inclusive(x, limit, 1.toChar) - } diff --git a/src/library/scala/runtime/RichDouble.scala b/src/library/scala/runtime/RichDouble.scala index 64976acb12..607bde1fb5 100644 --- a/src/library/scala/runtime/RichDouble.scala +++ b/src/library/scala/runtime/RichDouble.scala @@ -6,62 +6,34 @@ ** |/ ** \* */ - - package scala.runtime -import scala.collection.immutable.{Range, NumericRange} - -final class RichDouble(x: Double) extends Proxy with Ordered[Double] { - // Proxy.self - def self: Any = x - - def compare(y: Double): Int = java.lang.Double.compare(x, y) - - def min(y: Double): Double = math.min(x, y) - def max(y: Double): Double = math.max(x, y) - def abs: Double = math.abs(x) +final class RichDouble(val self: Double) extends FractionalProxy[Double] { + protected val integralNum = Numeric.DoubleAsIfIntegral - def round: Long = math.round(x) - def ceil: Double = math.ceil(x) - def floor: Double = math.floor(x) - - /** See <code>BigDecimal.until</code>. */ - def until(end: Double): Range.Partial[Double, NumericRange[Double]] = - new Range.Partial(until(end, _)) - - /** See <code>BigDecimal.until</code>. */ - def until(end: Double, step: Double): NumericRange[Double] = - Range.Double(x, end, step) - - /** See <code>BigDecimal.to</code>. */ - def to(end: Double): Range.Partial[Double, NumericRange[Double]] = - new Range.Partial(to(end, _)) - - /** See <code>BigDecimal.to</code>. */ - def to(end: Double, step: Double): NumericRange[Double] = - Range.Double.inclusive(x, end, step) + def round: Long = math.round(self) + def ceil: Double = math.ceil(self) + def floor: Double = math.floor(self) /** Converts an angle measured in degrees to an approximately equivalent * angle measured in radians. * * @param x an angle, in degrees - * @return the measurement of the angle <code>x</code> in radians. + * @return the measurement of the angle x in radians. */ - def toRadians: Double = math.toRadians(x) + def toRadians: Double = math.toRadians(self) /** Converts an angle measured in radians to an approximately equivalent * angle measured in degrees * * @param x angle, in radians - * @return the measurement of the angle <code>x</code> in degrees. + * @return the measurement of the angle x in degrees. */ - def toDegrees: Double = math.toDegrees(x) + def toDegrees: Double = math.toDegrees(self) // isNaN is provided by the implicit conversion to java.lang.Double - // def isNaN: Boolean = java.lang.Double.isNaN(x) - def isInfinity: Boolean = java.lang.Double.isInfinite(x) - def isPosInfinity: Boolean = isInfinity && x > 0.0 - def isNegInfinity: Boolean = isInfinity && x < 0.0 - + // def isNaN: Boolean = java.lang.Double.isNaN(self) + def isInfinity: Boolean = java.lang.Double.isInfinite(self) + def isPosInfinity: Boolean = isInfinity && self > 0.0 + def isNegInfinity: Boolean = isInfinity && self < 0.0 } diff --git a/src/library/scala/runtime/RichFloat.scala b/src/library/scala/runtime/RichFloat.scala index e8e351bdaa..8a4ab13c19 100644 --- a/src/library/scala/runtime/RichFloat.scala +++ b/src/library/scala/runtime/RichFloat.scala @@ -6,27 +6,14 @@ ** |/ ** \* */ - - package scala.runtime +final class RichFloat(val self: Float) extends FractionalProxy[Float] { + protected val integralNum = Numeric.FloatAsIfIntegral -final class RichFloat(x: Float) extends Proxy with Ordered[Float] { - - // Proxy.self - def self: Any = x - - // Ordered[Float].compare - //def compare(y: Float): Int = if (x < y) -1 else if (x > y) 1 else 0 - def compare(y: Float): Int = java.lang.Float.compare(x, y) - - def min(y: Float) = math.min(x, y) - def max(y: Float) = math.max(x, y) - def abs: Float = math.abs(x) - - def round: Int = math.round(x) - def ceil: Float = math.ceil(x).toFloat - def floor: Float = math.floor(x).toFloat + def round: Int = math.round(self) + def ceil: Float = math.ceil(self).toFloat + def floor: Float = math.floor(self).toFloat /** Converts an angle measured in degrees to an approximately equivalent * angle measured in radians. @@ -34,7 +21,7 @@ final class RichFloat(x: Float) extends Proxy with Ordered[Float] { * @param x an angle, in degrees * @return the measurement of the angle <code>x</code> in radians. */ - def toRadians: Float = math.toRadians(x).toFloat + def toRadians: Float = math.toRadians(self).toFloat /** Converts an angle measured in radians to an approximately equivalent * angle measured in degrees. @@ -42,12 +29,11 @@ final class RichFloat(x: Float) extends Proxy with Ordered[Float] { * @param x angle, in radians * @return the measurement of the angle <code>x</code> in degrees. */ - def toDegrees: Float = math.toDegrees(x).toFloat + def toDegrees: Float = math.toDegrees(self).toFloat // isNaN is provided by the implicit conversion to java.lang.Float - // def isNaN: Boolean = java.lang.Float.isNaN(x) - def isInfinity: Boolean = java.lang.Float.isInfinite(x) - def isPosInfinity: Boolean = isInfinity && x > 0.0f - def isNegInfinity: Boolean = isInfinity && x < 0.0f - + // def isNaN: Boolean = java.lang.Float.isNaN(self) + def isInfinity: Boolean = java.lang.Float.isInfinite(self) + def isPosInfinity: Boolean = isInfinity && self > 0.0f + def isNegInfinity: Boolean = isInfinity && self < 0.0f } diff --git a/src/library/scala/runtime/RichInt.scala b/src/library/scala/runtime/RichInt.scala index c5ed5df07c..8ba5685922 100644 --- a/src/library/scala/runtime/RichInt.scala +++ b/src/library/scala/runtime/RichInt.scala @@ -7,32 +7,28 @@ \* */ - package scala.runtime -import collection.immutable.Range - - -final class RichInt(val start: Int) extends Proxy with Ordered[Int] { - - // Proxy - def self: Any = start +import scala.collection.immutable.Range - // Ordered[Int] - def compare(that: Int): Int = if (start < that) -1 else if (start > that) 1 else 0 +// Note that this does not implement IntegralProxy[Int] so that it can return +// the Int-specific Range class from until/to. +final class RichInt(val self: Int) extends ScalaNumberProxy[Int] with RangedProxy[Int] { + type ResultWithoutStep = Range + def isWhole() = true - def until(end: Int): Range = Range(start, end) - def until(end: Int, step: Int): Range = Range(start, end, step) + def until(end: Int): Range = Range(self, end) + def until(end: Int, step: Int): Range = Range(self, end, step) - /** like <code>until</code>, but includes the last index */ - def to(end: Int): Range.Inclusive = Range.inclusive(start, end) - def to(end: Int, step: Int): Range.Inclusive = Range.inclusive(start, end, step) + /** like `until`, but includes the last index */ + def to(end: Int): Range.Inclusive = Range.inclusive(self, end) + def to(end: Int, step: Int): Range.Inclusive = Range.inclusive(self, end, step) - def min(that: Int): Int = if (start < that) start else that - def max(that: Int): Int = if (start > that) start else that - def abs: Int = if (start < 0) -start else start + override def min(that: Int): Int = if (self < that) self else that + override def max(that: Int): Int = if (self > that) self else that + override def abs: Int = if (self < 0) -self else self - def toBinaryString: String = java.lang.Integer.toBinaryString(start) - def toHexString: String = java.lang.Integer.toHexString(start) - def toOctalString: String = java.lang.Integer.toOctalString(start) + def toBinaryString: String = java.lang.Integer.toBinaryString(self) + def toHexString: String = java.lang.Integer.toHexString(self) + def toOctalString: String = java.lang.Integer.toOctalString(self) } diff --git a/src/library/scala/runtime/RichLong.scala b/src/library/scala/runtime/RichLong.scala index 82e2c77ef7..807929aa6d 100644 --- a/src/library/scala/runtime/RichLong.scala +++ b/src/library/scala/runtime/RichLong.scala @@ -6,40 +6,10 @@ ** |/ ** \* */ - - package scala.runtime -import scala.collection.immutable.{Range, NumericRange} - -final class RichLong(x: Long) extends Proxy with Ordered[Long] { - - // Proxy.self - def self: Any = x - - // Ordered[Long].compare - def compare(y: Long): Int = if (x < y) -1 else if (x > y) 1 else 0 - - /** Create a NumericRange[Long] in range <code>[start;end)</code> - * with the specified step, where start is the target Long. - * - * @param end the end value of the range (exclusive) - * @param step the distance between elements (defaults to 1) - * @return the range - */ - def until(end: Long, step: Long = 1L): NumericRange.Exclusive[Long] = Range.Long(x, end, step) - - def until(end: Long): NumericRange.Exclusive[Long] = Range.Long(x, end, 1l) - - /** Like until, but inclusive of the end value. - */ - def to(end: Long, step: Long = 1L): NumericRange.Inclusive[Long] = Range.Long.inclusive(x, end, step) - - def min(y: Long): Long = if (x < y) x else y - def max(y: Long): Long = if (x > y) x else y - def abs: Long = if (x < 0) -x else x - - def toBinaryString: String = java.lang.Long.toBinaryString(x) - def toHexString: String = java.lang.Long.toHexString(x) - def toOctalString: String = java.lang.Long.toOctalString(x) +final class RichLong(val self: Long) extends IntegralProxy[Long] { + def toBinaryString: String = java.lang.Long.toBinaryString(self) + def toHexString: String = java.lang.Long.toHexString(self) + def toOctalString: String = java.lang.Long.toOctalString(self) } diff --git a/src/library/scala/runtime/RichShort.scala b/src/library/scala/runtime/RichShort.scala index 0fa34b27c4..51214ac13e 100644 --- a/src/library/scala/runtime/RichShort.scala +++ b/src/library/scala/runtime/RichShort.scala @@ -6,17 +6,6 @@ ** |/ ** \* */ - - package scala.runtime - -final class RichShort(start: Short) extends Proxy with Ordered[Short] { - - // Proxy.self - def self: Any = start - - // Ordered[Short].compare - def compare(that: Short): Int = if (start < that) -1 else if (start > that) 1 else 0 - -} +final class RichShort(val self: Short) extends ScalaWholeNumberProxy[Short] { } diff --git a/src/library/scala/runtime/ScalaNumberProxy.scala b/src/library/scala/runtime/ScalaNumberProxy.scala new file mode 100644 index 0000000000..42d65ba388 --- /dev/null +++ b/src/library/scala/runtime/ScalaNumberProxy.scala @@ -0,0 +1,80 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2010, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +package scala.runtime + +import scala.collection.{ mutable, immutable } +import math.ScalaNumericConversions +import immutable.NumericRange +import Proxy.Typed + +/** Base classes for the Rich* wrappers of the primitive types. + * As with all classes in scala.runtime.*, this is not a supported API. + * + * @author Paul Phillips + * @version 2.9 + * @since 2.9 + */ +abstract class ScalaNumberProxy[T: Numeric] extends ScalaNumericConversions with Typed[T] with OrderedProxy[T] { + private val num = implicitly[Numeric[T]] + protected val ord: Ordering[T] = num + + def underlying() = self.asInstanceOf[AnyRef] + def doubleValue() = num.toDouble(self) + def floatValue() = num.toFloat(self) + def longValue() = num.toLong(self) + def intValue() = num.toInt(self) + + def min(that: T): T = num.min(self, that) + def max(that: T): T = num.max(self, that) + def abs = num.abs(self) + def signum = num.signum(self) +} +abstract class ScalaWholeNumberProxy[T: Numeric] extends ScalaNumberProxy[T] { + def isWhole() = true +} +abstract class IntegralProxy[T : Integral] extends ScalaWholeNumberProxy[T] with RangedProxy[T] { + private lazy val num = implicitly[Integral[T]] + type ResultWithoutStep = NumericRange[T] + + def until(end: T): NumericRange.Exclusive[T] = NumericRange(self, end, num.one) + def until(end: T, step: T): NumericRange.Exclusive[T] = NumericRange(self, end, step) + def to(end: T): NumericRange.Inclusive[T] = NumericRange.inclusive(self, end, num.one) + def to(end: T, step: T): NumericRange.Inclusive[T] = NumericRange.inclusive(self, end, step) +} +abstract class FractionalProxy[T : Fractional] extends ScalaNumberProxy[T] with RangedProxy[T] { + def isWhole() = false + + /** In order to supply predictable ranges, we require an Integral[T] which provides + * us with discrete operations on the (otherwise fractional) T. See Numeric.DoubleAsIfIntegral + * for an example. + */ + protected implicit def integralNum: Integral[T] + private lazy val num = implicitly[Fractional[T]] + type ResultWithoutStep = Range.Partial[T, NumericRange[T]] + + def until(end: T): ResultWithoutStep = new Range.Partial(NumericRange(self, end, _)) + def until(end: T, step: T): NumericRange.Exclusive[T] = NumericRange(self, end, step) + def to(end: T): ResultWithoutStep = new Range.Partial(NumericRange.inclusive(self, end, _)) + def to(end: T, step: T): NumericRange.Inclusive[T] = NumericRange.inclusive(self, end, step) +} + +trait OrderedProxy[T] extends Typed[T] with Ordered[T] { + protected def ord: Ordering[T] + + def compare(y: T) = ord.compare(self, y) +} +trait RangedProxy[T] extends Typed[T] { + type ResultWithoutStep + + def until(end: T): ResultWithoutStep + def until(end: T, step: T): immutable.IndexedSeq[T] + def to(end: T): ResultWithoutStep + def to(end: T, step: T): immutable.IndexedSeq[T] +} + diff --git a/test/files/run/richWrapperEquals.scala b/test/files/run/richWrapperEquals.scala new file mode 100644 index 0000000000..44beb133b3 --- /dev/null +++ b/test/files/run/richWrapperEquals.scala @@ -0,0 +1,10 @@ +object Test { + def main(args: Array[String]): Unit = { + assert(intWrapper(5) == 5) + assert(5 == intWrapper(5)) + assert(5 == (5: java.lang.Integer)) + assert((5: java.lang.Integer) == 5) + assert((5: java.lang.Integer) == intWrapper(5)) + assert(intWrapper(5) == (5: java.lang.Integer)) + } +} |