scala.tools.cmd.gen.AnyVals.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.apache.servicemix.bundles.scala-compiler
Show all versions of org.apache.servicemix.bundles.scala-compiler
This OSGi bundle wraps ${pkgArtifactId} ${pkgVersion} jar file.
/* NSC -- new Scala compiler
* Copyright 2007-2011 LAMP/EPFL
* @author Paul Phillips
*/
package scala.tools.cmd
package gen
/** Code generation of the AnyVal types and their companions.
*/
trait AnyValReps {
self: AnyVals =>
sealed abstract class AnyValNum(name: String) extends AnyValRep(name) {
def isCardinal: Boolean = isIntegerType(this)
def unaryOps = if (isCardinal) List("+", "-", "~") else List("+", "-")
def bitwiseOps = if (isCardinal) List("|", "&", "^") else Nil
def shiftOps = if (isCardinal) List("<<", ">>>", ">>") else Nil
def comparisonOps = List("==", "!=", "<", "<=", ">", ">=")
def otherOps = List("+", "-" ,"*", "/", "%")
// Given two numeric value types S and T , the operation type of S and T is defined as follows:
// If both S and T are subrange types then the operation type of S and T is Int.
// Otherwise the operation type of S and T is the larger of the two types wrt ranking.
// Given two numeric values v and w the operation type of v and w is the operation type
// of their run-time types.
def opType(that: AnyValNum): AnyValNum = {
val rank = IndexedSeq(I, L, F, D)
(rank indexOf this, rank indexOf that) match {
case (-1, -1) => I
case (r1, r2) => rank apply (r1 max r2)
}
}
def mkCoercions = numeric map (x => "def to%s: %s".format(x, x))
def mkUnaryOps = unaryOps map (x => "def unary_%s : %s".format(x, this opType I))
def mkStringOps = List("def +(x: String): String")
def mkShiftOps = (
for (op <- shiftOps ; arg <- List(I, L)) yield
"def %s(x: %s): %s".format(op, arg, this opType I)
)
def clumps: List[List[String]] = {
val xs1 = List(mkCoercions, mkUnaryOps, mkStringOps, mkShiftOps) map (xs => if (xs.isEmpty) xs else xs :+ "")
val xs2 = List(
mkBinOpsGroup(comparisonOps, numeric, _ => Z),
mkBinOpsGroup(bitwiseOps, cardinal, this opType _),
mkBinOpsGroup(otherOps, numeric, this opType _)
)
xs1 ++ xs2
}
def classLines = (clumps :+ commonClassLines).foldLeft(List[String]()) {
case (res, Nil) => res
case (res, lines) =>
val xs = lines map {
case "" => ""
case s => interpolate(s) + " = " + stub
}
res ++ xs
}
def objectLines = {
val comp = if (isCardinal) cardinalCompanion else floatingCompanion
(comp + allCompanions).trim.lines map interpolate toList
}
/** Makes a set of binary operations based on the given set of ops, args, and resultFn.
*
* @param ops list of function names e.g. List(">>", "%")
* @param args list of types which should appear as arguments
* @param resultFn function which calculates return type based on arg type
* @return list of function definitions
*/
def mkBinOpsGroup(ops: List[String], args: List[AnyValNum], resultFn: AnyValNum => AnyValRep): List[String] = (
ops flatMap (op =>
args.map(arg => "def %s(x: %s): %s".format(op, arg, resultFn(arg))) :+ ""
)
).toList
}
sealed abstract class AnyValRep(val name: String) {
def classLines: List[String]
def objectLines: List[String]
def commonClassLines = List(
"def getClass(): Class[@name@]"
)
def lcname = name.toLowerCase
def boxedName = this match {
case U => "scala.runtime.BoxedUnit"
case C => "java.lang.Character"
case I => "java.lang.Integer"
case _ => "java.lang." + name
}
def zeroRep = this match {
case L => "0L"
case F => "0.0f"
case D => "0.0d"
case _ => "0"
}
def indent(s: String) = if (s == "") "" else " " + s
def indentN(s: String) = s.lines map indent mkString "\n"
def boxUnboxImpls = Map(
"@boxImpl@" -> "%s.valueOf(x)".format(boxedName),
"@unboxImpl@" -> "x.asInstanceOf[%s].%sValue()".format(boxedName, lcname),
"@unboxDoc@" -> "the %s resulting from calling %sValue() on `x`".format(name, lcname)
)
def interpolations = Map(
"@name@" -> name,
"@boxed@" -> boxedName,
"@lcname@" -> lcname,
"@zero@" -> zeroRep
) ++ boxUnboxImpls
def interpolate(s: String): String = interpolations.foldLeft(s) {
case (str, (key, value)) => str.replaceAll(key, value)
}
def classDoc = interpolate(classDocTemplate)
def objectDoc = ""
def mkImports = ""
def mkClass = assemble("final class", "AnyVal", classLines) + "\n"
def mkObject = assemble("object", "AnyValCompanion", objectLines) + "\n"
def make() = List[String](
headerTemplate,
mkImports,
classDoc,
mkClass,
objectDoc,
mkObject
) mkString ""
def assemble(what: String, parent: String, lines: List[String]): String = {
val decl = "%s %s extends %s ".format(what, name, parent)
val body = if (lines.isEmpty) "{ }\n\n" else lines map indent mkString ("{\n", "\n", "\n}\n")
decl + body
}
override def toString = name
}
}
trait AnyValTemplates {
def headerTemplate = ("""
/* __ *\
** ________ ___ / / ___ Scala API **
** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
\* */
%s
package scala
""".trim.format(timestampString) + "\n\n")
def classDocTemplate = ("""
/** `@name@` is a member of the value classes, those whose instances are
* not represented as objects by the underlying host system.
*
* There is an implicit conversion from [[scala.@name@]] => [[scala.runtime.Rich@name@]]
* which provides useful non-primitive operations.
*/
""".trim + "\n")
def timestampString = "// DO NOT EDIT, CHANGES WILL BE LOST.\n"
def stub = """sys.error("stub")"""
def allCompanions = """
/** Transform a value type into a boxed reference type.
*
* @param x the @name@ to be boxed
* @return a @boxed@ offering `x` as its underlying value.
*/
def box(x: @name@): @boxed@ = @boxImpl@
/** Transform a boxed type into a value type. Note that this
* method is not typesafe: it accepts any Object, but will throw
* an exception if the argument is not a @boxed@.
*
* @param x the @boxed@ to be unboxed.
* @throws ClassCastException if the argument is not a @boxed@
* @return @unboxDoc@
*/
def unbox(x: java.lang.Object): @name@ = @unboxImpl@
/** The String representation of the scala.@name@ companion object.
*/
override def toString = "object scala.@name@"
"""
def cardinalCompanion = """
/** The smallest value representable as a @name@.
*/
final val MinValue = @[email protected]_VALUE
/** The largest value representable as a @name@.
*/
final val MaxValue = @[email protected]_VALUE
"""
def floatingCompanion = """
/** The smallest positive value greater than @zero@ which is
* representable as a @name@.
*/
final val MinPositiveValue = @[email protected]_VALUE
final val NaN = @[email protected]
final val PositiveInfinity = @[email protected]_INFINITY
final val NegativeInfinity = @[email protected]_INFINITY
@deprecated("use @[email protected] instead", "2.9.0")
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.@[email protected]_VALUE]], which
* is the smallest positive value representable by a @name@. In Scala that number
* is called @[email protected].
*/
final val MinValue = -@[email protected]_VALUE
/** The largest finite positive number representable as a @name@. */
final val MaxValue = @[email protected]_VALUE
"""
}
class AnyVals extends AnyValReps with AnyValTemplates {
object B extends AnyValNum("Byte")
object S extends AnyValNum("Short")
object C extends AnyValNum("Char")
object I extends AnyValNum("Int")
object L extends AnyValNum("Long")
object F extends AnyValNum("Float")
object D extends AnyValNum("Double")
object Z extends AnyValRep("Boolean") {
def classLines = """
def unary_! : Boolean = sys.error("stub")
def ==(x: Boolean): Boolean = sys.error("stub")
def !=(x: Boolean): Boolean = sys.error("stub")
def ||(x: Boolean): Boolean = sys.error("stub")
def &&(x: Boolean): Boolean = sys.error("stub")
// Compiler won't build with these seemingly more accurate signatures
// def ||(x: => Boolean): Boolean = sys.error("stub")
// def &&(x: => Boolean): Boolean = sys.error("stub")
def |(x: Boolean): Boolean = sys.error("stub")
def &(x: Boolean): Boolean = sys.error("stub")
def ^(x: Boolean): Boolean = sys.error("stub")
def getClass(): Class[Boolean] = sys.error("stub")
""".trim.lines.toList
def objectLines = interpolate(allCompanions).lines.toList
}
object U extends AnyValRep("Unit") {
override def classDoc = """
/** Unit is a member of the value classes, those whose instances are
* not represented as objects by the underlying host system. There is
* only one value of type Unit: `()`.
*/
"""
def classLines = List(
"""def getClass(): Class[Unit] = sys.error("stub")"""
)
def objectLines = interpolate(allCompanions).lines.toList
override def boxUnboxImpls = Map(
"@boxImpl@" -> "scala.runtime.BoxedUnit.UNIT",
"@unboxImpl@" -> "()",
"@unboxDoc@" -> "the Unit value ()"
)
}
def isSubrangeType = Set(B, S, C)
def isIntegerType = Set(B, S, C, I, L)
def isFloatingType = Set(F, D)
def isWideType = Set(L, D)
def cardinal = numeric filter isIntegerType
def numeric = List(B, S, C, I, L, F, D)
def values = List(U, Z) ++ numeric
def make() = values map (x => (x.name, x.make()))
}
object AnyVals extends AnyVals { }
© 2015 - 2025 Weber Informatics LLC | Privacy Policy