org.jetbrains.kotlin.fir.backend.utils.ConstantUtils.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlin-compiler-embeddable Show documentation
Show all versions of kotlin-compiler-embeddable Show documentation
the Kotlin compiler embeddable
/*
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.backend.utils
import org.jetbrains.kotlin.fir.backend.Fir2IrComponents
import org.jetbrains.kotlin.fir.backend.Fir2IrConversionScope
import org.jetbrains.kotlin.fir.backend.Fir2IrVisitor
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirLiteralExpression
import org.jetbrains.kotlin.fir.types.ConeIntegerLiteralType
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.resolvedType
import org.jetbrains.kotlin.fir.types.toConstKind
import org.jetbrains.kotlin.ir.declarations.createExpressionBody
import org.jetbrains.kotlin.ir.expressions.IrConst
import org.jetbrains.kotlin.ir.expressions.IrConstKind
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.removeAnnotations
import org.jetbrains.kotlin.types.ConstantValueKind
fun FirLiteralExpression.getIrConstKind(): IrConstKind<*> = when (kind) {
ConstantValueKind.IntegerLiteral, ConstantValueKind.UnsignedIntegerLiteral -> {
val type = resolvedType as ConeIntegerLiteralType
type.getApproximatedType().toConstKind()!!.toIrConstKind()
}
else -> kind.toIrConstKind()
}
fun FirLiteralExpression.toIrConst(irType: IrType): IrConst {
return convertWithOffsets { startOffset, endOffset ->
@Suppress("UNCHECKED_CAST")
val kind = getIrConstKind() as IrConstKind
@Suppress("UNCHECKED_CAST")
val value = (value as? Long)?.let {
when (kind) {
IrConstKind.Byte -> it.toByte()
IrConstKind.Short -> it.toShort()
IrConstKind.Int -> it.toInt()
IrConstKind.Float -> it.toFloat()
IrConstKind.Double -> it.toDouble()
else -> it
}
} as T ?: value
@Suppress("UNCHECKED_CAST")
IrConstImpl(
startOffset, endOffset,
// Strip all annotations (including special annotations such as @EnhancedNullability) from a constant type
irType.removeAnnotations(),
kind, value as T
)
}
}
private fun ConstantValueKind.toIrConstKind(): IrConstKind<*> = when (this) {
ConstantValueKind.Null -> IrConstKind.Null
ConstantValueKind.Boolean -> IrConstKind.Boolean
ConstantValueKind.Char -> IrConstKind.Char
ConstantValueKind.Byte -> IrConstKind.Byte
ConstantValueKind.Short -> IrConstKind.Short
ConstantValueKind.Int -> IrConstKind.Int
ConstantValueKind.Long -> IrConstKind.Long
ConstantValueKind.UnsignedByte -> IrConstKind.Byte
ConstantValueKind.UnsignedShort -> IrConstKind.Short
ConstantValueKind.UnsignedInt -> IrConstKind.Int
ConstantValueKind.UnsignedLong -> IrConstKind.Long
ConstantValueKind.String -> IrConstKind.String
ConstantValueKind.Float -> IrConstKind.Float
ConstantValueKind.Double -> IrConstKind.Double
ConstantValueKind.IntegerLiteral, ConstantValueKind.UnsignedIntegerLiteral -> throw IllegalArgumentException()
ConstantValueKind.Error -> throw IllegalArgumentException()
}
// This method is intended to be used for default values of annotation parameters (compile-time strings, numbers, enum values, KClasses)
// where they are needed and may produce incorrect results for values that may be encountered outside annotations.
fun FirExpression.asCompileTimeIrInitializer(components: Fir2IrComponents, expectedType: ConeKotlinType? = null): IrExpressionBody {
val visitor = Fir2IrVisitor(components, Fir2IrConversionScope(components.configuration))
val expression = visitor.convertToIrExpression(this, expectedType = expectedType)
return components.irFactory.createExpressionBody(expression)
}