Write docs for primitive types conversions

This commit is contained in:
Abduqodiri Qurbonzoda
2019-03-05 20:36:17 +03:00
parent 76d4a2fd17
commit a0e2ca669b
3 changed files with 389 additions and 11 deletions
+238
View File
@@ -186,12 +186,52 @@ public class Byte private constructor() : Number(), Comparable<Byte> {
/** Creates a range from this value to the specified [other] value. */
public operator fun rangeTo(other: Long): LongRange
/** Returns this value. */
public override fun toByte(): Byte
/**
* Converts this [Byte] value to [Char].
*
* Returns the `Char` with the numeric value equal to this value sign-extended to 16 bits.
*/
public override fun toChar(): Char
/**
* Converts this [Byte] value to [Short].
*
* The resulting `Short` value represents the same numerical value as this `Byte`.
*
* The least significant 8 bits of the resulting `Short` value are the same as the binary representation of this `Byte` value,
* whereas the most significant 8 bits are filled with the bit sign of this value.
*/
public override fun toShort(): Short
/**
* Converts this [Byte] value to [Int].
*
* The resulting `Int` value represents the same numerical value as this `Byte`.
*
* The least significant 8 bits of the resulting `Int` value are the same as the binary representation of this `Byte` value,
* whereas the most significant 24 bits are filled with the bit sign of this value.
*/
public override fun toInt(): Int
/**
* Converts this [Byte] value to [Long].
*
* The resulting `Long` value represents the same numerical value as this `Byte`.
*
* The least significant 8 bits of the resulting `Long` value are the same as the binary representation of this `Byte` value,
* whereas the most significant 56 bits are filled with the bit sign of this value.
*/
public override fun toLong(): Long
/**
* Converts this [Byte] value to [Float].
*
* The resulting `Float` value represents the same numerical value as this `Byte`.
*/
public override fun toFloat(): Float
/**
* Converts this [Byte] value to [Double].
*
* The resulting `Double` value represents the same numerical value as this `Byte`.
*/
public override fun toDouble(): Double
}
@@ -374,12 +414,52 @@ public class Short private constructor() : Number(), Comparable<Short> {
/** Creates a range from this value to the specified [other] value. */
public operator fun rangeTo(other: Long): LongRange
/**
* Converts this [Short] value to [Byte].
*
* If this value is in [Byte.MIN_VALUE]..[Byte.MAX_VALUE], the resulting `Byte` value represents
* the same numerical value as this `Short`.
*
* The resulting `Byte` value is represented by the least significant 8 bits of this `Short` value.
*/
public override fun toByte(): Byte
/**
* Converts this [Short] value to [Char].
*
* Returns the `Char` with the numeric value equal to this value.
*/
public override fun toChar(): Char
/** Returns this value. */
public override fun toShort(): Short
/**
* Converts this [Short] value to [Int].
*
* The resulting `Int` value represents the same numerical value as this `Short`.
*
* The least significant 16 bits of the resulting `Int` value are the same as the binary representation of this `Short` value,
* whereas the most significant 16 bits are filled with the bit sign of this value.
*/
public override fun toInt(): Int
/**
* Converts this [Short] value to [Long].
*
* The resulting `Long` value represents the same numerical value as this `Short`.
*
* The least significant 16 bits of the resulting `Long` value are the same as the binary representation of this `Short` value,
* whereas the most significant 48 bits are filled with the bit sign of this value.
*/
public override fun toLong(): Long
/**
* Converts this [Short] value to [Float].
*
* The resulting `Float` value represents the same numerical value as this `Short`.
*/
public override fun toFloat(): Float
/**
* Converts this [Short] value to [Double].
*
* The resulting `Double` value represents the same numerical value as this `Short`.
*/
public override fun toDouble(): Double
}
@@ -577,12 +657,54 @@ public class Int private constructor() : Number(), Comparable<Int> {
/** Inverts the bits in this value. */
public fun inv(): Int
/**
* Converts this [Int] value to [Byte].
*
* If this value is in [Byte.MIN_VALUE]..[Byte.MAX_VALUE], the resulting `Byte` value represents
* the same numerical value as this `Int`.
*
* The resulting `Byte` value is represented by the least significant 8 bits of this `Int` value.
*/
public override fun toByte(): Byte
/**
* Converts this [Int] value to [Char].
*
* Returns the `Char` with the numeric value equal to this value truncated to 16 bits.
*/
public override fun toChar(): Char
/**
* Converts this [Int] value to [Short].
*
* If this value is in [Short.MIN_VALUE]..[Short.MAX_VALUE], the resulting `Short` value represents
* the same numerical value as this `Int`.
*
* The resulting `Short` value is represented by the least significant 16 bits of this `Int` value.
*/
public override fun toShort(): Short
/** Returns this value. */
public override fun toInt(): Int
/**
* Converts this [Int] value to [Long].
*
* The resulting `Long` value represents the same numerical value as this `Int`.
*
* The least significant 32 bits of the resulting `Long` value are the same as the binary representation of this `Int` value,
* whereas the most significant 32 bits are filled with the bit sign of this value.
*/
public override fun toLong(): Long
/**
* Converts this [Int] value to [Float].
*
* The resulting value is the closest `Float` to this `Int` value.
* In case when this `Int` value is exactly between two `Float`s,
* the one with zero at least significant bit of mantissa is selected.
*/
public override fun toFloat(): Float
/**
* Converts this [Int] value to [Double].
*
* The resulting `Double` value represents the same numerical value as this `Int`.
*/
public override fun toDouble(): Double
}
@@ -780,12 +902,56 @@ public class Long private constructor() : Number(), Comparable<Long> {
/** Inverts the bits in this value. */
public fun inv(): Long
/**
* Converts this [Long] value to [Byte].
*
* If this value is in [Byte.MIN_VALUE]..[Byte.MAX_VALUE], the resulting `Byte` value represents
* the same numerical value as this `Long`.
*
* The resulting `Byte` value is represented by the least significant 8 bits of this `Long` value.
*/
public override fun toByte(): Byte
/**
* Converts this [Long] value to [Char].
*
* Returns the `Char` with the numeric value equal to this value truncated to 16 bits.
*/
public override fun toChar(): Char
/**
* Converts this [Long] value to [Short].
*
* If this value is in [Short.MIN_VALUE]..[Short.MAX_VALUE], the resulting `Short` value represents
* the same numerical value as this `Long`.
*
* The resulting `Short` value is represented by the least significant 16 bits of this `Long` value.
*/
public override fun toShort(): Short
/**
* Converts this [Long] value to [Int].
*
* If this value is in [Int.MIN_VALUE]..[Int.MAX_VALUE], the resulting `Int` value represents
* the same numerical value as this `Long`.
*
* The resulting `Int` value is represented by the least significant 32 bits of this `Long` value.
*/
public override fun toInt(): Int
/** Returns this value. */
public override fun toLong(): Long
/**
* Converts this [Long] value to [Float].
*
* The resulting value is the closest `Float` to this `Long` value.
* In case when this `Long` value is exactly between two `Float`s,
* the one with zero at least significant bit of mantissa is selected.
*/
public override fun toFloat(): Float
/**
* Converts this [Long] value to [Double].
*
* The resulting value is the closest `Double` to this `Long` value.
* In case when this `Long` value is exactly between two `Double`s,
* the one with zero at least significant bit of mantissa is selected.
*/
public override fun toDouble(): Double
}
@@ -963,12 +1129,47 @@ public class Float private constructor() : Number(), Comparable<Float> {
public operator fun unaryMinus(): Float
/**
* Converts this [Float] value to [Byte].
*
* The resulting `Byte` value is equal to `this.toInt().toByte()`.
*/
public override fun toByte(): Byte
/**
* Converts this [Float] value to [Char].
*
* The resulting `Char` value is equal to `this.toInt().toChar()`.
*/
public override fun toChar(): Char
/**
* Converts this [Float] value to [Short].
*
* The resulting `Short` value is equal to `this.toInt().toShort()`.
*/
public override fun toShort(): Short
/**
* Converts this [Float] value to [Int].
*
* The fractional part, if any, is rounded down.
* Returns zero if this `Float` value is `NaN`, [Int.MIN_VALUE] if it's less than `Int.MIN_VALUE`,
* [Int.MAX_VALUE] if it's bigger than `Int.MAX_VALUE`.
*/
public override fun toInt(): Int
/**
* Converts this [Float] value to [Long].
*
* The fractional part, if any, is rounded down.
* Returns zero if this `Float` value is `NaN`, [Long.MIN_VALUE] if it's less than `Long.MIN_VALUE`,
* [Long.MAX_VALUE] if it's bigger than `Long.MAX_VALUE`.
*/
public override fun toLong(): Long
/** Returns this value. */
public override fun toFloat(): Float
/**
* Converts this [Float] value to [Double].
*
* The resulting `Double` value represents the same numerical value as this `Float`.
*/
public override fun toDouble(): Double
}
@@ -1146,12 +1347,49 @@ public class Double private constructor() : Number(), Comparable<Double> {
public operator fun unaryMinus(): Double
/**
* Converts this [Double] value to [Byte].
*
* The resulting `Byte` value is equal to `this.toInt().toByte()`.
*/
public override fun toByte(): Byte
/**
* Converts this [Double] value to [Char].
*
* The resulting `Char` value is equal to `this.toInt().toChar()`.
*/
public override fun toChar(): Char
/**
* Converts this [Double] value to [Short].
*
* The resulting `Short` value is equal to `this.toInt().toShort()`.
*/
public override fun toShort(): Short
/**
* Converts this [Double] value to [Int].
*
* The fractional part, if any, is rounded down.
* Returns zero if this `Double` value is `NaN`, [Int.MIN_VALUE] if it's less than `Int.MIN_VALUE`,
* [Int.MAX_VALUE] if it's bigger than `Int.MAX_VALUE`.
*/
public override fun toInt(): Int
/**
* Converts this [Double] value to [Long].
*
* The fractional part, if any, is rounded down.
* Returns zero if this `Double` value is `NaN`, [Long.MIN_VALUE] if it's less than `Long.MIN_VALUE`,
* [Long.MAX_VALUE] if it's bigger than `Long.MAX_VALUE`.
*/
public override fun toLong(): Long
/**
* Converts this [Double] value to [Float].
*
* The resulting value is the closest `Float` to this `Double` value.
* In case when this `Double` value is exactly between two `Float`s,
* the one with zero at least significant bit of mantissa is selected.
*/
public override fun toFloat(): Float
/** Returns this value. */
public override fun toDouble(): Double
}
+9 -5
View File
@@ -17,24 +17,28 @@
package org.jetbrains.kotlin.generators.builtins
import org.jetbrains.kotlin.generators.builtins.ProgressionKind.*
import kotlin.properties.Delegates
enum class PrimitiveType(val byteSize: Int?) {
enum class PrimitiveType(val byteSize: Int) {
BYTE(1),
CHAR(2),
SHORT(2),
INT(4),
LONG(8),
FLOAT(null),
DOUBLE(null),
BOOLEAN(null);
FLOAT(4),
DOUBLE(8),
BOOLEAN(1);
val capitalized: String get() = name.toLowerCase().capitalize()
val bitSize = byteSize * 8
val isFloatingPoint: Boolean get() = this in floatingPoint
val isIntegral: Boolean get() = this in integral
companion object {
val exceptBoolean = PrimitiveType.values().filterNot { it == BOOLEAN }
val onlyNumeric = PrimitiveType.values().filterNot { it == BOOLEAN || it == CHAR }
val floatingPoint = listOf(FLOAT, DOUBLE)
val integral = exceptBoolean - floatingPoint
}
}
+142 -6
View File
@@ -101,7 +101,7 @@ class GeneratePrimitives(out: PrintWriter) : BuiltInsSourceGenerator(out) {
*/
public const val MAX_VALUE: $className = $maxValue""")
}
if (kind.byteSize != null) {
if (kind.isIntegral) {
out.println("""
/**
* The number of bytes used to represent an instance of $className in a binary form.
@@ -113,7 +113,7 @@ class GeneratePrimitives(out: PrintWriter) : BuiltInsSourceGenerator(out) {
* The number of bits used to represent an instance of $className in a binary form.
*/
@SinceKotlin("1.3")
public const val SIZE_BITS: Int = ${kind.byteSize * 8}""")
public const val SIZE_BITS: Int = ${kind.bitSize}""")
}
out.println(""" }""")
@@ -130,7 +130,7 @@ class GeneratePrimitives(out: PrintWriter) : BuiltInsSourceGenerator(out) {
generateBitwiseOperators(className, since = if (kind == PrimitiveType.BYTE || kind == PrimitiveType.SHORT) "1.1" else null)
}
generateConversions()
generateConversions(kind)
out.println("}\n")
}
@@ -223,10 +223,146 @@ class GeneratePrimitives(out: PrintWriter) : BuiltInsSourceGenerator(out) {
out.println()
}
private fun generateConversions() {
private fun compareByDomainCapacity(type1: PrimitiveType, type2: PrimitiveType): Int =
if (type1.isIntegral && type2.isIntegral) type1.byteSize - type2.byteSize else type1.ordinal - type2.ordinal
private fun docForConversionFromFloatingToIntegral(fromFloating: PrimitiveType, toIntegral: PrimitiveType): String {
require(fromFloating.isFloatingPoint)
require(toIntegral.isIntegral)
val thisName = fromFloating.capitalized
val otherName = toIntegral.capitalized
return if (compareByDomainCapacity(toIntegral, PrimitiveType.INT) < 0) {
"""
* The resulting `$otherName` value is equal to `this.toInt().to$otherName()`.
*/
"""
} else {
"""
* The fractional part, if any, is rounded down.
* Returns zero if this `$thisName` value is `NaN`, [$otherName.MIN_VALUE] if it's less than `$otherName.MIN_VALUE`,
* [$otherName.MAX_VALUE] if it's bigger than `$otherName.MAX_VALUE`.
*/
"""
}
}
private fun docForConversionFromFloatingToFloating(fromFloating: PrimitiveType, toFloating: PrimitiveType): String {
require(fromFloating.isFloatingPoint)
require(toFloating.isFloatingPoint)
val thisName = fromFloating.capitalized
val otherName = toFloating.capitalized
return if (compareByDomainCapacity(toFloating, fromFloating) < 0) {
"""
* The resulting value is the closest `$otherName` to this `$thisName` value.
* In case when this `$thisName` value is exactly between two `$otherName`s,
* the one with zero at least significant bit of mantissa is selected.
*/
"""
} else {
"""
* The resulting `$otherName` value represents the same numerical value as this `$thisName`.
*/
"""
}
}
private fun docForConversionFromIntegralToIntegral(fromIntegral: PrimitiveType, toIntegral: PrimitiveType): String {
require(fromIntegral.isIntegral)
require(toIntegral.isIntegral)
val thisName = fromIntegral.capitalized
val otherName = toIntegral.capitalized
return if (compareByDomainCapacity(toIntegral, fromIntegral) < 0) {
if (toIntegral == PrimitiveType.CHAR) {
"""
* Returns the `$otherName` with the numeric value equal to this value truncated to ${toIntegral.bitSize} bits.
*/
"""
} else {
"""
* If this value is in [$otherName.MIN_VALUE]..[$otherName.MAX_VALUE], the resulting `$otherName` value represents
* the same numerical value as this `$thisName`.
*
* The resulting `$otherName` value is represented by the least significant ${toIntegral.bitSize} bits of this `$thisName` value.
*/
"""
}
} else if (compareByDomainCapacity(toIntegral, fromIntegral) > 0) {
if (toIntegral == PrimitiveType.CHAR) {
"""
* Returns the `$otherName` with the numeric value equal to this value sign-extended to ${toIntegral.bitSize} bits.
*/
"""
} else {
"""
* The resulting `$otherName` value represents the same numerical value as this `$thisName`.
*
* The least significant ${fromIntegral.bitSize} bits of the resulting `$otherName` value are the same as the binary representation of this `$thisName` value,
* whereas the most significant ${toIntegral.bitSize - fromIntegral.bitSize} bits are filled with the bit sign of this value.
*/
"""
}
} else { // Short -> Char
"""
* Returns the `$otherName` with the numeric value equal to this value.
*/
"""
}
}
private fun docForConversionFromIntegralToFloating(fromIntegral: PrimitiveType, toFloating: PrimitiveType): String {
require(fromIntegral.isIntegral)
require(toFloating.isFloatingPoint)
val thisName = fromIntegral.capitalized
val otherName = toFloating.capitalized
return if (fromIntegral == PrimitiveType.LONG || fromIntegral == PrimitiveType.INT && toFloating == PrimitiveType.FLOAT) {
"""
* The resulting value is the closest `$otherName` to this `$thisName` value.
* In case when this `$thisName` value is exactly between two `$otherName`s,
* the one with zero at least significant bit of mantissa is selected.
*/
"""
} else {
"""
* The resulting `$otherName` value represents the same numerical value as this `$thisName`.
*/
"""
}
}
private fun generateConversions(kind: PrimitiveType) {
val thisName = kind.capitalized
for (otherKind in PrimitiveType.exceptBoolean) {
val name = otherKind.capitalized
out.println(" public override fun to$name(): $name")
val otherName = otherKind.capitalized
val doc = if (kind == otherKind) {
" /** Returns this value. */"
} else {
val detail = if (kind in PrimitiveType.integral) {
if (otherKind.isIntegral) {
docForConversionFromIntegralToIntegral(kind, otherKind)
} else {
docForConversionFromIntegralToFloating(kind, otherKind)
}
} else {
if (otherKind.isIntegral) {
docForConversionFromFloatingToIntegral(kind, otherKind)
} else {
docForConversionFromFloatingToFloating(kind, otherKind)
}
}
" /**\n * Converts this [$thisName] value to [$otherName].\n *\n" + detail.replaceIndent(" ")
}
out.println(doc)
out.println(" public override fun to$otherName(): $otherName")
}
}