[JS IR BE] Support Number.to(Byte|Short|Int|Float|Double|Long)

This commit is contained in:
Svyatoslav Kuzmich
2018-10-10 20:50:01 +03:00
parent bad9534abd
commit 783f27c554
5 changed files with 33 additions and 21 deletions
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.symbols.impl.IrExternalPackageFragmentSymbolImpl
import org.jetbrains.kotlin.ir.util.constructors
import org.jetbrains.kotlin.ir.util.getPropertyGetter
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
@@ -101,6 +102,7 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC
val jsNumberToInt = getInternalFunction("numberToInt")
val jsNumberToShort = getInternalFunction("numberToShort")
val jsNumberToLong = getInternalFunction("numberToLong")
val jsNumberToChar = getInternalFunction("numberToChar")
val jsToByte = getInternalFunction("toByte")
val jsToShort = getInternalFunction("toShort")
val jsToLong = getInternalFunction("toLong")
@@ -174,6 +176,7 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC
)
val charClassSymbol = getInternalClassWithoutPackage("kotlin.Char")
val charConstructor = charClassSymbol.constructors.single().owner
val uByteClassSymbol = getInternalClassWithoutPackage("kotlin.UByte")
val uShortClassSymbol = getInternalClassWithoutPackage("kotlin.UShort")
@@ -6,11 +6,10 @@
package org.jetbrains.kotlin.ir.backend.js.lower.calls
import org.jetbrains.kotlin.ir.backend.js.ir.irCall
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.originalKotlinType
import org.jetbrains.kotlin.name.Name
@@ -18,13 +17,13 @@ import org.jetbrains.kotlin.types.SimpleType
typealias SymbolToTransformer = MutableMap<IrFunctionSymbol, (IrCall) -> IrExpression>
internal fun SymbolToTransformer.add(from: Map<SimpleType, IrSimpleFunction>, to: IrSimpleFunction) {
internal fun SymbolToTransformer.add(from: Map<SimpleType, IrFunction>, to: IrFunction) {
from.forEach { _, func ->
add(func.symbol, to)
}
}
internal fun SymbolToTransformer.add(from: Map<SimpleType, IrSimpleFunction>, to: (IrCall) -> IrExpression) {
internal fun SymbolToTransformer.add(from: Map<SimpleType, IrFunction>, to: (IrCall) -> IrExpression) {
from.forEach { _, func ->
add(func.symbol, to)
}
@@ -34,7 +33,7 @@ internal fun SymbolToTransformer.add(from: IrFunctionSymbol, to: (IrCall) -> IrE
put(from, to)
}
internal fun SymbolToTransformer.add(from: IrFunctionSymbol, to: IrSimpleFunction, dispatchReceiverAsFirstArgument: Boolean = false) {
internal fun SymbolToTransformer.add(from: IrFunctionSymbol, to: IrFunction, dispatchReceiverAsFirstArgument: Boolean = false) {
put(from) { call -> irCall(call, to.symbol, dispatchReceiverAsFirstArgument) }
}
@@ -48,11 +47,11 @@ internal fun <K> MutableMap<K, (IrCall) -> IrExpression>.addWithPredicate(
internal typealias MemberToTransformer = HashMap<SimpleMemberKey, (IrCall) -> IrExpression>
internal fun MemberToTransformer.add(type: IrType, name: Name, v: IrSimpleFunctionSymbol) {
internal fun MemberToTransformer.add(type: IrType, name: Name, v: IrFunctionSymbol) {
add(type, name) { irCall(it, v, dispatchReceiverAsFirstArgument = true) }
}
internal fun MemberToTransformer.add(type: IrType, name: Name, v: IrSimpleFunction) {
internal fun MemberToTransformer.add(type: IrType, name: Name, v: IrFunction) {
add(type, name, v.symbol)
}
@@ -64,21 +64,25 @@ class NumberConversionCallsTransformer(context: JsIrBackendContext) : CallsTrans
add(it, ConversionNames.TO_LONG, intrinsics.jsToLong)
}
for (type in arrayOf(irBuiltIns.byteType, irBuiltIns.intType)) {
add(type, ConversionNames.TO_CHAR) {
irCall(it, intrinsics.charClassSymbol.constructors.single(), dispatchReceiverAsFirstArgument = true)
}
irBuiltIns.numberType.let {
add(it, ConversionNames.TO_BYTE, intrinsics.jsNumberToByte)
add(it, ConversionNames.TO_DOUBLE, intrinsics.jsNumberToDouble)
add(it, ConversionNames.TO_FLOAT, intrinsics.jsNumberToDouble)
add(it, ConversionNames.TO_INT, intrinsics.jsNumberToInt)
add(it, ConversionNames.TO_SHORT, intrinsics.jsNumberToShort)
add(it, ConversionNames.TO_LONG, intrinsics.jsNumberToLong)
}
for (type in arrayOf(irBuiltIns.floatType, irBuiltIns.doubleType)) {
add(type, ConversionNames.TO_CHAR) {
JsIrBuilder.buildCall(intrinsics.charClassSymbol.constructors.single()).apply {
putValueArgument(0, irCall(it, intrinsics.jsNumberToInt, dispatchReceiverAsFirstArgument = true))
}
}
for (type in arrayOf(irBuiltIns.byteType, irBuiltIns.shortType, irBuiltIns.intType)) {
add(type, ConversionNames.TO_CHAR, intrinsics.charConstructor)
}
add(irBuiltIns.charType, ConversionNames.TO_CHAR) { it.dispatchReceiver!! }
for (type in arrayOf(irBuiltIns.floatType, irBuiltIns.doubleType, irBuiltIns.numberType)) {
add(type, ConversionNames.TO_CHAR, intrinsics.jsNumberToChar)
}
add(irBuiltIns.charType, ConversionNames.TO_CHAR, ::useDispatchReceiver)
}
override fun transformCall(call: IrCall): IrExpression {
@@ -86,6 +86,10 @@ class IrBuiltIns(
val charType = char.toIrType()
val charClass = builtIns.char.toIrSymbol()
val number = builtIns.number.defaultType
val numberType = number.toIrType()
val numberClass = builtIns.number.toIrSymbol()
val byte = builtIns.byteType
val byteType = byte.toIrType()
val byteClass = builtIns.byte.toIrSymbol()
@@ -9,7 +9,7 @@ fun numberToByte(a: dynamic): Byte = toByte(numberToInt(a))
fun numberToDouble(a: dynamic): Double = js("+a").unsafeCast<Double>()
fun numberToInt(a: dynamic): Int = doubleToInt(a)
fun numberToInt(a: dynamic): Int = if (a is Long) a.toInt() else doubleToInt(a)
fun numberToShort(a: dynamic): Short = toShort(numberToInt(a))
@@ -17,7 +17,7 @@ fun numberToShort(a: dynamic): Short = toShort(numberToInt(a))
fun toByte(a: dynamic): Byte = js("a << 24 >> 24").unsafeCast<Byte>()
fun toShort(a: dynamic): Short = js("a << 16 >> 16").unsafeCast<Short>()
fun numberToLong(a: dynamic): Long = fromNumber(a)
fun numberToLong(a: dynamic): Long = if (a is Long) a else fromNumber(a)
fun toLong(a: dynamic): Long = fromInt(a)
@@ -25,4 +25,6 @@ fun doubleToInt(a: dynamic) = js("""
if (a > 2147483647) return 2147483647;
if (a < -2147483648) return -2147483648;
return a | 0;
""").unsafeCast<Int>()
""").unsafeCast<Int>()
fun numberToChar(a: dynamic) = Char(numberToInt(a))