Add possibility to interpret spread operator on unsigned arrays

This commit is contained in:
Ivan Kylchik
2020-08-21 17:59:13 +03:00
committed by TeamCityServer
parent ca231ccc53
commit 3c0c8d97cc
2 changed files with 35 additions and 16 deletions
@@ -700,32 +700,44 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
} }
private fun interpretVararg(expression: IrVararg): ExecutionResult { private fun interpretVararg(expression: IrVararg): ExecutionResult {
fun arrayToList(value: Any?): List<Any?> {
return when (value) {
is ByteArray -> value.toList()
is CharArray -> value.toList()
is ShortArray -> value.toList()
is IntArray -> value.toList()
is LongArray -> value.toList()
is FloatArray -> value.toList()
is DoubleArray -> value.toList()
is BooleanArray -> value.toList()
is Array<*> -> value.toList()
else -> listOf(value)
}
}
val args = expression.elements.flatMap { val args = expression.elements.flatMap {
it.interpret().check { executionResult -> return executionResult } it.interpret().check { executionResult -> return executionResult }
return@flatMap when (val result = stack.popReturnValue()) { return@flatMap when (val result = stack.popReturnValue()) {
is Wrapper -> listOf(result.value) is Wrapper -> listOf(result.value)
is Primitive<*> -> is Primitive<*> -> arrayToList(result.value)
when (val value = result.value) { is Common -> when {
is ByteArray -> value.toList() result.irClass.defaultType.isUnsignedArray() -> arrayToList((result.fields.single().state as Primitive<*>).value)
is CharArray -> value.toList() else -> listOf(result)
is ShortArray -> value.toList() }
is IntArray -> value.toList()
is LongArray -> value.toList()
is FloatArray -> value.toList()
is DoubleArray -> value.toList()
is BooleanArray -> value.toList()
is Array<*> -> value.toList()
else -> listOf(value)
}
else -> listOf(result) else -> listOf(result)
} }
} }
val array = when ((expression.type.classifierOrFail.owner as? IrDeclaration)?.nameForIrSerialization?.asString()) { val array = when {
"UByteArray", "UShortArray", "UIntArray", "ULongArray" -> { expression.type.isUnsignedArray() -> {
val owner = expression.type.classOrNull!!.owner val owner = expression.type.classOrNull!!.owner
val storageProperty = owner.declarations.filterIsInstance<IrProperty>().first { it.name.asString() == "storage" } val storageProperty = owner.declarations.filterIsInstance<IrProperty>().first { it.name.asString() == "storage" }
val primitiveArray = args.map { ((it as Common).fields.single().state as Primitive<*>).value } val primitiveArray = args.map {
when (it) {
is Common -> (it.fields.single().state as Primitive<*>).value // is unsigned number
else -> it // is primitive number
}
}
val unsignedArray = primitiveArray.toPrimitiveStateArray(storageProperty.backingField!!.type) val unsignedArray = primitiveArray.toPrimitiveStateArray(storageProperty.backingField!!.type)
Common(owner).apply { Common(owner).apply {
setSuperClassRecursive() setSuperClassRecursive()
@@ -214,6 +214,13 @@ internal fun State?.getCorrectReceiverByFunction(irFunction: IrFunction): State?
internal fun IrFunction.getCapitalizedFileName() = this.file.name.replace(".kt", "Kt").capitalizeAsciiOnly() internal fun IrFunction.getCapitalizedFileName() = this.file.name.replace(".kt", "Kt").capitalizeAsciiOnly()
internal fun IrType.isUnsigned() = this.isUByte() || this.isUShort() || this.isUInt() || this.isULong()
internal fun IrType.isUnsignedArray(): Boolean {
if (this !is IrSimpleType || classifier !is IrClassSymbol) return false
val fqName = (classifier.owner as IrDeclarationWithName).fqNameWhenAvailable?.asString()
return fqName in setOf("kotlin.UByteArray", "kotlin.UShortArray", "kotlin.UIntArray", "kotlin.ULongArray")
}
internal fun IrType.isPrimitiveArray(): Boolean { internal fun IrType.isPrimitiveArray(): Boolean {
return this.getClass()?.fqNameWhenAvailable?.toUnsafe()?.let { StandardNames.isPrimitiveArray(it) } ?: false return this.getClass()?.fqNameWhenAvailable?.toUnsafe()?.let { StandardNames.isPrimitiveArray(it) } ?: false
} }