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 project(':Interop:Indexer')
|
||||||
compile "org.jetbrains.kotlin:kotlin-native-shared:$konanVersion"
|
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? {
|
private fun integerLiteral(size: Int, isSigned: Boolean, value: Long): String? {
|
||||||
if (!isSigned) {
|
return if (isSigned) {
|
||||||
val signedLiteral = integerLiteral(size, true, value)
|
if (value == Long.MIN_VALUE) {
|
||||||
val converter = when (size) {
|
return "${value + 1} - 1" // Workaround for "The value is out of range" compile error.
|
||||||
1 -> "toUByte"
|
}
|
||||||
2 -> "toUShort"
|
|
||||||
4 -> "toUInt"
|
val narrowedValue: Number = when (size) {
|
||||||
8 -> "toULong"
|
1 -> value.toByte()
|
||||||
|
2 -> value.toShort()
|
||||||
|
4 -> value.toInt()
|
||||||
|
8 -> value
|
||||||
else -> return null
|
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) {
|
"${narrowedValue}u"
|
||||||
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 narrowedValue.toString()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun floatingLiteral(type: Type, value: Double): String? {
|
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) {
|
private fun generateConstant(constant: ConstantDef) {
|
||||||
val literal = when (constant) {
|
val kotlinName = constant.name
|
||||||
is IntegerConstantDef -> integerLiteral(constant.type, constant.value) ?: return
|
val declaration = when (constant) {
|
||||||
is FloatingConstantDef -> floatingLiteral(constant.type, constant.value) ?: return
|
is IntegerConstantDef -> {
|
||||||
is StringConstantDef -> constant.value.quoteAsKotlinLiteral()
|
val literal = integerLiteral(constant.type, constant.value) ?: return
|
||||||
else -> {
|
val kotlinType = mirror(constant.type).argType
|
||||||
// Not supported yet, ignore:
|
when (platform) {
|
||||||
return
|
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) {
|
out(declaration)
|
||||||
is IntegerConstantDef,
|
|
||||||
is FloatingConstantDef -> mirror(constant.type).argType
|
|
||||||
|
|
||||||
is StringConstantDef -> KotlinTypes.string
|
// TODO: consider using `const` modifier in all cases.
|
||||||
|
// Note: It is not currently possible for floating literals.
|
||||||
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")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateStubs(): List<KotlinStub> {
|
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.descriptors.ModuleDescriptor
|
||||||
import org.jetbrains.kotlin.konan.library.KonanLibrary
|
import org.jetbrains.kotlin.konan.library.KonanLibrary
|
||||||
|
import org.jetbrains.kotlin.konan.library.isInterop
|
||||||
|
|
||||||
sealed class KonanModuleOrigin {
|
sealed class KonanModuleOrigin {
|
||||||
|
|
||||||
@@ -18,4 +19,9 @@ object CurrentKonanModuleOrigin: CompiledKonanModuleOrigin()
|
|||||||
|
|
||||||
object SyntheticModulesOrigin : KonanModuleOrigin()
|
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)!!
|
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.impl.ModuleDescriptorImpl
|
||||||
import org.jetbrains.kotlin.descriptors.konan.KonanModuleDescriptorFactory
|
import org.jetbrains.kotlin.descriptors.konan.KonanModuleDescriptorFactory
|
||||||
import org.jetbrains.kotlin.descriptors.konan.KonanModuleOrigin
|
import org.jetbrains.kotlin.descriptors.konan.KonanModuleOrigin
|
||||||
|
import org.jetbrains.kotlin.descriptors.konan.isInteropLibrary
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.resolve.ImplicitIntegerCoercion
|
||||||
import org.jetbrains.kotlin.storage.StorageManager
|
import org.jetbrains.kotlin.storage.StorageManager
|
||||||
|
|
||||||
internal object KonanModuleDescriptorFactoryImpl: KonanModuleDescriptorFactory {
|
internal object KonanModuleDescriptorFactoryImpl: KonanModuleDescriptorFactory {
|
||||||
@@ -21,7 +23,10 @@ internal object KonanModuleDescriptorFactoryImpl: KonanModuleDescriptorFactory {
|
|||||||
name,
|
name,
|
||||||
storageManager,
|
storageManager,
|
||||||
builtIns,
|
builtIns,
|
||||||
capabilities = customCapabilities + mapOf(KonanModuleOrigin.CAPABILITY to origin))
|
capabilities = customCapabilities + mapOf(
|
||||||
|
KonanModuleOrigin.CAPABILITY to origin,
|
||||||
|
ImplicitIntegerCoercion.MODULE_CAPABILITY to origin.isInteropLibrary()
|
||||||
|
))
|
||||||
|
|
||||||
override fun createDescriptorAndNewBuiltIns(
|
override fun createDescriptorAndNewBuiltIns(
|
||||||
name: Name,
|
name: Name,
|
||||||
|
|||||||
Reference in New Issue
Block a user