Change toIrConst extension function logic
For now this function check not value, but type. By ir type it create right ir const
This commit is contained in:
+9
-9
@@ -407,13 +407,13 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
|
||||
}
|
||||
|
||||
private suspend fun interpretConst(expression: IrConst<*>): ExecutionResult {
|
||||
fun getSignedType(unsignedClassName: String): IrType {
|
||||
return when (unsignedClassName) {
|
||||
"UByte" -> irBuiltIns.byteType
|
||||
"UShort" -> irBuiltIns.shortType
|
||||
"UInt" -> irBuiltIns.intType
|
||||
"ULong" -> irBuiltIns.longType
|
||||
else -> throw InterpreterException("Unsupported unsigned class $unsignedClassName")
|
||||
fun getSignedType(unsignedType: IrType): IrType {
|
||||
return when {
|
||||
unsignedType.isUByte() -> irBuiltIns.byteType
|
||||
unsignedType.isUShort() -> irBuiltIns.shortType
|
||||
unsignedType.isUInt() -> irBuiltIns.intType
|
||||
unsignedType.isULong() -> irBuiltIns.longType
|
||||
else -> throw InterpreterException("Unsupported unsigned class ${unsignedType.render()}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -421,7 +421,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
|
||||
val unsignedClass = expression.type.classOrNull!!
|
||||
val constructor = unsignedClass.constructors.single().owner
|
||||
val constructorCall = IrConstructorCallImpl.fromSymbolOwner(constructor.returnType, constructor.symbol)
|
||||
constructorCall.putValueArgument(0, expression.value.toIrConst(getSignedType(unsignedClass.owner.name.asString())))
|
||||
constructorCall.putValueArgument(0, expression.value.toIrConst(getSignedType(expression.type)))
|
||||
|
||||
constructorCall.interpret()
|
||||
} else {
|
||||
@@ -622,7 +622,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
|
||||
IrTypeOperator.CAST, IrTypeOperator.IMPLICIT_CAST -> {
|
||||
if (!isErased && !stack.peekReturnValue().isSubtypeOf(typeOperand)) {
|
||||
val convertibleClassName = stack.popReturnValue().irClass.fqNameWhenAvailable
|
||||
throw ClassCastException("$convertibleClassName cannot be cast to ${typeOperand.getFqName(withNullableSymbol = true)}")
|
||||
throw ClassCastException("$convertibleClassName cannot be cast to ${typeOperand.render()}")
|
||||
}
|
||||
}
|
||||
IrTypeOperator.SAFE_CAST -> {
|
||||
|
||||
+2
-1
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrNull
|
||||
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
||||
import org.jetbrains.kotlin.ir.util.render
|
||||
|
||||
enum class ReturnLabel {
|
||||
NEXT, RETURN, BREAK_LOOP, BREAK_WHEN, CONTINUE, EXCEPTION
|
||||
@@ -46,7 +47,7 @@ fun ExecutionResult.implicitCastIfNeeded(expectedType: IrType, actualType: IrTyp
|
||||
|
||||
if (!actualState.isSubtypeOf(expectedType)) {
|
||||
val convertibleClassName = stack.popReturnValue().irClass.fqNameWhenAvailable
|
||||
throw ClassCastException("$convertibleClassName cannot be cast to ${expectedType.getFqName(withNullableSymbol = true)}")
|
||||
throw ClassCastException("$convertibleClassName cannot be cast to ${expectedType.render()}")
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
+43
-44
@@ -42,20 +42,18 @@ fun IrFunctionAccessExpression.getBody(): IrBody? {
|
||||
fun State.toIrExpression(expression: IrExpression): IrExpression {
|
||||
val start = expression.startOffset
|
||||
val end = expression.endOffset
|
||||
val type = expression.type.makeNotNull()
|
||||
return when (this) {
|
||||
is Primitive<*> ->
|
||||
when (this.value) {
|
||||
// toIrConst call is necessary to replace ir offsets
|
||||
is Boolean, is Char, is Byte, is Short, is Int, is Long, is String, is Float, is Double ->
|
||||
this.value.toIrConst(this.type, start, end)
|
||||
null -> this.value.toIrConst(this.type, start, end)
|
||||
when {
|
||||
this.value == null -> this.value.toIrConst(type, start, end)
|
||||
type.isPrimitiveType() || type.isString() -> this.value.toIrConst(type, start, end)
|
||||
else -> expression // TODO support for arrays
|
||||
}
|
||||
is Complex -> {
|
||||
val type = this.irClass.defaultType.toKotlinType()
|
||||
val stateType = this.irClass.defaultType.toKotlinType()
|
||||
when {
|
||||
UnsignedTypes.isUnsignedType(type) ->
|
||||
(this.fields.single().state as Primitive<*>).value.toIrConst(this.irClass.defaultType, start, end)
|
||||
UnsignedTypes.isUnsignedType(stateType) -> (this.fields.single().state as Primitive<*>).value.toIrConst(type, start, end)
|
||||
else -> expression
|
||||
}
|
||||
}
|
||||
@@ -74,18 +72,23 @@ fun Any?.toState(irType: IrType): State {
|
||||
}
|
||||
|
||||
fun Any?.toIrConst(irType: IrType, startOffset: Int = UNDEFINED_OFFSET, endOffset: Int = UNDEFINED_OFFSET): IrConst<*> {
|
||||
return when (this) {
|
||||
is Boolean -> IrConstImpl(startOffset, endOffset, irType, IrConstKind.Boolean, this)
|
||||
is Char -> IrConstImpl(startOffset, endOffset, irType, IrConstKind.Char, this)
|
||||
is Byte -> IrConstImpl(startOffset, endOffset, irType, IrConstKind.Byte, this)
|
||||
is Short -> IrConstImpl(startOffset, endOffset, irType, IrConstKind.Short, this)
|
||||
is Int -> IrConstImpl(startOffset, endOffset, irType, IrConstKind.Int, this)
|
||||
is Long -> IrConstImpl(startOffset, endOffset, irType, IrConstKind.Long, this)
|
||||
is String -> IrConstImpl(startOffset, endOffset, irType, IrConstKind.String, this)
|
||||
is Float -> IrConstImpl(startOffset, endOffset, irType, IrConstKind.Float, this)
|
||||
is Double -> IrConstImpl(startOffset, endOffset, irType, IrConstKind.Double, this)
|
||||
null -> IrConstImpl(startOffset, endOffset, irType, IrConstKind.Null, this)
|
||||
else -> throw UnsupportedOperationException("Unsupported const element type ${this::class}")
|
||||
val constType = irType.makeNotNull()
|
||||
return when {
|
||||
this == null -> IrConstImpl.constNull(startOffset, endOffset, irType)
|
||||
constType.isBoolean() -> IrConstImpl.boolean(startOffset, endOffset, constType, this as Boolean)
|
||||
constType.isChar() -> IrConstImpl.char(startOffset, endOffset, constType, this as Char)
|
||||
constType.isByte() -> IrConstImpl.byte(startOffset, endOffset, constType, (this as Number).toByte())
|
||||
constType.isShort() -> IrConstImpl.short(startOffset, endOffset, constType, (this as Number).toShort())
|
||||
constType.isInt() -> IrConstImpl.int(startOffset, endOffset, constType, (this as Number).toInt())
|
||||
constType.isLong() -> IrConstImpl.long(startOffset, endOffset, constType, (this as Number).toLong())
|
||||
constType.isString() -> IrConstImpl.string(startOffset, endOffset, constType, this as String)
|
||||
constType.isFloat() -> IrConstImpl.float(startOffset, endOffset, constType, (this as Number).toFloat())
|
||||
constType.isDouble() -> IrConstImpl.double(startOffset, endOffset, constType, (this as Number).toDouble())
|
||||
constType.isUByte() -> IrConstImpl.byte(startOffset, endOffset, constType, (this as Number).toByte())
|
||||
constType.isUShort() -> IrConstImpl.short(startOffset, endOffset, constType, (this as Number).toShort())
|
||||
constType.isUInt() -> IrConstImpl.int(startOffset, endOffset, constType, (this as Number).toInt())
|
||||
constType.isULong() -> IrConstImpl.long(startOffset, endOffset, constType, (this as Number).toLong())
|
||||
else -> throw UnsupportedOperationException("Unsupported const element type ${constType.render()}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,25 +115,21 @@ fun IrAnnotationContainer.getEvaluateIntrinsicValue(): String? {
|
||||
return (this.getAnnotation(evaluateIntrinsicAnnotation).getValueArgument(0) as IrConst<*>).value.toString()
|
||||
}
|
||||
|
||||
fun getPrimitiveClass(fqName: String, asObject: Boolean = false): Class<*>? {
|
||||
return when (fqName) {
|
||||
"kotlin.Boolean" -> if (asObject) Boolean::class.javaObjectType else Boolean::class.java
|
||||
"kotlin.Char" -> if (asObject) Char::class.javaObjectType else Char::class.java
|
||||
"kotlin.Byte" -> if (asObject) Byte::class.javaObjectType else Byte::class.java
|
||||
"kotlin.Short" -> if (asObject) Short::class.javaObjectType else Short::class.java
|
||||
"kotlin.Int" -> if (asObject) Int::class.javaObjectType else Int::class.java
|
||||
"kotlin.Long" -> if (asObject) Long::class.javaObjectType else Long::class.java
|
||||
"kotlin.String" -> if (asObject) String::class.javaObjectType else String::class.java
|
||||
"kotlin.Float" -> if (asObject) Float::class.javaObjectType else Float::class.java
|
||||
"kotlin.Double" -> if (asObject) Double::class.javaObjectType else Double::class.java
|
||||
fun getPrimitiveClass(irType: IrType, asObject: Boolean = false): Class<*>? {
|
||||
return when {
|
||||
irType.isBoolean() -> if (asObject) Boolean::class.javaObjectType else Boolean::class.java
|
||||
irType.isChar() -> if (asObject) Char::class.javaObjectType else Char::class.java
|
||||
irType.isByte() -> if (asObject) Byte::class.javaObjectType else Byte::class.java
|
||||
irType.isShort() -> if (asObject) Short::class.javaObjectType else Short::class.java
|
||||
irType.isInt() -> if (asObject) Int::class.javaObjectType else Int::class.java
|
||||
irType.isLong() -> if (asObject) Long::class.javaObjectType else Long::class.java
|
||||
irType.isString() -> if (asObject) String::class.javaObjectType else String::class.java
|
||||
irType.isFloat() -> if (asObject) Float::class.javaObjectType else Float::class.java
|
||||
irType.isDouble() -> if (asObject) Double::class.javaObjectType else Double::class.java
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
fun IrType.getFqName(withNullableSymbol: Boolean = false): String? {
|
||||
return this.classOrNull?.owner?.fqNameWhenAvailable?.asString()?.let { if (this.isNullable() && withNullableSymbol) "$it?" else it }
|
||||
}
|
||||
|
||||
fun IrFunction.getArgsForMethodInvocation(args: List<Variable>): List<Any?> {
|
||||
val argsValues = args.map {
|
||||
when (val state = it.state) {
|
||||
@@ -159,15 +158,15 @@ fun IrFunction.getLastOverridden(): IrFunction {
|
||||
}
|
||||
|
||||
fun List<Any?>.toPrimitiveStateArray(type: IrType): Primitive<*> {
|
||||
return when (type.getFqName()) {
|
||||
"kotlin.ByteArray" -> Primitive(ByteArray(size) { i -> (this[i] as Number).toByte() }, type)
|
||||
"kotlin.CharArray" -> Primitive(CharArray(size) { i -> this[i] as Char }, type)
|
||||
"kotlin.ShortArray" -> Primitive(ShortArray(size) { i -> (this[i] as Number).toShort() }, type)
|
||||
"kotlin.IntArray" -> Primitive(IntArray(size) { i -> (this[i] as Number).toInt() }, type)
|
||||
"kotlin.LongArray" -> Primitive(LongArray(size) { i -> (this[i] as Number).toLong() }, type)
|
||||
"kotlin.FloatArray" -> Primitive(FloatArray(size) { i -> (this[i] as Number).toFloat() }, type)
|
||||
"kotlin.DoubleArray" -> Primitive(DoubleArray(size) { i -> (this[i] as Number).toDouble() }, type)
|
||||
"kotlin.BooleanArray" -> Primitive(BooleanArray(size) { i -> this[i].toString().toBoolean() }, type)
|
||||
return when {
|
||||
type.isByteArray() -> Primitive(ByteArray(size) { i -> (this[i] as Number).toByte() }, type)
|
||||
type.isCharArray() -> Primitive(CharArray(size) { i -> this[i] as Char }, type)
|
||||
type.isShortArray() -> Primitive(ShortArray(size) { i -> (this[i] as Number).toShort() }, type)
|
||||
type.isIntArray() -> Primitive(IntArray(size) { i -> (this[i] as Number).toInt() }, type)
|
||||
type.isLongArray() -> Primitive(LongArray(size) { i -> (this[i] as Number).toLong() }, type)
|
||||
type.isFloatArray() -> Primitive(FloatArray(size) { i -> (this[i] as Number).toFloat() }, type)
|
||||
type.isDoubleArray() -> Primitive(DoubleArray(size) { i -> (this[i] as Number).toDouble() }, type)
|
||||
type.isBooleanArray() -> Primitive(BooleanArray(size) { i -> this[i].toString().toBoolean() }, type)
|
||||
else -> Primitive<Array<*>>(this.toTypedArray(), type)
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -5,7 +5,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.common.interpreter.state
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.getFqName
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.getLastOverridden
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.stack.Variable
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
@@ -13,6 +12,7 @@ import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.util.nameForIrSerialization
|
||||
import org.jetbrains.kotlin.ir.util.render
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
|
||||
class Lambda(val irFunction: IrFunction, override val irClass: IrClass) : State {
|
||||
@@ -29,9 +29,9 @@ class Lambda(val irFunction: IrFunction, override val irClass: IrClass) : State
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
val receiver = (irFunction.dispatchReceiverParameter?.type ?: irFunction.extensionReceiverParameter?.type)?.getFqName(true)
|
||||
val arguments = irFunction.valueParameters.map { it.type.getFqName(true) }.joinToString(prefix = "(", postfix = ")")
|
||||
val returnType = irFunction.returnType.getFqName(true)
|
||||
val receiver = (irFunction.dispatchReceiverParameter?.type ?: irFunction.extensionReceiverParameter?.type)?.render()
|
||||
val arguments = irFunction.valueParameters.joinToString(prefix = "(", postfix = ")") { it.type.render() }
|
||||
val returnType = irFunction.returnType.render()
|
||||
return ("$arguments -> $returnType").let { if (receiver != null) "$receiver.$it" else it }
|
||||
}
|
||||
}
|
||||
+2
-3
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.backend.common.interpreter.state
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.builtins.evaluateIntrinsicAnnotation
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.getEvaluateIntrinsicValue
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.getFqName
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.getPrimitiveClass
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.hasAnnotation
|
||||
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
||||
@@ -124,14 +123,14 @@ class Wrapper(val value: Any, override val irClass: IrClass) : Complex(irClass,
|
||||
}
|
||||
|
||||
private fun IrType.getClass(asObject: Boolean): Class<out Any> {
|
||||
val fqName = this.getFqName() ?: return Any::class.java // null if this.isTypeParameter()
|
||||
val owner = this.classOrNull?.owner
|
||||
return when {
|
||||
this.isPrimitiveType() -> getPrimitiveClass(fqName, asObject)!!
|
||||
this.isPrimitiveType() -> getPrimitiveClass(this.makeNotNull(), asObject)!!
|
||||
this.isArray() -> if (asObject) Array<Any?>::class.javaObjectType else Array<Any?>::class.java
|
||||
//TODO primitive array
|
||||
owner.hasAnnotation(evaluateIntrinsicAnnotation) -> Class.forName(owner!!.getEvaluateIntrinsicValue())
|
||||
else -> {
|
||||
val fqName = owner?.fqNameWhenAvailable?.asString() ?: return Any::class.java // null if this.isTypeParameter()
|
||||
val javaClassId = JavaToKotlinClassMap.mapKotlinToJava(FqNameUnsafe(fqName))
|
||||
val className = javaClassId?.asSingleFqName()?.asString() ?: fqName
|
||||
Class.forName(className.replaceDotWithDollarForInnerClasses())
|
||||
|
||||
Reference in New Issue
Block a user