Addresses the issues swirling around Double.Epsilon and friends
which were battled out in more than one venue and then aptly summarized by retronym in #3791. Thanks to Simon Ochsenreither for submitting a patch; I wasn't able to use too much of it because the source code for these types is generated, but effort is always appreciated. Closes #3791, and I'm tired and I'd hate to blow this one at this late date: review by rytz. git-svn-id: http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk@24461 5e8d7ff9-d8ef-0310-90f0-a4852d11357a
This commit is contained in:
parent
63fa1b5291
commit
b25198b965
|
@ -6,10 +6,9 @@
|
|||
package scala.tools.cmd
|
||||
package gen
|
||||
|
||||
trait AnyValTemplates {
|
||||
def timestampString = "// generated on " + new java.util.Date + "\n"
|
||||
|
||||
def template = """
|
||||
trait AnyValTemplates {
|
||||
def timestampString = ""
|
||||
def template = ("""
|
||||
/* __ *\
|
||||
** ________ ___ / / ___ Scala API **
|
||||
** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL **
|
||||
|
@ -22,10 +21,10 @@ trait AnyValTemplates {
|
|||
package scala
|
||||
|
||||
import java.{ lang => jl }
|
||||
|
||||
""".trim.format(timestampString) + "\n\n"
|
||||
)
|
||||
|
||||
val booleanBody = """
|
||||
def booleanBody = """
|
||||
final class Boolean extends AnyVal {
|
||||
def unary_! : Boolean = sys.error("stub")
|
||||
|
||||
|
@ -48,7 +47,7 @@ object Boolean extends AnyValCompanion {
|
|||
}
|
||||
""".trim
|
||||
|
||||
val unitBody = """
|
||||
def unitBody = """
|
||||
import runtime.BoxedUnit
|
||||
|
||||
final class Unit extends AnyVal { }
|
||||
|
@ -59,6 +58,40 @@ object Unit extends AnyValCompanion {
|
|||
def unbox(x: jl.Object): Unit = ()
|
||||
}
|
||||
""".trim
|
||||
|
||||
def cardinalCompanion = """
|
||||
final val MinValue = @type@.MIN_VALUE
|
||||
final val MaxValue = @type@.MAX_VALUE
|
||||
|
||||
def box(x: @name@): @type@ = @type@.valueOf(x)
|
||||
def unbox(x: jl.Object): @name@ = x.asInstanceOf[@type@].@lcname@Value()
|
||||
override def toString = "object scala.@name@"
|
||||
""".trim.lines
|
||||
|
||||
def floatingCompanion = """
|
||||
/** The smallest positive value greater than @zero@.*/
|
||||
final val MinPositiveValue = @type@.MIN_VALUE
|
||||
final val NaN = @type@.NaN
|
||||
final val PositiveInfinity = @type@.POSITIVE_INFINITY
|
||||
final val NegativeInfinity = @type@.NEGATIVE_INFINITY
|
||||
|
||||
@deprecated("use @name@.MinPositiveValue instead")
|
||||
final val Epsilon = MinPositiveValue
|
||||
|
||||
/** The negative number with the greatest (finite) absolute value which is representable
|
||||
* by a @name@. Note that it differs from [[java.lang.@name@.MIN_VALUE]], which
|
||||
* is the smallest positive value representable by a @name@. In Scala that number
|
||||
* is called @name@.MinPositiveValue.
|
||||
*/
|
||||
final val MinValue = -@type@.MAX_VALUE
|
||||
|
||||
/** The largest finite positive number representable as a @name@. */
|
||||
final val MaxValue = @type@.MAX_VALUE
|
||||
|
||||
def box(x: @name@): @type@ = @type@.valueOf(x)
|
||||
def unbox(x: jl.Object): @name@ = x.asInstanceOf[@type@].@lcname@Value()
|
||||
override def toString = "object scala.@name@"
|
||||
""".trim.lines
|
||||
}
|
||||
|
||||
class AnyVals extends AnyValTemplates {
|
||||
|
@ -90,11 +123,18 @@ class AnyVals extends AnyValTemplates {
|
|||
val isCardinal = cardinal contains name
|
||||
val restype = if ("LFD" contains name.head) name else I
|
||||
val tpe = javaType(name)
|
||||
val zero = name.head match {
|
||||
case 'L' => "0L"
|
||||
case 'F' => "0.0f"
|
||||
case 'D' => "0.0d"
|
||||
case _ => "0"
|
||||
}
|
||||
val interpolations = Map(
|
||||
"@restype@" -> restype,
|
||||
"@name@" -> name,
|
||||
"@type@" -> tpe,
|
||||
"@lcname@" -> name.toLowerCase
|
||||
"@lcname@" -> name.toLowerCase,
|
||||
"@zero@" -> zero
|
||||
)
|
||||
|
||||
def mkCoercions = numeric map (x => "def to%s: %s".format(x, x))
|
||||
|
@ -131,7 +171,7 @@ class AnyVals extends AnyValTemplates {
|
|||
}
|
||||
assemble("final class", "AnyVal", lines)
|
||||
}
|
||||
def mkObject = assemble("object", "AnyValCompanion", companionLines map interpolate)
|
||||
def mkObject = assemble("object", "AnyValCompanion", companionBody map interpolate toList)
|
||||
|
||||
def assemble(what: String, parent: String, lines: List[String]): String = (
|
||||
List(what, name, "extends", parent, "{").mkString(" ") +:
|
||||
|
@ -170,37 +210,11 @@ class AnyVals extends AnyValTemplates {
|
|||
def shiftops = if (isCardinal) List("<<", ">>>", ">>") else Nil
|
||||
def boolBinops = List("==", "!=", "<", "<=", ">", ">=")
|
||||
def otherBinops = List("+", "-" ,"*", "/", "%")
|
||||
|
||||
def floatingCompanion = List(
|
||||
"final val MinPositiveValue = @type@.MIN_VALUE",
|
||||
"final val MinNegativeValue = -@type@.MAX_VALUE",
|
||||
"final val NaN = @type@.NaN",
|
||||
"final val PositiveInfinity = @type@.POSITIVE_INFINITY",
|
||||
"final val NegativeInfinity = @type@.NEGATIVE_INFINITY",
|
||||
"",
|
||||
"""@deprecated("use @name@.MinPositiveValue instead")""",
|
||||
"final val Epsilon = MinPositiveValue",
|
||||
"""@deprecated("use @name@.MinNegativeValue instead")""",
|
||||
"final val MinValue = MinNegativeValue"
|
||||
)
|
||||
|
||||
def cardinalCompanion = List(
|
||||
"final val MinValue = @type@.MIN_VALUE"
|
||||
)
|
||||
|
||||
def commonCompanion = List(
|
||||
"final val MaxValue = @type@.MAX_VALUE",
|
||||
"",
|
||||
"def box(x: @name@): @type@ = @type@.valueOf(x)",
|
||||
"def unbox(x: jl.Object): @name@ = x.asInstanceOf[@type@].@lcname@Value()",
|
||||
"override def toString = \"object scala.@name@\""
|
||||
)
|
||||
|
||||
def companionLines = (
|
||||
def companionBody =
|
||||
if (isCardinal) cardinalCompanion
|
||||
else floatingCompanion
|
||||
) ++ commonCompanion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object AnyVals extends AnyVals { }
|
|
@ -27,19 +27,19 @@ object Codegen {
|
|||
|
||||
if (anyvals || all) {
|
||||
val av = new AnyVals {
|
||||
override def timestampString =
|
||||
if (stamp) super.timestampString
|
||||
else ""
|
||||
override def timestampString = (
|
||||
"// DO NOT EDIT, CHANGES WILL BE LOST.\n" + (
|
||||
if (stamp) "// Generated by tools/codegen on " + new java.util.Date + "\n" else ""
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
av.make() foreach { case (name, code ) =>
|
||||
val file = out / (name + ".scala") toFile;
|
||||
echo("Writing: " + file)
|
||||
file writeAll code
|
||||
}
|
||||
}
|
||||
if (products || all) {
|
||||
()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,15 +10,15 @@ import FromString.ExistingDir
|
|||
|
||||
trait CodegenSpec extends Spec with Meta.StdOpts with Interpolation {
|
||||
def referenceSpec = CodegenSpec
|
||||
def programInfo = Spec.Info("codegen", "", "scala.tools.cmd.cmd")
|
||||
def programInfo = Spec.Info("codegen", "", "scala.tools.cmd.gen.Codegen")
|
||||
|
||||
import FromString.ExistingDir
|
||||
|
||||
help("Usage: codegen [<options>]")
|
||||
|
||||
val inDir = "in" / "directory containing templates" --^ ExistingDir
|
||||
// val inDir = "in" / "directory containing templates" --^ ExistingDir
|
||||
val outDir = "out" / "directory for generated files" --^ ExistingDir
|
||||
val install = "install" / "write source files directly to src/library/scala"
|
||||
// val install = "install" / "write source files directly to src/library/scala"
|
||||
val anyvals = "anyvals" / "generate sources for AnyVal types" --?
|
||||
val products = "products" / "generate sources for ProductN, FunctionN, etc." --?
|
||||
val genall = "all" / "generate sources for everything" --?
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
** |/ **
|
||||
\* */
|
||||
|
||||
// generated on Sun Jan 23 21:13:38 PST 2011
|
||||
// DO NOT EDIT, CHANGES WILL BE LOST.
|
||||
|
||||
package scala
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
** |/ **
|
||||
\* */
|
||||
|
||||
// generated on Sun Jan 23 21:13:38 PST 2011
|
||||
// DO NOT EDIT, CHANGES WILL BE LOST.
|
||||
|
||||
package scala
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
** |/ **
|
||||
\* */
|
||||
|
||||
// generated on Sun Jan 23 21:13:38 PST 2011
|
||||
// DO NOT EDIT, CHANGES WILL BE LOST.
|
||||
|
||||
package scala
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
** |/ **
|
||||
\* */
|
||||
|
||||
// generated on Sun Jan 23 21:13:38 PST 2011
|
||||
// DO NOT EDIT, CHANGES WILL BE LOST.
|
||||
|
||||
package scala
|
||||
|
||||
|
@ -119,16 +119,23 @@ final class Double extends AnyVal {
|
|||
|
||||
|
||||
object Double extends AnyValCompanion {
|
||||
/** The smallest positive value greater than 0.0d.*/
|
||||
final val MinPositiveValue = jl.Double.MIN_VALUE
|
||||
final val MinNegativeValue = -jl.Double.MAX_VALUE
|
||||
final val NaN = jl.Double.NaN
|
||||
final val PositiveInfinity = jl.Double.POSITIVE_INFINITY
|
||||
final val NegativeInfinity = jl.Double.NEGATIVE_INFINITY
|
||||
|
||||
@deprecated("use Double.MinPositiveValue instead")
|
||||
final val Epsilon = MinPositiveValue
|
||||
@deprecated("use Double.MinNegativeValue instead")
|
||||
final val MinValue = MinNegativeValue
|
||||
final val Epsilon = MinPositiveValue
|
||||
|
||||
/** The negative number with the greatest (finite) absolute value which is representable
|
||||
* by a Double. Note that it differs from [[java.lang.Double.MIN_VALUE]], which
|
||||
* is the smallest positive value representable by a Double. In Scala that number
|
||||
* is called Double.MinPositiveValue.
|
||||
*/
|
||||
final val MinValue = -jl.Double.MAX_VALUE
|
||||
|
||||
/** The largest finite positive number representable as a Double. */
|
||||
final val MaxValue = jl.Double.MAX_VALUE
|
||||
|
||||
def box(x: Double): jl.Double = jl.Double.valueOf(x)
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
** |/ **
|
||||
\* */
|
||||
|
||||
// generated on Sun Jan 23 21:13:38 PST 2011
|
||||
// DO NOT EDIT, CHANGES WILL BE LOST.
|
||||
|
||||
package scala
|
||||
|
||||
|
@ -119,16 +119,23 @@ final class Float extends AnyVal {
|
|||
|
||||
|
||||
object Float extends AnyValCompanion {
|
||||
/** The smallest positive value greater than 0.0f.*/
|
||||
final val MinPositiveValue = jl.Float.MIN_VALUE
|
||||
final val MinNegativeValue = -jl.Float.MAX_VALUE
|
||||
final val NaN = jl.Float.NaN
|
||||
final val PositiveInfinity = jl.Float.POSITIVE_INFINITY
|
||||
final val NegativeInfinity = jl.Float.NEGATIVE_INFINITY
|
||||
|
||||
@deprecated("use Float.MinPositiveValue instead")
|
||||
final val Epsilon = MinPositiveValue
|
||||
@deprecated("use Float.MinNegativeValue instead")
|
||||
final val MinValue = MinNegativeValue
|
||||
final val Epsilon = MinPositiveValue
|
||||
|
||||
/** The negative number with the greatest (finite) absolute value which is representable
|
||||
* by a Float. Note that it differs from [[java.lang.Float.MIN_VALUE]], which
|
||||
* is the smallest positive value representable by a Float. In Scala that number
|
||||
* is called Float.MinPositiveValue.
|
||||
*/
|
||||
final val MinValue = -jl.Float.MAX_VALUE
|
||||
|
||||
/** The largest finite positive number representable as a Float. */
|
||||
final val MaxValue = jl.Float.MAX_VALUE
|
||||
|
||||
def box(x: Float): jl.Float = jl.Float.valueOf(x)
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
** |/ **
|
||||
\* */
|
||||
|
||||
// generated on Sun Jan 23 21:13:38 PST 2011
|
||||
// DO NOT EDIT, CHANGES WILL BE LOST.
|
||||
|
||||
package scala
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
** |/ **
|
||||
\* */
|
||||
|
||||
// generated on Sun Jan 23 21:13:38 PST 2011
|
||||
// DO NOT EDIT, CHANGES WILL BE LOST.
|
||||
|
||||
package scala
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ package scala
|
|||
* operations such as the elementary exponential, logarithm, square root, and
|
||||
* trigonometric functions.
|
||||
*/
|
||||
@deprecated("use scala.math package object instead.\n(Example package object usage: scala.math.Pi )")
|
||||
@deprecated("use the scala.math package object instead.\n(Example package object usage: scala.math.Pi )")
|
||||
object Math extends MathCommon {
|
||||
@deprecated("Use scala.Byte.MinValue instead")
|
||||
val MIN_BYTE = java.lang.Byte.MIN_VALUE
|
||||
|
@ -50,7 +50,7 @@ object Math extends MathCommon {
|
|||
val MIN_FLOAT = -java.lang.Float.MAX_VALUE
|
||||
|
||||
/** The smallest difference between two values of <a href="Float.html" target="_self">scala.Float</a>. */
|
||||
@deprecated("Use scala.Float.Epsilon instead")
|
||||
@deprecated("Use scala.Float.MinPositiveValue instead")
|
||||
val EPS_FLOAT = java.lang.Float.MIN_VALUE
|
||||
|
||||
/** The greatest possible value for <a href="Float.html" target="_self">scala.Float</a>. */
|
||||
|
@ -74,7 +74,7 @@ object Math extends MathCommon {
|
|||
val MIN_DOUBLE = -java.lang.Double.MAX_VALUE
|
||||
|
||||
/** The smallest difference between two values of <a href="Double.html" target="_self">scala.Double</a>. */
|
||||
@deprecated("Use scala.Double.Epsilon instead")
|
||||
@deprecated("Use scala.Double.MinPositiveValue instead")
|
||||
val EPS_DOUBLE = java.lang.Double.MIN_VALUE
|
||||
|
||||
/** The greatest possible value for <a href="Double.html" target="_self">scala.Double</a>. */
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
** |/ **
|
||||
\* */
|
||||
|
||||
// generated on Sun Jan 23 21:13:38 PST 2011
|
||||
// DO NOT EDIT, CHANGES WILL BE LOST.
|
||||
|
||||
package scala
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
** |/ **
|
||||
\* */
|
||||
|
||||
// generated on Sun Jan 23 21:13:38 PST 2011
|
||||
// DO NOT EDIT, CHANGES WILL BE LOST.
|
||||
|
||||
package scala
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@ object Arbitrary {
|
|||
/** Arbitrary instance of Float */
|
||||
implicit lazy val arbFloat: Arbitrary[Float] = Arbitrary(
|
||||
Gen.chooseNum(
|
||||
Float.MinNegativeValue, Float.MaxValue
|
||||
Float.MinValue, Float.MaxValue
|
||||
// I find that including these by default is a little TOO testy.
|
||||
// Float.Epsilon, Float.NaN, Float.PositiveInfinity, Float.NegativeInfinity
|
||||
)
|
||||
|
@ -107,7 +107,7 @@ object Arbitrary {
|
|||
/** Arbitrary instance of Double */
|
||||
implicit lazy val arbDouble: Arbitrary[Double] = Arbitrary(
|
||||
Gen.chooseNum(
|
||||
Double.MinNegativeValue / 2, Double.MaxValue / 2
|
||||
Double.MinValue / 2, Double.MaxValue / 2
|
||||
// As above. Perhaps behind some option?
|
||||
// Double.Epsilon, Double.NaN, Double.PositiveInfinity, Double.NegativeInfinity
|
||||
)
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
t3115.scala:6: error: object Math in object sc is deprecated:
|
||||
println(sc.Math)
|
||||
^
|
||||
t3115.scala:7: error: object Math in package scala is deprecated: use scala.math package object instead.
|
||||
t3115.scala:7: error: object Math in package scala is deprecated: use the scala.math package object instead.
|
||||
(Example package object usage: scala.math.Pi )
|
||||
println(scala.Math)
|
||||
^
|
||||
t3115.scala:8: error: object Math in package scala is deprecated: use scala.math package object instead.
|
||||
t3115.scala:8: error: object Math in package scala is deprecated: use the scala.math package object instead.
|
||||
(Example package object usage: scala.math.Pi )
|
||||
scala.Math.Pi
|
||||
^
|
||||
|
|
|
@ -3,5 +3,6 @@
|
|||
|
||||
THISDIR=`dirname $0`
|
||||
SCALALIB=$THISDIR/../src/library/scala
|
||||
BINDIR=$THISDIR/../build/pack/bin
|
||||
|
||||
scala scala.tools.cmd.gen.Codegen "$@"
|
||||
$BINDIR/scala scala.tools.cmd.gen.Codegen "$@"
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
|
||||
THISDIR=`dirname $0`
|
||||
$THISDIR/codegen --anyvals --out $THISDIR/../src/library/scala
|
Loading…
Reference in New Issue