Enable implicit integer coercion for interop libraries
This commit is contained in:
committed by
SvyatoslavScherbina
parent
5eaaa5bbb9
commit
2c12dcd612
@@ -36,3 +36,9 @@ dependencies {
|
||||
compile project(':Interop:Indexer')
|
||||
compile "org.jetbrains.kotlin:kotlin-native-shared:$konanVersion"
|
||||
}
|
||||
|
||||
compileKotlin {
|
||||
kotlinOptions {
|
||||
freeCompilerArgs = ['-Xuse-experimental=kotlin.ExperimentalUnsignedTypes']
|
||||
}
|
||||
}
|
||||
|
||||
+50
-47
@@ -732,32 +732,31 @@ class StubGenerator(
|
||||
}
|
||||
|
||||
private fun integerLiteral(size: Int, isSigned: Boolean, value: Long): String? {
|
||||
if (!isSigned) {
|
||||
val signedLiteral = integerLiteral(size, true, value)
|
||||
val converter = when (size) {
|
||||
1 -> "toUByte"
|
||||
2 -> "toUShort"
|
||||
4 -> "toUInt"
|
||||
8 -> "toULong"
|
||||
return if (isSigned) {
|
||||
if (value == Long.MIN_VALUE) {
|
||||
return "${value + 1} - 1" // Workaround for "The value is out of range" compile error.
|
||||
}
|
||||
|
||||
val narrowedValue: Number = when (size) {
|
||||
1 -> value.toByte()
|
||||
2 -> value.toShort()
|
||||
4 -> value.toInt()
|
||||
8 -> value
|
||||
else -> return null
|
||||
}
|
||||
|
||||
return "($signedLiteral).$converter()"
|
||||
}
|
||||
narrowedValue.toString()
|
||||
} else {
|
||||
val narrowedValue: Any = when (size) {
|
||||
1 -> value.toUByte()
|
||||
2 -> value.toUShort()
|
||||
4 -> value.toUInt()
|
||||
8 -> value.toULong()
|
||||
else -> return null
|
||||
}
|
||||
|
||||
if (value == Long.MIN_VALUE) {
|
||||
return "${value + 1} - 1" // Workaround for "The value is out of range" compile error.
|
||||
"${narrowedValue}u"
|
||||
}
|
||||
|
||||
val narrowedValue: Number = when (size) {
|
||||
1 -> value.toByte()
|
||||
2 -> value.toShort()
|
||||
4 -> value.toInt()
|
||||
8 -> value
|
||||
else -> return null
|
||||
}
|
||||
|
||||
return narrowedValue.toString()
|
||||
}
|
||||
|
||||
private fun floatingLiteral(type: Type, value: Double): String? {
|
||||
@@ -777,37 +776,41 @@ class StubGenerator(
|
||||
}
|
||||
}
|
||||
|
||||
private fun topLevelValWithGetter(name: String, type: KotlinType, expressionBody: String): String =
|
||||
"val ${name.asSimpleName()}: ${type.render(kotlinFile)} get() = $expressionBody"
|
||||
|
||||
private fun topLevelConstVal(name: String, type: KotlinType, initializer: String): String =
|
||||
"const val ${name.asSimpleName()}: ${type.render(kotlinFile)} = $initializer"
|
||||
|
||||
private fun generateConstant(constant: ConstantDef) {
|
||||
val literal = when (constant) {
|
||||
is IntegerConstantDef -> integerLiteral(constant.type, constant.value) ?: return
|
||||
is FloatingConstantDef -> floatingLiteral(constant.type, constant.value) ?: return
|
||||
is StringConstantDef -> constant.value.quoteAsKotlinLiteral()
|
||||
else -> {
|
||||
// Not supported yet, ignore:
|
||||
return
|
||||
val kotlinName = constant.name
|
||||
val declaration = when (constant) {
|
||||
is IntegerConstantDef -> {
|
||||
val literal = integerLiteral(constant.type, constant.value) ?: return
|
||||
val kotlinType = mirror(constant.type).argType
|
||||
when (platform) {
|
||||
KotlinPlatform.NATIVE -> topLevelConstVal(kotlinName, kotlinType, literal)
|
||||
// No reason to make it const val with backing field on Kotlin/JVM yet:
|
||||
KotlinPlatform.JVM -> topLevelValWithGetter(kotlinName, kotlinType, literal)
|
||||
}
|
||||
}
|
||||
is FloatingConstantDef -> {
|
||||
val literal = floatingLiteral(constant.type, constant.value) ?: return
|
||||
val kotlinType = mirror(constant.type).argType
|
||||
topLevelValWithGetter(kotlinName, kotlinType, literal)
|
||||
}
|
||||
is StringConstantDef -> {
|
||||
val literal = constant.value.quoteAsKotlinLiteral()
|
||||
val kotlinType = KotlinTypes.string
|
||||
topLevelValWithGetter(kotlinName, kotlinType, literal)
|
||||
}
|
||||
else -> return
|
||||
}
|
||||
|
||||
val kotlinType = when (constant) {
|
||||
is IntegerConstantDef,
|
||||
is FloatingConstantDef -> mirror(constant.type).argType
|
||||
out(declaration)
|
||||
|
||||
is StringConstantDef -> KotlinTypes.string
|
||||
|
||||
else -> {
|
||||
// Not supported yet, ignore:
|
||||
return
|
||||
}
|
||||
}.render(kotlinFile)
|
||||
|
||||
// TODO: improve value rendering.
|
||||
|
||||
// TODO: consider using `const` modifier.
|
||||
// It is not currently possible for floating literals.
|
||||
// Also it provokes constant propagation which can reduce binary compatibility
|
||||
// when replacing interop stubs without recompiling the application.
|
||||
|
||||
out("val ${constant.name.asSimpleName()}: $kotlinType get() = $literal")
|
||||
// TODO: consider using `const` modifier in all cases.
|
||||
// Note: It is not currently possible for floating literals.
|
||||
}
|
||||
|
||||
private fun generateStubs(): List<KotlinStub> {
|
||||
|
||||
+6
@@ -2,6 +2,7 @@ package org.jetbrains.kotlin.descriptors.konan
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.konan.library.KonanLibrary
|
||||
import org.jetbrains.kotlin.konan.library.isInterop
|
||||
|
||||
sealed class KonanModuleOrigin {
|
||||
|
||||
@@ -18,4 +19,9 @@ object CurrentKonanModuleOrigin: CompiledKonanModuleOrigin()
|
||||
|
||||
object SyntheticModulesOrigin : KonanModuleOrigin()
|
||||
|
||||
internal fun KonanModuleOrigin.isInteropLibrary(): Boolean = when (this) {
|
||||
is DeserializedKonanModuleOrigin -> this.library.isInterop
|
||||
CurrentKonanModuleOrigin, SyntheticModulesOrigin -> false
|
||||
}
|
||||
|
||||
val ModuleDescriptor.konanModuleOrigin get() = this.getCapability(KonanModuleOrigin.CAPABILITY)!!
|
||||
|
||||
+6
-1
@@ -6,7 +6,9 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.konan.KonanModuleDescriptorFactory
|
||||
import org.jetbrains.kotlin.descriptors.konan.KonanModuleOrigin
|
||||
import org.jetbrains.kotlin.descriptors.konan.isInteropLibrary
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.ImplicitIntegerCoercion
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
|
||||
internal object KonanModuleDescriptorFactoryImpl: KonanModuleDescriptorFactory {
|
||||
@@ -21,7 +23,10 @@ internal object KonanModuleDescriptorFactoryImpl: KonanModuleDescriptorFactory {
|
||||
name,
|
||||
storageManager,
|
||||
builtIns,
|
||||
capabilities = customCapabilities + mapOf(KonanModuleOrigin.CAPABILITY to origin))
|
||||
capabilities = customCapabilities + mapOf(
|
||||
KonanModuleOrigin.CAPABILITY to origin,
|
||||
ImplicitIntegerCoercion.MODULE_CAPABILITY to origin.isInteropLibrary()
|
||||
))
|
||||
|
||||
override fun createDescriptorAndNewBuiltIns(
|
||||
name: Name,
|
||||
|
||||
Reference in New Issue
Block a user