[IR] Handle each interpreter checker one by one
This wy we can interpret all expressions like `A::a.name` at first and after that evaluate all complex expressions like `A::a.name + A::b.name`.
This commit is contained in:
+3
-4
@@ -9,11 +9,10 @@ import org.jetbrains.kotlin.ir.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.interpreter.IrInterpreterConfiguration
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
|
||||
interface IrInterpreterChecker : IrElementVisitor<Boolean, IrInterpreterCheckerData> {
|
||||
val mode: EvaluationMode
|
||||
}
|
||||
interface IrInterpreterChecker : IrElementVisitor<Boolean, IrInterpreterCheckerData>
|
||||
|
||||
class IrInterpreterCheckerData(
|
||||
val mode: EvaluationMode,
|
||||
val irBuiltIns: IrBuiltIns,
|
||||
val interpreterConfiguration: IrInterpreterConfiguration
|
||||
val interpreterConfiguration: IrInterpreterConfiguration,
|
||||
)
|
||||
+19
-21
@@ -17,9 +17,7 @@ import org.jetbrains.kotlin.ir.util.constructors
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.ir.util.statements
|
||||
|
||||
class IrInterpreterCommonChecker(
|
||||
override val mode: EvaluationMode
|
||||
) : IrInterpreterChecker {
|
||||
class IrInterpreterCommonChecker : IrInterpreterChecker {
|
||||
private val visitedStack = mutableListOf<IrElement>()
|
||||
|
||||
private inline fun IrElement.asVisited(crossinline block: () -> Boolean): Boolean {
|
||||
@@ -42,14 +40,14 @@ class IrInterpreterCommonChecker(
|
||||
private fun visitConstructor(expression: IrFunctionAccessExpression, data: IrInterpreterCheckerData): Boolean {
|
||||
val constructor = expression.symbol.owner
|
||||
|
||||
if (!mode.canEvaluateFunction(constructor)) return false
|
||||
if (!data.mode.canEvaluateFunction(constructor)) return false
|
||||
if (!visitValueArguments(expression, data)) return false
|
||||
return visitBodyIfNeeded(constructor, data) &&
|
||||
constructor.parentAsClass.declarations.filterIsInstance<IrAnonymousInitializer>().all { it.accept(this, data) }
|
||||
}
|
||||
|
||||
private fun visitBodyIfNeeded(irFunction: IrFunction, data: IrInterpreterCheckerData): Boolean {
|
||||
if (!mode.mustCheckBodyOf(irFunction)) return true
|
||||
if (!data.mode.mustCheckBodyOf(irFunction)) return true
|
||||
return irFunction.asVisited { irFunction.body?.accept(this@IrInterpreterCommonChecker, data) ?: true }
|
||||
}
|
||||
|
||||
@@ -58,10 +56,10 @@ class IrInterpreterCommonChecker(
|
||||
}
|
||||
|
||||
override fun visitCall(expression: IrCall, data: IrInterpreterCheckerData): Boolean {
|
||||
if (!mode.canEvaluateExpression(expression)) return false
|
||||
if (!data.mode.canEvaluateExpression(expression)) return false
|
||||
|
||||
val owner = expression.symbol.owner
|
||||
if (!mode.canEvaluateFunction(owner)) return false
|
||||
if (!data.mode.canEvaluateFunction(owner)) return false
|
||||
|
||||
// We disable `toFloat` folding on K/JS till `toFloat` is fixed (KT-35422)
|
||||
// This check must be placed here instead of CallInterceptor because we still
|
||||
@@ -101,7 +99,7 @@ class IrInterpreterCommonChecker(
|
||||
}
|
||||
|
||||
override fun visitBlock(expression: IrBlock, data: IrInterpreterCheckerData): Boolean {
|
||||
if (!mode.canEvaluateBlock(expression)) return false
|
||||
if (!data.mode.canEvaluateBlock(expression)) return false
|
||||
|
||||
// `IrReturnableBlock` will be created from IrCall after inline. We should do basically the same check as for IrCall.
|
||||
if (expression is IrReturnableBlock) {
|
||||
@@ -113,7 +111,7 @@ class IrInterpreterCommonChecker(
|
||||
}
|
||||
|
||||
override fun visitComposite(expression: IrComposite, data: IrInterpreterCheckerData): Boolean {
|
||||
if (!mode.canEvaluateComposite(expression)) return false
|
||||
if (!data.mode.canEvaluateComposite(expression)) return false
|
||||
|
||||
return visitStatements(expression.statements, data)
|
||||
}
|
||||
@@ -125,7 +123,7 @@ class IrInterpreterCommonChecker(
|
||||
override fun visitConst(expression: IrConst<*>, data: IrInterpreterCheckerData): Boolean {
|
||||
if (expression.type.getUnsignedType() != null) {
|
||||
val constructor = expression.type.classOrNull?.owner?.constructors?.singleOrNull() ?: return false
|
||||
return mode.canEvaluateFunction(constructor)
|
||||
return data.mode.canEvaluateFunction(constructor)
|
||||
}
|
||||
return true
|
||||
}
|
||||
@@ -146,7 +144,7 @@ class IrInterpreterCommonChecker(
|
||||
.filterIsInstance<IrSimpleFunction>()
|
||||
.single { it.name.asString() == "toString" && it.valueParameters.isEmpty() && it.extensionReceiverParameter == null }
|
||||
|
||||
mode.canEvaluateFunction(toString) && visitBodyIfNeeded(toString, data)
|
||||
data.mode.canEvaluateFunction(toString) && visitBodyIfNeeded(toString, data)
|
||||
}
|
||||
|
||||
else -> arg.accept(this, data)
|
||||
@@ -160,7 +158,7 @@ class IrInterpreterCommonChecker(
|
||||
}
|
||||
|
||||
override fun visitGetEnumValue(expression: IrGetEnumValue, data: IrInterpreterCheckerData): Boolean {
|
||||
if (!mode.canEvaluateEnumValue(expression)) return false
|
||||
if (!data.mode.canEvaluateEnumValue(expression)) return false
|
||||
|
||||
// we want to avoid recursion in cases like "enum class E(val srt: String) { OK(OK.name) }"
|
||||
if (visitedStack.contains(expression)) return true
|
||||
@@ -242,20 +240,20 @@ class IrInterpreterCommonChecker(
|
||||
}
|
||||
|
||||
override fun visitFunctionReference(expression: IrFunctionReference, data: IrInterpreterCheckerData): Boolean {
|
||||
if (!mode.canEvaluateCallableReference(expression)) return false
|
||||
if (!data.mode.canEvaluateCallableReference(expression)) return false
|
||||
|
||||
val owner = expression.symbol.owner
|
||||
val dispatchReceiverComputable = expression.dispatchReceiver?.accept(this, data) ?: true
|
||||
val extensionReceiverComputable = expression.extensionReceiver?.accept(this, data) ?: true
|
||||
|
||||
if (!mode.canEvaluateFunction(owner)) return false
|
||||
if (!data.mode.canEvaluateFunction(owner)) return false
|
||||
|
||||
val bodyComputable = visitBodyIfNeeded(owner, data)
|
||||
return dispatchReceiverComputable && extensionReceiverComputable && bodyComputable
|
||||
}
|
||||
|
||||
override fun visitFunctionExpression(expression: IrFunctionExpression, data: IrInterpreterCheckerData): Boolean {
|
||||
if (!mode.canEvaluateFunctionExpression(expression)) return false
|
||||
if (!data.mode.canEvaluateFunctionExpression(expression)) return false
|
||||
|
||||
val body = expression.function.body ?: return false
|
||||
return expression.function.asVisited { body.accept(this, data) }
|
||||
@@ -275,7 +273,7 @@ class IrInterpreterCommonChecker(
|
||||
}
|
||||
|
||||
override fun visitWhen(expression: IrWhen, data: IrInterpreterCheckerData): Boolean {
|
||||
if (!mode.canEvaluateExpression(expression)) return false
|
||||
if (!data.mode.canEvaluateExpression(expression)) return false
|
||||
|
||||
return expression.branches.all { it.accept(this, data) }
|
||||
}
|
||||
@@ -297,7 +295,7 @@ class IrInterpreterCommonChecker(
|
||||
}
|
||||
|
||||
override fun visitTry(aTry: IrTry, data: IrInterpreterCheckerData): Boolean {
|
||||
if (!mode.canEvaluateExpression(aTry)) return false
|
||||
if (!data.mode.canEvaluateExpression(aTry)) return false
|
||||
|
||||
if (!aTry.tryResult.accept(this, data)) return false
|
||||
if (aTry.finallyExpression != null && aTry.finallyExpression?.accept(this, data) == false) return false
|
||||
@@ -314,22 +312,22 @@ class IrInterpreterCommonChecker(
|
||||
}
|
||||
|
||||
override fun visitThrow(expression: IrThrow, data: IrInterpreterCheckerData): Boolean {
|
||||
if (!mode.canEvaluateExpression(expression)) return false
|
||||
if (!data.mode.canEvaluateExpression(expression)) return false
|
||||
|
||||
return expression.value.accept(this, data)
|
||||
}
|
||||
|
||||
override fun visitPropertyReference(expression: IrPropertyReference, data: IrInterpreterCheckerData): Boolean {
|
||||
if (!mode.canEvaluateCallableReference(expression)) return false
|
||||
if (!data.mode.canEvaluateCallableReference(expression)) return false
|
||||
|
||||
val dispatchReceiverComputable = expression.dispatchReceiver?.accept(this, data) ?: true
|
||||
val extensionReceiverComputable = expression.extensionReceiver?.accept(this, data) ?: true
|
||||
|
||||
val getterIsComputable = expression.getter?.let { mode.canEvaluateFunction(it.owner) } ?: true
|
||||
val getterIsComputable = expression.getter?.let { data.mode.canEvaluateFunction(it.owner) } ?: true
|
||||
return dispatchReceiverComputable && extensionReceiverComputable && getterIsComputable
|
||||
}
|
||||
|
||||
override fun visitClassReference(expression: IrClassReference, data: IrInterpreterCheckerData): Boolean {
|
||||
return mode.canEvaluateClassReference(expression)
|
||||
return data.mode.canEvaluateClassReference(expression)
|
||||
}
|
||||
}
|
||||
+2
-4
@@ -16,14 +16,12 @@ import org.jetbrains.kotlin.ir.expressions.IrGetEnumValue
|
||||
import org.jetbrains.kotlin.ir.expressions.IrStringConcatenation
|
||||
import org.jetbrains.kotlin.ir.util.isSubclassOf
|
||||
|
||||
class IrInterpreterNameChecker(
|
||||
override val mode: EvaluationMode,
|
||||
) : IrInterpreterChecker {
|
||||
class IrInterpreterNameChecker : IrInterpreterChecker {
|
||||
override fun visitElement(element: IrElement, data: IrInterpreterCheckerData) = false
|
||||
|
||||
override fun visitCall(expression: IrCall, data: IrInterpreterCheckerData): Boolean {
|
||||
val owner = expression.symbol.owner
|
||||
if (!mode.canEvaluateFunction(owner)) return false
|
||||
if (!data.mode.canEvaluateFunction(owner)) return false
|
||||
|
||||
return expression.isKCallableNameCall(data.irBuiltIns) || expression.isEnumName()
|
||||
}
|
||||
|
||||
+4
@@ -8,8 +8,10 @@ package org.jetbrains.kotlin.ir.interpreter.preprocessor
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCallableReference
|
||||
import org.jetbrains.kotlin.ir.expressions.IrGetValue
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
|
||||
import org.jetbrains.kotlin.ir.interpreter.checker.IrInterpreterNameChecker.Companion.isKCallableNameCall
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
|
||||
// Note: this class still will not allow us to evaluate things like `A()::a.name + `A()::b.name`.
|
||||
// This code will be optimized but not completely turned into "ab" result.
|
||||
@@ -22,8 +24,10 @@ class IrInterpreterKCallableNamePreprocessor : IrInterpreterPreprocessor {
|
||||
|
||||
// receiver is needed for bound callable reference
|
||||
val receiver = callableReference.dispatchReceiver ?: callableReference.extensionReceiver ?: return expression
|
||||
|
||||
callableReference.dispatchReceiver = null
|
||||
callableReference.extensionReceiver = null
|
||||
if (receiver is IrGetValue && receiver.symbol.owner.name == SpecialNames.THIS) return expression
|
||||
|
||||
return IrCompositeImpl(
|
||||
expression.startOffset, expression.endOffset, expression.type, origin = null, statements = listOf(receiver, expression)
|
||||
|
||||
+3
-1
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
|
||||
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
|
||||
import org.jetbrains.kotlin.ir.interpreter.checker.EvaluationMode
|
||||
import org.jetbrains.kotlin.ir.interpreter.checker.IrInterpreterChecker
|
||||
import org.jetbrains.kotlin.ir.interpreter.isPrimitiveArray
|
||||
import org.jetbrains.kotlin.ir.interpreter.toIrConst
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
@@ -22,11 +23,12 @@ internal abstract class IrConstAnnotationTransformer(
|
||||
interpreter: IrInterpreter,
|
||||
irFile: IrFile,
|
||||
mode: EvaluationMode,
|
||||
checker: IrInterpreterChecker,
|
||||
evaluatedConstTracker: EvaluatedConstTracker?,
|
||||
onWarning: (IrFile, IrElement, IrErrorExpression) -> Unit,
|
||||
onError: (IrFile, IrElement, IrErrorExpression) -> Unit,
|
||||
suppressExceptions: Boolean,
|
||||
) : IrConstTransformer(interpreter, irFile, mode, evaluatedConstTracker, onWarning, onError, suppressExceptions) {
|
||||
) : IrConstTransformer(interpreter, irFile, mode, checker, evaluatedConstTracker, onWarning, onError, suppressExceptions) {
|
||||
protected fun transformAnnotations(annotationContainer: IrAnnotationContainer) {
|
||||
annotationContainer.annotations.forEach { annotation ->
|
||||
transformAnnotation(annotation)
|
||||
|
||||
+3
-2
@@ -13,20 +13,21 @@ import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationBase
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.expressions.IrErrorExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrVararg
|
||||
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
|
||||
import org.jetbrains.kotlin.ir.interpreter.checker.EvaluationMode
|
||||
import org.jetbrains.kotlin.ir.interpreter.checker.IrInterpreterChecker
|
||||
import org.jetbrains.kotlin.ir.util.primaryConstructor
|
||||
|
||||
internal class IrConstDeclarationAnnotationTransformer(
|
||||
interpreter: IrInterpreter,
|
||||
irFile: IrFile,
|
||||
mode: EvaluationMode,
|
||||
checker: IrInterpreterChecker,
|
||||
evaluatedConstTracker: EvaluatedConstTracker?,
|
||||
onWarning: (IrFile, IrElement, IrErrorExpression) -> Unit,
|
||||
onError: (IrFile, IrElement, IrErrorExpression) -> Unit,
|
||||
suppressExceptions: Boolean,
|
||||
) : IrConstAnnotationTransformer(interpreter, irFile, mode, evaluatedConstTracker, onWarning, onError, suppressExceptions) {
|
||||
) : IrConstAnnotationTransformer(interpreter, irFile, mode, checker, evaluatedConstTracker, onWarning, onError, suppressExceptions) {
|
||||
override fun visitFile(declaration: IrFile, data: Nothing?): IrFile {
|
||||
transformAnnotations(declaration)
|
||||
return super.visitFile(declaration, data)
|
||||
|
||||
+11
-5
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrStringConcatenationImpl
|
||||
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
|
||||
import org.jetbrains.kotlin.ir.interpreter.checker.EvaluationMode
|
||||
import org.jetbrains.kotlin.ir.interpreter.checker.IrInterpreterChecker
|
||||
import org.jetbrains.kotlin.ir.interpreter.createGetField
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
@@ -23,11 +24,12 @@ internal class IrConstExpressionTransformer(
|
||||
interpreter: IrInterpreter,
|
||||
irFile: IrFile,
|
||||
mode: EvaluationMode,
|
||||
checker: IrInterpreterChecker,
|
||||
evaluatedConstTracker: EvaluatedConstTracker?,
|
||||
onWarning: (IrFile, IrElement, IrErrorExpression) -> Unit,
|
||||
onError: (IrFile, IrElement, IrErrorExpression) -> Unit,
|
||||
suppressExceptions: Boolean,
|
||||
) : IrConstTransformer(interpreter, irFile, mode, evaluatedConstTracker, onWarning, onError, suppressExceptions) {
|
||||
) : IrConstTransformer(interpreter, irFile, mode, checker, evaluatedConstTracker, onWarning, onError, suppressExceptions) {
|
||||
override fun visitCall(expression: IrCall, data: Nothing?): IrElement {
|
||||
if (expression.canBeInterpreted()) {
|
||||
return expression.interpret(failAsError = false)
|
||||
@@ -55,27 +57,31 @@ internal class IrConstExpressionTransformer(
|
||||
)
|
||||
|
||||
fun IrExpression.wrapInToStringConcatAndInterpret(): IrExpression = wrapInStringConcat().interpret(failAsError = false)
|
||||
fun IrExpression.getConstStringOrEmpty(): String = if (this is IrConst<*>) value.toString() else ""
|
||||
|
||||
// If we have some complex expression in arguments (like some `IrComposite`) we will skip it,
|
||||
// but we must visit this argument in order to apply all possible optimizations.
|
||||
val transformed = super.visitStringConcatenation(expression, data) as? IrStringConcatenation ?: return expression
|
||||
// here `StringBuilder`'s list is used to optimize memory, everything works without it
|
||||
val folded = mutableListOf<IrExpression>()
|
||||
val buildersList = mutableListOf<StringBuilder>()
|
||||
for (next in expression.arguments) {
|
||||
for (next in transformed.arguments) {
|
||||
val last = folded.lastOrNull()
|
||||
when {
|
||||
!next.wrapInStringConcat().canBeInterpreted() -> {
|
||||
folded += next
|
||||
buildersList.add(StringBuilder())
|
||||
buildersList.add(StringBuilder(next.getConstStringOrEmpty()))
|
||||
}
|
||||
last == null || !last.wrapInStringConcat().canBeInterpreted() -> {
|
||||
val result = next.wrapInToStringConcatAndInterpret()
|
||||
folded += result
|
||||
buildersList.add(StringBuilder((result as? IrConst<*>)?.value?.toString() ?: ""))
|
||||
buildersList.add(StringBuilder(result.getConstStringOrEmpty()))
|
||||
}
|
||||
else -> {
|
||||
val nextAsConst = next.wrapInToStringConcatAndInterpret()
|
||||
if (nextAsConst !is IrConst<*>) {
|
||||
folded += next
|
||||
buildersList.add(StringBuilder())
|
||||
buildersList.add(StringBuilder(next.getConstStringOrEmpty()))
|
||||
} else {
|
||||
folded[folded.size - 1] = IrConstImpl.string(
|
||||
// Inlined strings may have `last.startOffset > next.endOffset`
|
||||
|
||||
+24
-25
@@ -16,18 +16,13 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
|
||||
import org.jetbrains.kotlin.ir.interpreter.IrInterpreterConfiguration
|
||||
import org.jetbrains.kotlin.ir.interpreter.checker.EvaluationMode
|
||||
import org.jetbrains.kotlin.ir.interpreter.checker.IrInterpreterCheckerData
|
||||
import org.jetbrains.kotlin.ir.interpreter.checker.IrInterpreterCommonChecker
|
||||
import org.jetbrains.kotlin.ir.interpreter.checker.IrInterpreterNameChecker
|
||||
import org.jetbrains.kotlin.ir.interpreter.checker.*
|
||||
import org.jetbrains.kotlin.ir.interpreter.preprocessor.IrInterpreterKCallableNamePreprocessor
|
||||
import org.jetbrains.kotlin.ir.interpreter.preprocessor.IrInterpreterPreprocessorData
|
||||
import org.jetbrains.kotlin.ir.interpreter.toConstantValue
|
||||
import org.jetbrains.kotlin.ir.util.dump
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||
|
||||
private val preprocessors = setOf(IrInterpreterKCallableNamePreprocessor())
|
||||
|
||||
fun IrFile.transformConst(
|
||||
interpreter: IrInterpreter,
|
||||
mode: EvaluationMode,
|
||||
@@ -36,22 +31,30 @@ fun IrFile.transformConst(
|
||||
onError: (IrFile, IrElement, IrErrorExpression) -> Unit = { _, _, _ -> },
|
||||
suppressExceptions: Boolean = false,
|
||||
) {
|
||||
val preprocessedFile = preprocessors.fold(this) { acc, preprocessor ->
|
||||
preprocessor.preprocess(acc, IrInterpreterPreprocessorData(mode, interpreter.irBuiltIns))
|
||||
val preprocessors = setOf(IrInterpreterKCallableNamePreprocessor())
|
||||
val preprocessedFile = preprocessors.fold(this) { file, preprocessor ->
|
||||
preprocessor.preprocess(file, IrInterpreterPreprocessorData(mode, interpreter.irBuiltIns))
|
||||
}
|
||||
|
||||
val irConstExpressionTransformer = IrConstExpressionTransformer(
|
||||
interpreter, preprocessedFile, mode, evaluatedConstTracker, onWarning, onError, suppressExceptions
|
||||
val checkers = setOf(
|
||||
IrInterpreterNameChecker(),
|
||||
IrInterpreterCommonChecker(),
|
||||
)
|
||||
val irConstDeclarationAnnotationTransformer = IrConstDeclarationAnnotationTransformer(
|
||||
interpreter, preprocessedFile, mode, evaluatedConstTracker, onWarning, onError, suppressExceptions
|
||||
)
|
||||
val irConstTypeAnnotationTransformer = IrConstTypeAnnotationTransformer(
|
||||
interpreter, preprocessedFile, mode, evaluatedConstTracker, onWarning, onError, suppressExceptions
|
||||
)
|
||||
preprocessedFile.transform(irConstExpressionTransformer, null)
|
||||
preprocessedFile.transform(irConstDeclarationAnnotationTransformer, null)
|
||||
preprocessedFile.transform(irConstTypeAnnotationTransformer, null)
|
||||
|
||||
checkers.fold(preprocessedFile) { file, checker ->
|
||||
val irConstExpressionTransformer = IrConstExpressionTransformer(
|
||||
interpreter, file, mode, checker, evaluatedConstTracker, onWarning, onError, suppressExceptions
|
||||
)
|
||||
val irConstDeclarationAnnotationTransformer = IrConstDeclarationAnnotationTransformer(
|
||||
interpreter, file, mode, checker, evaluatedConstTracker, onWarning, onError, suppressExceptions
|
||||
)
|
||||
val irConstTypeAnnotationTransformer = IrConstTypeAnnotationTransformer(
|
||||
interpreter, file, mode, checker, evaluatedConstTracker, onWarning, onError, suppressExceptions
|
||||
)
|
||||
file.transform(irConstExpressionTransformer, null)
|
||||
file.transform(irConstDeclarationAnnotationTransformer, null)
|
||||
file.transform(irConstTypeAnnotationTransformer, null)
|
||||
}
|
||||
}
|
||||
|
||||
// Note: We are using `IrElementTransformer` here instead of `IrElementTransformerVoid` to avoid conflicts with `IrTypeVisitorVoid`
|
||||
@@ -60,16 +63,12 @@ internal abstract class IrConstTransformer(
|
||||
protected val interpreter: IrInterpreter,
|
||||
private val irFile: IrFile,
|
||||
private val mode: EvaluationMode,
|
||||
private val checker: IrInterpreterChecker,
|
||||
private val evaluatedConstTracker: EvaluatedConstTracker? = null,
|
||||
private val onWarning: (IrFile, IrElement, IrErrorExpression) -> Unit,
|
||||
private val onError: (IrFile, IrElement, IrErrorExpression) -> Unit,
|
||||
private val suppressExceptions: Boolean,
|
||||
) : IrElementTransformer<Nothing?> {
|
||||
private val checkers = setOf(
|
||||
IrInterpreterCommonChecker(mode),
|
||||
IrInterpreterNameChecker(mode)
|
||||
)
|
||||
|
||||
private fun IrExpression.warningIfError(original: IrExpression): IrExpression {
|
||||
if (this is IrErrorExpression) {
|
||||
onWarning(irFile, original, this)
|
||||
@@ -94,7 +93,7 @@ internal abstract class IrConstTransformer(
|
||||
configuration: IrInterpreterConfiguration = interpreter.environment.configuration
|
||||
): Boolean {
|
||||
return try {
|
||||
checkers.any { this.accept(it, IrInterpreterCheckerData(interpreter.irBuiltIns, configuration)) }
|
||||
this.accept(checker, IrInterpreterCheckerData(mode, interpreter.irBuiltIns, configuration))
|
||||
} catch (e: Throwable) {
|
||||
if (suppressExceptions) {
|
||||
return false
|
||||
|
||||
+8
-4
@@ -7,22 +7,26 @@ package org.jetbrains.kotlin.ir.interpreter.transformer
|
||||
|
||||
import org.jetbrains.kotlin.constant.EvaluatedConstTracker
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.expressions.IrErrorExpression
|
||||
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
|
||||
import org.jetbrains.kotlin.ir.interpreter.checker.EvaluationMode
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.interpreter.checker.IrInterpreterChecker
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.typeOrNull
|
||||
import org.jetbrains.kotlin.ir.visitors.IrTypeTransformerVoid
|
||||
|
||||
internal class IrConstTypeAnnotationTransformer(
|
||||
interpreter: IrInterpreter,
|
||||
irFile: IrFile,
|
||||
mode: EvaluationMode,
|
||||
checker: IrInterpreterChecker,
|
||||
evaluatedConstTracker: EvaluatedConstTracker?,
|
||||
onWarning: (IrFile, IrElement, IrErrorExpression) -> Unit,
|
||||
onError: (IrFile, IrElement, IrErrorExpression) -> Unit,
|
||||
suppressExceptions: Boolean,
|
||||
) : IrConstAnnotationTransformer(interpreter, irFile, mode, evaluatedConstTracker, onWarning, onError, suppressExceptions),
|
||||
) : IrConstAnnotationTransformer(interpreter, irFile, mode, checker, evaluatedConstTracker, onWarning, onError, suppressExceptions),
|
||||
IrTypeTransformerVoid<Nothing?> {
|
||||
|
||||
override fun <Type : IrType?> transformType(container: IrElement, type: Type, data: Nothing?): Type {
|
||||
|
||||
Vendored
+3
@@ -24,9 +24,12 @@ class A {
|
||||
|
||||
val temp = A()
|
||||
val g = temp::b.<!EVALUATED("b")!>name<!>
|
||||
val insideStringConcat = "${temp::b.<!EVALUATED("b")!>name<!>}"
|
||||
|
||||
val complexExpression1 = A()::a.<!EVALUATED("a")!>name<!> + A()::b.<!EVALUATED("b")!>name<!>
|
||||
val complexExpression2 = A::a.<!EVALUATED("a")!>name<!> <!EVALUATED("ab")!>+ A::b.<!EVALUATED("b")!>name<!><!>
|
||||
|
||||
var recursive = ::test.<!EVALUATED("test")!>name<!>
|
||||
}
|
||||
|
||||
fun getA(): A = A()
|
||||
|
||||
Reference in New Issue
Block a user