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
+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")
}
}