Make ir interpreter to work with minimal dependence on ir lowerings
This commit is contained in:
+110
-74
@@ -11,6 +11,7 @@ import kotlinx.coroutines.yield
|
|||||||
import org.jetbrains.kotlin.backend.common.interpreter.builtins.*
|
import org.jetbrains.kotlin.backend.common.interpreter.builtins.*
|
||||||
import org.jetbrains.kotlin.backend.common.interpreter.stack.*
|
import org.jetbrains.kotlin.backend.common.interpreter.stack.*
|
||||||
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
||||||
|
import org.jetbrains.kotlin.descriptors.PropertyGetterDescriptor
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
@@ -75,7 +76,9 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
is IrFunctionImpl -> interpretFunction(this, data)
|
is IrFunctionImpl -> interpretFunction(this, data)
|
||||||
is IrCall -> interpretCall(this, data)
|
is IrCall -> interpretCall(this, data)
|
||||||
is IrConstructorCall -> interpretConstructorCall(this, data)
|
is IrConstructorCall -> interpretConstructorCall(this, data)
|
||||||
|
is IrEnumConstructorCall -> interpretEnumConstructorCall(this, data)
|
||||||
is IrDelegatingConstructorCall -> interpretDelegatedConstructorCall(this, data)
|
is IrDelegatingConstructorCall -> interpretDelegatedConstructorCall(this, data)
|
||||||
|
is IrInstanceInitializerCall -> interpretInstanceInitializerCall(this, data)
|
||||||
is IrBody -> interpretBody(this, data)
|
is IrBody -> interpretBody(this, data)
|
||||||
is IrBlock -> interpretBlock(this, data)
|
is IrBlock -> interpretBlock(this, data)
|
||||||
is IrReturn -> interpretReturn(this, data)
|
is IrReturn -> interpretReturn(this, data)
|
||||||
@@ -99,6 +102,8 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
is IrCatch -> interpretCatch(this, data)
|
is IrCatch -> interpretCatch(this, data)
|
||||||
is IrThrow -> interpretThrow(this, data)
|
is IrThrow -> interpretThrow(this, data)
|
||||||
is IrStringConcatenation -> interpretStringConcatenation(this, data)
|
is IrStringConcatenation -> interpretStringConcatenation(this, data)
|
||||||
|
is IrFunctionExpression -> interpretFunctionExpression(this, data)
|
||||||
|
is IrFunctionReference -> interpretFunctionReference(this, data)
|
||||||
|
|
||||||
else -> TODO("${this.javaClass} not supported")
|
else -> TODO("${this.javaClass} not supported")
|
||||||
}
|
}
|
||||||
@@ -143,7 +148,7 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
while (cause != null) {
|
while (cause != null) {
|
||||||
for ((causeStackIndex, causeStackTraceElement) in cause.stackTrace.withIndex()) {
|
for ((causeStackIndex, causeStackTraceElement) in cause.stackTrace.withIndex()) {
|
||||||
val currentStackTraceValue = causeStackTraceElement.className + "." + causeStackTraceElement.methodName
|
val currentStackTraceValue = causeStackTraceElement.className + "." + causeStackTraceElement.methodName
|
||||||
if (currentStackTraceValue== lastNeededValue) {
|
if (currentStackTraceValue == lastNeededValue) {
|
||||||
cause.stackTrace = cause.stackTrace.sliceArray(0 until causeStackIndex).reversedArray()
|
cause.stackTrace = cause.stackTrace.sliceArray(0 until causeStackIndex).reversedArray()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -210,11 +215,13 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
data.pushReturnValue(result.toState(result.getType(irFunction.returnType)))
|
data.pushReturnValue(result.toState(result.getType(irFunction.returnType)))
|
||||||
}
|
}
|
||||||
"arrayOfNulls" -> {
|
"arrayOfNulls" -> {
|
||||||
val result = arrayOfNulls<Any?>(irFunction.getArgsForMethodInvocation(data).first() as Int)
|
val size = (data.getVariableState(irFunction.valueParameters.first().descriptor) as Primitive<*>).value as Int
|
||||||
|
val result = arrayOfNulls<Any?>(size)
|
||||||
data.pushReturnValue(result.toState(result.getType(irFunction.returnType)))
|
data.pushReturnValue(result.toState(result.getType(irFunction.returnType)))
|
||||||
}
|
}
|
||||||
"values", "enumValues" -> {
|
"values", "enumValues" -> {
|
||||||
val enumClass = irFunction.parentAsClass
|
val enumClass =
|
||||||
|
(irFunction.parent as? IrClass) ?: data.getVariableState(irFunction.typeParameters.first().descriptor).irClass
|
||||||
val enumEntries = enumClass.declarations
|
val enumEntries = enumClass.declarations
|
||||||
.filterIsInstance<IrEnumEntry>()
|
.filterIsInstance<IrEnumEntry>()
|
||||||
.map { entry ->
|
.map { entry ->
|
||||||
@@ -224,14 +231,16 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
data.pushReturnValue(enumEntries.toTypedArray().toState(irBuiltIns.arrayClass.defaultType))
|
data.pushReturnValue(enumEntries.toTypedArray().toState(irBuiltIns.arrayClass.defaultType))
|
||||||
}
|
}
|
||||||
"valueOf", "enumValueOf" -> {
|
"valueOf", "enumValueOf" -> {
|
||||||
val enumClass = irFunction.parentAsClass
|
val enumClass =
|
||||||
val enumEntryName = (data.getAll().single().state as Primitive<*>).value.toString()
|
(irFunction.parent as? IrClass) ?: data.getVariableState(irFunction.typeParameters.first().descriptor).irClass
|
||||||
|
val enumEntryName = (data.getVariableState(irFunction.valueParameters.first().descriptor) as Primitive<*>).value.toString()
|
||||||
val enumEntry = enumClass.declarations
|
val enumEntry = enumClass.declarations
|
||||||
.filterIsInstance<IrEnumEntry>()
|
.filterIsInstance<IrEnumEntry>()
|
||||||
.singleOrNull { it.name.asString() == enumEntryName }
|
.singleOrNull { it.name.asString() == enumEntryName }
|
||||||
if (enumEntry == null) {
|
if (enumEntry == null) {
|
||||||
val message = "No enum constant ${enumClass.fqNameForIrSerialization}.$enumEntryName"
|
val message = "No enum constant ${enumClass.fqNameForIrSerialization}.$enumEntryName"
|
||||||
data.pushReturnValue(ExceptionState(IllegalArgumentException(message), illegalArgumentException, stackTrace))
|
data.pushReturnValue(ExceptionState(IllegalArgumentException(message), illegalArgumentException, stackTrace))
|
||||||
|
return Code.EXCEPTION
|
||||||
} else {
|
} else {
|
||||||
enumEntry.interpret(data).also { if (it != Code.NEXT) return it }
|
enumEntry.interpret(data).also { if (it != Code.NEXT) return it }
|
||||||
}
|
}
|
||||||
@@ -289,7 +298,10 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
|
|
||||||
private suspend fun calculateBuiltIns(irFunction: IrFunction, data: Frame): Code {
|
private suspend fun calculateBuiltIns(irFunction: IrFunction, data: Frame): Code {
|
||||||
val descriptor = irFunction.descriptor
|
val descriptor = irFunction.descriptor
|
||||||
val methodName = descriptor.name.asString()
|
val methodName = when (val property = (irFunction as? IrFunctionImpl)?.correspondingPropertySymbol) {
|
||||||
|
null -> descriptor.name.asString()
|
||||||
|
else -> property.owner.name.asString()
|
||||||
|
}
|
||||||
val args = data.getAll().map { it.state }
|
val args = data.getAll().map { it.state }
|
||||||
|
|
||||||
val receiverType = descriptor.dispatchReceiverParameter?.type ?: descriptor.extensionReceiverParameter?.type
|
val receiverType = descriptor.dispatchReceiverParameter?.type ?: descriptor.extensionReceiverParameter?.type
|
||||||
@@ -370,26 +382,50 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
extensionReceiver?.let { newFrame.addVar(Variable(irFunction.symbol.getExtensionReceiver()!!, it)) }
|
extensionReceiver?.let { newFrame.addVar(Variable(irFunction.symbol.getExtensionReceiver()!!, it)) }
|
||||||
|
|
||||||
// if irFunction is lambda and it has receiver, then first descriptor must be taken from extension receiver
|
// if irFunction is lambda and it has receiver, then first descriptor must be taken from extension receiver
|
||||||
val receiverAsFirstArgument = if (irFunction.isLocalLambda()) listOfNotNull(irFunction.symbol.getExtensionReceiver()) else listOf()
|
val receiverAsFirstArgument = if (dispatchReceiver is Lambda) listOfNotNull(irFunction.symbol.getExtensionReceiver()) else listOf()
|
||||||
val valueParametersDescriptors = receiverAsFirstArgument + irFunction.descriptor.valueParameters
|
val valueParametersDescriptors = receiverAsFirstArgument + irFunction.descriptor.valueParameters
|
||||||
interpretValueParameters(expression, data).also { if (it != Code.NEXT) return it }
|
interpretValueParameters(expression, data).also { if (it != Code.NEXT) return it }
|
||||||
newFrame.addAll(valueParametersDescriptors.map { Variable(it, data.popReturnValue()) })
|
newFrame.addAll(valueParametersDescriptors.map { Variable(it, data.popReturnValue()) })
|
||||||
|
|
||||||
val isWrapper = (dispatchReceiver is Wrapper && rawExtensionReceiver == null) ||
|
irFunction.takeIf { it.isInline }?.typeParameters?.forEachIndexed { index, typeParameter ->
|
||||||
(extensionReceiver is Wrapper && rawDispatchReceiver == null)
|
if (typeParameter.isReified) {
|
||||||
|
val typeArgumentState = Common(expression.getTypeArgument(index)?.classOrNull!!.owner, mutableListOf())
|
||||||
|
newFrame.addVar(Variable(typeParameter.descriptor, typeArgumentState))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val isWrapper = dispatchReceiver is Wrapper && rawExtensionReceiver == null
|
||||||
val code = when {
|
val code = when {
|
||||||
isWrapper -> ((dispatchReceiver ?: extensionReceiver) as Wrapper).getMethod(irFunction).invokeMethod(irFunction, newFrame)
|
isWrapper -> (dispatchReceiver as Wrapper).getMethod(irFunction).invokeMethod(irFunction, newFrame)
|
||||||
irFunction.hasAnnotation(evaluateIntrinsicAnnotation) -> Wrapper.getStaticMethod(irFunction).invokeMethod(irFunction, newFrame)
|
irFunction.hasAnnotation(evaluateIntrinsicAnnotation) -> Wrapper.getStaticMethod(irFunction).invokeMethod(irFunction, newFrame)
|
||||||
irFunction.isAbstract() -> calculateAbstract(irFunction, newFrame) //abstract check must be before fake overridden check
|
irFunction.isAbstract() -> calculateAbstract(irFunction, newFrame) //abstract check must be before fake overridden check
|
||||||
irFunction.isFakeOverridden() -> calculateOverridden(irFunction as IrFunctionImpl, newFrame)
|
irFunction.isFakeOverridden() -> calculateOverridden(irFunction as IrFunctionImpl, newFrame)
|
||||||
irFunction.body == null -> calculateBuiltIns(irFunction, newFrame)
|
irFunction.body == null || dispatchReceiver is Primitive<*> -> calculateBuiltIns(irFunction, newFrame)
|
||||||
else -> irFunction.interpret(newFrame)
|
else -> irFunction.interpret(newFrame)
|
||||||
}
|
}
|
||||||
data.pushReturnValue(newFrame)
|
data.pushReturnValue(newFrame)
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun interpretInstanceInitializerCall(call: IrInstanceInitializerCall, data: Frame): Code {
|
||||||
|
val irClass = call.classSymbol.owner
|
||||||
|
|
||||||
|
val classProperties = irClass.declarations.filterIsInstance<IrProperty>()
|
||||||
|
classProperties.forEach { property ->
|
||||||
|
property.backingField?.initializer?.expression?.interpret(data)?.also { if (it != Code.NEXT) return it }
|
||||||
|
val receiver = irClass.thisReceiver!!.descriptor
|
||||||
|
if (property.backingField?.initializer != null)
|
||||||
|
property.backingField?.let { data.getVariableState(receiver).setState(Variable(it.descriptor, data.popReturnValue())) }
|
||||||
|
}
|
||||||
|
|
||||||
|
val anonymousInitializer = irClass.declarations.filterIsInstance<IrAnonymousInitializer>().filter { !it.isStatic }
|
||||||
|
anonymousInitializer.forEach { init -> init.body.interpret(data).also { if (it != Code.NEXT) return it } }
|
||||||
|
|
||||||
|
return Code.NEXT
|
||||||
|
}
|
||||||
|
|
||||||
private suspend fun interpretConstructor(constructorCall: IrFunctionAccessExpression, data: Frame): Code {
|
private suspend fun interpretConstructor(constructorCall: IrFunctionAccessExpression, data: Frame): Code {
|
||||||
|
val isPrimary = (constructorCall.symbol.owner as IrConstructor).isPrimary
|
||||||
interpretValueParameters(constructorCall, data).also { if (it != Code.NEXT) return it }
|
interpretValueParameters(constructorCall, data).also { if (it != Code.NEXT) return it }
|
||||||
val valueParameters = constructorCall.symbol.descriptor.valueParameters.map { Variable(it, data.popReturnValue()) }.toMutableList()
|
val valueParameters = constructorCall.symbol.descriptor.valueParameters.map { Variable(it, data.popReturnValue()) }.toMutableList()
|
||||||
val newFrame = InterpreterFrame(valueParameters)
|
val newFrame = InterpreterFrame(valueParameters)
|
||||||
@@ -402,23 +438,33 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
|
|
||||||
if (parent.defaultType.isArray() || parent.defaultType.isPrimitiveArray()) {
|
if (parent.defaultType.isArray() || parent.defaultType.isPrimitiveArray()) {
|
||||||
// array constructor doesn't have body so must be treated separately
|
// array constructor doesn't have body so must be treated separately
|
||||||
// here we must except only one possible constructor, with one value parameter size
|
|
||||||
// the other one, with lambda, is transforming into ir returnable block
|
|
||||||
val arrayConstructor = irBuiltIns.primitiveArrays.first().constructors.single { it.owner.valueParameters.size == 2 }
|
val arrayConstructor = irBuiltIns.primitiveArrays.first().constructors.single { it.owner.valueParameters.size == 2 }
|
||||||
val sizeDescriptor = arrayConstructor.owner.valueParameters.single { it.name.asString() == "size" }.descriptor
|
val sizeDescriptor = arrayConstructor.owner.valueParameters.single { it.name.asString() == "size" }.descriptor
|
||||||
val size = (newFrame.getVariableState(sizeDescriptor) as Primitive<Int>).value
|
val size = (newFrame.getVariableState(sizeDescriptor) as Primitive<*>).value as Int
|
||||||
|
|
||||||
|
val arrayValue = Array<Any?>(size) { 0 }
|
||||||
|
if (valueParameters.size == 2) {
|
||||||
|
val initDescriptor = arrayConstructor.owner.valueParameters.single { it.name.asString() == "init" }.descriptor
|
||||||
|
val initLambda = newFrame.getVariableState(initDescriptor) as Lambda
|
||||||
|
val indexDescriptor = initLambda.irFunction.valueParameters.single().descriptor
|
||||||
|
for (i in 0 until size) {
|
||||||
|
val lambdaFrame = InterpreterFrame(mutableListOf(Variable(indexDescriptor, i.toState(irBuiltIns.intType))))
|
||||||
|
initLambda.irFunction.body!!.interpret(lambdaFrame).also { if (it != Code.RETURN) return it }
|
||||||
|
arrayValue[i] = lambdaFrame.popReturnValue().let { (it as? Wrapper)?.value ?: (it as? Primitive<*>)?.value ?: it }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val array = when (parent.defaultType.getFqName()) {
|
val array = when (parent.defaultType.getFqName()) {
|
||||||
"kotlin.ByteArray" -> Primitive(ByteArray(size), parent.defaultType)
|
"kotlin.ByteArray" -> Primitive(ByteArray(size) { i -> (arrayValue[i] as Number).toByte() }, parent.defaultType)
|
||||||
"kotlin.CharArray" -> Primitive(CharArray(size), parent.defaultType)
|
"kotlin.CharArray" -> Primitive(CharArray(size) { i -> (arrayValue[i] as Number).toChar() }, parent.defaultType)
|
||||||
"kotlin.ShortArray" -> Primitive(ShortArray(size), parent.defaultType)
|
"kotlin.ShortArray" -> Primitive(ShortArray(size) { i -> (arrayValue[i] as Number).toShort() }, parent.defaultType)
|
||||||
"kotlin.IntArray" -> Primitive(IntArray(size), parent.defaultType)
|
"kotlin.IntArray" -> Primitive(IntArray(size) { i -> (arrayValue[i] as Number).toInt() }, parent.defaultType)
|
||||||
"kotlin.LongArray" -> Primitive(LongArray(size), parent.defaultType)
|
"kotlin.LongArray" -> Primitive(LongArray(size) { i -> (arrayValue[i] as Number).toLong() }, parent.defaultType)
|
||||||
"kotlin.FloatArray" -> Primitive(FloatArray(size), parent.defaultType)
|
"kotlin.FloatArray" -> Primitive(FloatArray(size) { i -> (arrayValue[i] as Number).toFloat() }, parent.defaultType)
|
||||||
"kotlin.DoubleArray" -> Primitive(DoubleArray(size), parent.defaultType)
|
"kotlin.DoubleArray" -> Primitive(DoubleArray(size) { i -> (arrayValue[i] as Number).toDouble() }, parent.defaultType)
|
||||||
"kotlin.BooleanArray" -> Primitive(BooleanArray(size), parent.defaultType)
|
"kotlin.BooleanArray" -> Primitive(BooleanArray(size) { i -> arrayValue[i].toString().toBoolean() }, parent.defaultType)
|
||||||
else -> throw AssertionError("Unsupported array class ${parent.defaultType.getFqName()}")
|
else -> Primitive<Array<*>>(arrayValue, parent.defaultType)
|
||||||
}
|
} as Primitive<*>
|
||||||
|
|
||||||
data.pushReturnValue(array)
|
data.pushReturnValue(array)
|
||||||
return Code.NEXT
|
return Code.NEXT
|
||||||
@@ -426,10 +472,10 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
|
|
||||||
val state = Common(parent, mutableListOf())
|
val state = Common(parent, mutableListOf())
|
||||||
newFrame.addVar(Variable(constructorCall.getThisAsReceiver(), state)) //used to set up fields in body
|
newFrame.addVar(Variable(constructorCall.getThisAsReceiver(), state)) //used to set up fields in body
|
||||||
val code = constructorCall.getBody()?.interpret(newFrame) ?: Code.NEXT
|
constructorCall.getBody()?.interpret(newFrame)?.also { if (it != Code.NEXT) return it.apply { data.pushReturnValue(newFrame) } }
|
||||||
state.superType = newFrame.popReturnValue() as Complex
|
val returnedState = newFrame.popReturnValue() as Complex
|
||||||
data.pushReturnValue(state)
|
data.pushReturnValue(if (isPrimary) state.apply { superType = returnedState } else returnedState.apply { setStatesFrom(state) })
|
||||||
return code
|
return Code.NEXT
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun interpretConstructorCall(constructorCall: IrConstructorCall, data: Frame): Code {
|
private suspend fun interpretConstructorCall(constructorCall: IrConstructorCall, data: Frame): Code {
|
||||||
@@ -439,6 +485,12 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun interpretEnumConstructorCall(enumConstructorCall: IrEnumConstructorCall, data: Frame): Code {
|
||||||
|
return interpretConstructor(enumConstructorCall, data).apply {
|
||||||
|
(data.peekReturnValue() as Complex).let { it.setInstanceRecursive(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private suspend fun interpretDelegatedConstructorCall(delegatingConstructorCall: IrDelegatingConstructorCall, data: Frame): Code {
|
private suspend fun interpretDelegatedConstructorCall(delegatingConstructorCall: IrDelegatingConstructorCall, data: Frame): Code {
|
||||||
if (delegatingConstructorCall.symbol.descriptor.containingDeclaration.defaultType == DefaultBuiltIns.Instance.anyType) {
|
if (delegatingConstructorCall.symbol.descriptor.containingDeclaration.defaultType == DefaultBuiltIns.Instance.anyType) {
|
||||||
val anyAsStateObject = Common(irBuiltIns.anyClass.owner, mutableListOf())
|
val anyAsStateObject = Common(irBuiltIns.anyClass.owner, mutableListOf())
|
||||||
@@ -458,7 +510,7 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
val newFrame = data.copy()
|
val newFrame = data.copy()
|
||||||
|
|
||||||
var code = Code.NEXT
|
var code = Code.NEXT
|
||||||
val iterator = statements.asSequence().iterator()
|
val iterator = statements.iterator()
|
||||||
while (code == Code.NEXT && iterator.hasNext()) {
|
while (code == Code.NEXT && iterator.hasNext()) {
|
||||||
code = iterator.next().interpret(newFrame)
|
code = iterator.next().interpret(newFrame)
|
||||||
}
|
}
|
||||||
@@ -467,34 +519,6 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun interpretBlock(block: IrBlock, data: Frame): Code {
|
private suspend fun interpretBlock(block: IrBlock, data: Frame): Code {
|
||||||
if (block.isLambdaFunction()) {
|
|
||||||
val irLambdaFunction = block.statements.filterIsInstance<IrFunctionReference>().first()
|
|
||||||
data.pushReturnValue(Lambda(irLambdaFunction.symbol.owner, irLambdaFunction.type.classOrNull!!.owner))
|
|
||||||
return Code.NEXT
|
|
||||||
}
|
|
||||||
|
|
||||||
val inlineFun = (block as? IrReturnableBlock)?.inlineFunctionSymbol?.owner
|
|
||||||
if (inlineFun?.hasAnnotation(evaluateIntrinsicAnnotation) == true) {
|
|
||||||
val newFrame = data.copy()
|
|
||||||
block.statements.filterIsInstance<IrVariable>().forEach { variable ->
|
|
||||||
variable.initializer!!.interpret(newFrame).also { if (it != Code.NEXT) return it }
|
|
||||||
newFrame.addVar(Variable(variable.descriptor, newFrame.popReturnValue()))
|
|
||||||
}
|
|
||||||
|
|
||||||
val originalVarToInline = ParallelVisitorForInlineFun()
|
|
||||||
.apply { this.visitElement(inlineFun.body!!.statements.first(), block.removeBlocks()!!) }
|
|
||||||
.originalVarToInline
|
|
||||||
|
|
||||||
val frameForWrapper = InterpreterFrame()
|
|
||||||
(listOfNotNull(inlineFun.extensionReceiverParameter, inlineFun.dispatchReceiverParameter) + inlineFun.valueParameters)
|
|
||||||
.map { it.descriptor }
|
|
||||||
.forEach { frameForWrapper.addVar(Variable(it, newFrame.getVariableState(originalVarToInline[it]!!))) }
|
|
||||||
|
|
||||||
return Wrapper.getStaticMethod(inlineFun)
|
|
||||||
.invokeMethod(inlineFun, frameForWrapper)
|
|
||||||
.apply { data.pushReturnValue(frameForWrapper) }
|
|
||||||
}
|
|
||||||
|
|
||||||
return interpretStatements(block.statements, data)
|
return interpretStatements(block.statements, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -591,34 +615,36 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun interpretGetObjectValue(expression: IrGetObjectValue, data: Frame): Code {
|
private suspend fun interpretGetObjectValue(expression: IrGetObjectValue, data: Frame): Code {
|
||||||
val objectState = Common(expression.symbol.owner, mutableListOf())
|
val objectState = Common(expression.symbol.owner, mutableListOf()).apply { this.instance = this }
|
||||||
val newFrame = data.copy().apply { addVar(Variable(expression.symbol.descriptor.thisAsReceiverParameter, objectState)) }
|
|
||||||
|
|
||||||
val constructor = expression.symbol.owner.declarations.single { it is IrConstructor } as IrConstructor
|
|
||||||
val constructorBody = constructor.body?.statements?.get(1) as? IrBlock
|
|
||||||
val irAnnotatedSetFields = constructorBody?.statements?.filterIsInstance<IrSetField>()
|
|
||||||
?.filter { it.symbol.owner.correspondingPropertySymbol!!.owner.hasAnnotation(compileTimeAnnotation) }
|
|
||||||
irAnnotatedSetFields?.forEach { irSetField -> irSetField.interpret(newFrame).also { if (it != Code.NEXT) return it } }
|
|
||||||
|
|
||||||
data.pushReturnValue(objectState)
|
data.pushReturnValue(objectState)
|
||||||
return Code.NEXT
|
return Code.NEXT
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun interpretGetEnumValue(expression: IrGetEnumValue, data: Frame): Code {
|
private suspend fun interpretGetEnumValue(expression: IrGetEnumValue, data: Frame): Code {
|
||||||
return interpretEnumEntry(expression.symbol.owner, data)
|
val enumEntry = expression.symbol.owner
|
||||||
|
val enumSignature = Pair(enumEntry.parentAsClass, enumEntry.name.asString())
|
||||||
|
mapOfEnums[enumSignature]?.let { return Code.NEXT.apply { data.pushReturnValue(it) } }
|
||||||
|
return interpretEnumEntry(enumEntry, data).apply {
|
||||||
|
if (this == Code.NEXT) mapOfEnums[enumSignature] = data.peekReturnValue() as Common
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun interpretEnumEntry(enumEntry: IrEnumEntry, data: Frame): Code {
|
private suspend fun interpretEnumEntry(enumEntry: IrEnumEntry, data: Frame): Code {
|
||||||
val enumSignature = Pair(enumEntry.parentAsClass, enumEntry.name.asString())
|
val enumClass = enumEntry.symbol.owner.parentAsClass
|
||||||
mapOfEnums[enumSignature]?.let {
|
val enumEntries = enumClass.declarations.filterIsInstance<IrEnumEntry>()
|
||||||
data.pushReturnValue(it)
|
|
||||||
return Code.NEXT
|
val enumSuperCall = (enumClass.primaryConstructor?.body?.statements?.firstOrNull() as? IrEnumConstructorCall)
|
||||||
|
if (enumEntries.isNotEmpty() && enumSuperCall != null) {
|
||||||
|
val valueArguments = listOf(
|
||||||
|
enumEntry.name.asString().toIrConst(irBuiltIns.stringType), enumEntries.indexOf(enumEntry).toIrConst(irBuiltIns.intType)
|
||||||
|
)
|
||||||
|
enumSuperCall.mapValueParameters { valueArguments[it.index] }
|
||||||
}
|
}
|
||||||
|
|
||||||
val code = enumEntry.initializerExpression?.interpret(data)?.also { if (it != Code.NEXT) return it }
|
val code = enumEntry.initializerExpression?.interpret(data)?.also { if (it != Code.NEXT) return it }
|
||||||
code ?: throw AssertionError("Initializer at enum entry ${enumEntry.fqNameWhenAvailable} is null")
|
enumSuperCall?.mapValueParameters { null }
|
||||||
mapOfEnums[enumSignature] = data.peekReturnValue() as Common
|
data.pushReturnValue((data.popReturnValue() as Complex))
|
||||||
return code
|
return code ?: throw AssertionError("Initializer at enum entry ${enumEntry.fqNameWhenAvailable} is null")
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun interpretTypeOperatorCall(expression: IrTypeOperatorCall, data: Frame): Code {
|
private suspend fun interpretTypeOperatorCall(expression: IrTypeOperatorCall, data: Frame): Code {
|
||||||
@@ -737,4 +763,14 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
data.pushReturnValue(result.toString().toState(expression.type))
|
data.pushReturnValue(result.toString().toState(expression.type))
|
||||||
return Code.NEXT
|
return Code.NEXT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun interpretFunctionExpression(expression: IrFunctionExpression, data: Frame): Code {
|
||||||
|
data.pushReturnValue(Lambda(expression.function, expression.type.classOrNull!!.owner))
|
||||||
|
return Code.NEXT
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun interpretFunctionReference(reference: IrFunctionReference, data: Frame): Code {
|
||||||
|
data.pushReturnValue(Lambda(reference.symbol.owner, reference.type.classOrNull!!.owner))
|
||||||
|
return Code.NEXT
|
||||||
|
}
|
||||||
}
|
}
|
||||||
-137
@@ -1,137 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2020 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.backend.common.interpreter
|
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
|
||||||
import org.jetbrains.kotlin.ir.util.statements
|
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class is used for parallel processing two ir elements and gathering information about ir temporary variables from inline block
|
|
||||||
*/
|
|
||||||
internal class ParallelVisitorForInlineFun : IrElementVisitor<Unit, IrElement> {
|
|
||||||
val originalVarToInline = mutableMapOf<DeclarationDescriptor, DeclarationDescriptor>()
|
|
||||||
|
|
||||||
override fun visitElement(element: IrElement, data: IrElement) {
|
|
||||||
element.accept(this, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitGetValue(expression: IrGetValue, data: IrElement) {
|
|
||||||
val original = expression.symbol.descriptor
|
|
||||||
val inline = (data as IrGetValue).symbol.descriptor
|
|
||||||
if (!original.equalTo(inline)) {
|
|
||||||
originalVarToInline[original] = inline
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun <T> visitConst(expression: IrConst<T>, data: IrElement) {}
|
|
||||||
|
|
||||||
override fun visitVariable(declaration: IrVariable, data: IrElement) {
|
|
||||||
declaration.initializer?.accept(this, (data as IrVariable).initializer!!)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitBody(body: IrBody, data: IrElement) {
|
|
||||||
for ((index, statement) in body.statements.withIndex()) {
|
|
||||||
statement.accept(this, (data as IrBody).statements[index])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitBlock(expression: IrBlock, data: IrElement) {
|
|
||||||
for ((index, statement) in expression.statements.withIndex()) {
|
|
||||||
statement.accept(this, (data as IrBlock).statements[index])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitStringConcatenation(expression: IrStringConcatenation, data: IrElement) {
|
|
||||||
for ((index, argument) in expression.arguments.withIndex()) {
|
|
||||||
argument.accept(this, (data as IrStringConcatenation).arguments[index])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitSetVariable(expression: IrSetVariable, data: IrElement) {
|
|
||||||
expression.value.accept(this, (data as IrSetVariable).value)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitGetField(expression: IrGetField, data: IrElement) {
|
|
||||||
expression.receiver?.accept(this, (data as IrGetField).receiver!!)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitSetField(expression: IrSetField, data: IrElement) {
|
|
||||||
expression.value.accept(this, (data as IrSetField).value)
|
|
||||||
expression.receiver?.accept(this, data.receiver!!)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitCall(expression: IrCall, data: IrElement) {
|
|
||||||
expression.dispatchReceiver?.accept(this, (data as IrCall).dispatchReceiver!!)
|
|
||||||
expression.extensionReceiver?.accept(this, (data as IrCall).extensionReceiver!!)
|
|
||||||
for (i in 0 until expression.valueArgumentsCount) {
|
|
||||||
expression.getValueArgument(i)?.accept(this, (data as IrCall).getValueArgument(i)!!)
|
|
||||||
}
|
|
||||||
expression.getBody()?.accept(this, (data as IrCall).getBody()!!)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitConstructorCall(expression: IrConstructorCall, data: IrElement) {
|
|
||||||
expression.dispatchReceiver?.accept(this, (data as IrConstructorCall).dispatchReceiver!!)
|
|
||||||
expression.extensionReceiver?.accept(this, (data as IrConstructorCall).extensionReceiver!!)
|
|
||||||
for (i in 0 until expression.valueArgumentsCount) {
|
|
||||||
expression.getValueArgument(i)?.accept(this, (data as IrConstructorCall).getValueArgument(i)!!)
|
|
||||||
}
|
|
||||||
expression.getBody()?.accept(this, (data as IrConstructorCall).getBody()!!)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall, data: IrElement) {
|
|
||||||
expression.dispatchReceiver?.accept(this, (data as IrDelegatingConstructorCall).dispatchReceiver!!)
|
|
||||||
expression.extensionReceiver?.accept(this, (data as IrDelegatingConstructorCall).extensionReceiver!!)
|
|
||||||
for (i in 0 until expression.valueArgumentsCount) {
|
|
||||||
expression.getValueArgument(i)?.accept(this, (data as IrDelegatingConstructorCall).getValueArgument(i)!!)
|
|
||||||
}
|
|
||||||
expression.getBody()?.accept(this, (data as IrDelegatingConstructorCall).getBody()!!)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitWhen(expression: IrWhen, data: IrElement) {
|
|
||||||
for ((index, branch) in expression.branches.withIndex()) {
|
|
||||||
branch.accept(this, (data as IrWhen).branches[index])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitBranch(branch: IrBranch, data: IrElement) {
|
|
||||||
branch.condition.accept(this, (data as IrBranch).condition)
|
|
||||||
branch.result.accept(this, data.result)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitLoop(loop: IrLoop, data: IrElement) {
|
|
||||||
loop.condition.accept(this, (data as IrLoop).condition)
|
|
||||||
loop.body?.accept(this, data.body!!)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitTry(aTry: IrTry, data: IrElement) {
|
|
||||||
aTry.tryResult.accept(this, (data as IrTry).tryResult)
|
|
||||||
for ((index, catch) in aTry.catches.withIndex()) {
|
|
||||||
catch.accept(this, data.catches[index])
|
|
||||||
}
|
|
||||||
aTry.finallyExpression?.accept(this, data.finallyExpression!!)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitCatch(aCatch: IrCatch, data: IrElement) {
|
|
||||||
aCatch.catchParameter.accept(this, (data as IrCatch).catchParameter)
|
|
||||||
aCatch.result.accept(this, data.result)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitReturn(expression: IrReturn, data: IrElement) {
|
|
||||||
expression.value.accept(this, (data as IrReturn).value)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitThrow(expression: IrThrow, data: IrElement) {
|
|
||||||
expression.value.accept(this, (data as IrThrow).value)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitTypeOperator(expression: IrTypeOperatorCall, data: IrElement) {
|
|
||||||
expression.argument.accept(this, (data as IrTypeOperatorCall).argument)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+5
-11
@@ -59,7 +59,9 @@ private fun DeclarationDescriptor.isSubtypeOf(other: DeclarationDescriptor): Boo
|
|||||||
|
|
||||||
private fun DeclarationDescriptor.hasSameNameAs(other: DeclarationDescriptor): Boolean {
|
private fun DeclarationDescriptor.hasSameNameAs(other: DeclarationDescriptor): Boolean {
|
||||||
return (this is VariableDescriptor && other is VariableDescriptor && this.name == other.name) ||
|
return (this is VariableDescriptor && other is VariableDescriptor && this.name == other.name) ||
|
||||||
(this is FunctionInvokeDescriptor && other is FunctionInvokeDescriptor && this.valueParameters.size == other.valueParameters.size)
|
(this is FunctionDescriptor && other is FunctionDescriptor &&
|
||||||
|
this.valueParameters.map { it.type.toString() } == other.valueParameters.map { it.type.toString() } &&
|
||||||
|
this.name == other.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun IrCall.isAbstract(): Boolean {
|
fun IrCall.isAbstract(): Boolean {
|
||||||
@@ -71,19 +73,11 @@ fun IrCall.isFakeOverridden(): Boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun IrFunction.isAbstract(): Boolean {
|
fun IrFunction.isAbstract(): Boolean {
|
||||||
return (this.symbol.owner as? IrSimpleFunction)?.modality == Modality.ABSTRACT
|
return (this as? IrSimpleFunction)?.modality == Modality.ABSTRACT
|
||||||
}
|
}
|
||||||
|
|
||||||
fun IrFunction.isFakeOverridden(): Boolean {
|
fun IrFunction.isFakeOverridden(): Boolean {
|
||||||
return this.symbol.owner.isFakeOverride
|
return this.isFakeOverride
|
||||||
}
|
|
||||||
|
|
||||||
fun IrContainerExpression.isLambdaFunction(): Boolean {
|
|
||||||
return this.origin == IrStatementOrigin.LAMBDA || this.origin == IrStatementOrigin.ANONYMOUS_FUNCTION
|
|
||||||
}
|
|
||||||
|
|
||||||
fun IrDeclaration.isLocalLambda(): Boolean {
|
|
||||||
return this.origin == IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun State.toIrExpression(expression: IrExpression): IrExpression {
|
fun State.toIrExpression(expression: IrExpression): IrExpression {
|
||||||
|
|||||||
+1
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.name.FqName
|
|||||||
|
|
||||||
val compileTimeAnnotation = FqName("kotlin.CompileTimeCalculation")
|
val compileTimeAnnotation = FqName("kotlin.CompileTimeCalculation")
|
||||||
val evaluateIntrinsicAnnotation = FqName("kotlin.EvaluateIntrinsic")
|
val evaluateIntrinsicAnnotation = FqName("kotlin.EvaluateIntrinsic")
|
||||||
|
val contractsDslAnnotation = FqName("kotlin.internal.ContractsDsl")
|
||||||
|
|
||||||
data class CompileTimeFunction(val methodName: String, val args: List<String>)
|
data class CompileTimeFunction(val methodName: String, val args: List<String>)
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -121,8 +121,8 @@ val unaryFunctions = mapOf<CompileTimeFunction, Function1<Any?, Any?>>(
|
|||||||
unaryOperation<Any>("hashCode", "Any") { a -> a.hashCode() },
|
unaryOperation<Any>("hashCode", "Any") { a -> a.hashCode() },
|
||||||
unaryOperation<Any>("toString", "Any") { a -> a.defaultToString() },
|
unaryOperation<Any>("toString", "Any") { a -> a.defaultToString() },
|
||||||
unaryOperation<Any?>("CHECK_NOT_NULL", "T0?") { a -> a!! },
|
unaryOperation<Any?>("CHECK_NOT_NULL", "T0?") { a -> a!! },
|
||||||
unaryOperation<ExceptionState>("<get-message>", "Throwable") { a -> a.getMessage() },
|
unaryOperation<ExceptionState>("message", "Throwable") { a -> a.getMessage() },
|
||||||
unaryOperation<ExceptionState>("<get-cause>", "Throwable") { a -> a.getCause() }
|
unaryOperation<ExceptionState>("cause", "Throwable") { a -> a.getCause() }
|
||||||
)
|
)
|
||||||
|
|
||||||
val binaryFunctions = mapOf<CompileTimeFunction, Function2<Any?, Any?, Any?>>(
|
val binaryFunctions = mapOf<CompileTimeFunction, Function2<Any?, Any?, Any?>>(
|
||||||
|
|||||||
+12
-14
@@ -12,10 +12,13 @@ import org.jetbrains.kotlin.backend.common.interpreter.builtins.unaryFunctions
|
|||||||
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.PropertyGetterDescriptor
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrGetValue
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.*
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
@@ -51,16 +54,8 @@ class Primitive<T>(var value: T, val type: IrType) : State {
|
|||||||
override val fields: MutableList<Variable> = mutableListOf()
|
override val fields: MutableList<Variable> = mutableListOf()
|
||||||
override val irClass: IrClass = type.classOrNull!!.owner
|
override val irClass: IrClass = type.classOrNull!!.owner
|
||||||
|
|
||||||
init {
|
override fun getState(descriptor: DeclarationDescriptor): State {
|
||||||
if (value != null) {
|
return super.getState(descriptor) ?: this
|
||||||
val properties = irClass.declarations.filterIsInstance<IrProperty>()
|
|
||||||
for (property in properties) {
|
|
||||||
val propertySignature = CompileTimeFunction(property.name.asString(), listOf(irClass.descriptor.defaultType.toString()))
|
|
||||||
val propertyValue = unaryFunctions[propertySignature]?.invoke(value)
|
|
||||||
?: throw NoSuchMethodException("For given property $propertySignature there is no entry in unary map")
|
|
||||||
fields.add(Variable(property.descriptor, Primitive(propertyValue, property.backingField!!.type)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setState(newVar: Variable) {
|
override fun setState(newVar: Variable) {
|
||||||
@@ -129,10 +124,13 @@ abstract class Complex(override val irClass: IrClass, override val fields: Mutab
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setStatesFrom(state: Complex) = state.fields.forEach { setState(it) }
|
||||||
|
|
||||||
override fun getIrFunction(descriptor: FunctionDescriptor): IrFunction? {
|
override fun getIrFunction(descriptor: FunctionDescriptor): IrFunction? {
|
||||||
return irClass.declarations.filterIsInstance<IrFunction>()
|
if (descriptor is PropertyGetterDescriptor)
|
||||||
.filter { it.descriptor.name == descriptor.name }
|
return irClass.declarations.filterIsInstance<IrProperty>().mapNotNull { it.getter }.single { it.descriptor.equalTo(descriptor) }
|
||||||
.firstOrNull { it.descriptor.valueParameters.map { it.type } == descriptor.valueParameters.map { it.type } }
|
|
||||||
|
return irClass.declarations.filterIsInstance<IrFunction>().singleOrNull { it.descriptor.equalTo(descriptor) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,7 +272,7 @@ class Wrapper(val value: Any, override val irClass: IrClass) : Complex(irClass,
|
|||||||
|
|
||||||
class Lambda(val irFunction: IrFunction, override val irClass: IrClass) : Complex(irClass, mutableListOf()) {
|
class Lambda(val irFunction: IrFunction, override val irClass: IrClass) : Complex(irClass, mutableListOf()) {
|
||||||
// irFunction is anonymous declaration, but irCall will contain descriptor of invoke method from Function interface
|
// irFunction is anonymous declaration, but irCall will contain descriptor of invoke method from Function interface
|
||||||
private val invokeDescriptor = irClass.declarations.first().descriptor
|
private val invokeDescriptor = irClass.declarations.single { it.nameForIrSerialization.asString() == "invoke" }.descriptor
|
||||||
|
|
||||||
override fun setState(newVar: Variable) {
|
override fun setState(newVar: Variable) {
|
||||||
throw UnsupportedOperationException("Method setState is not supported in Lambda class")
|
throw UnsupportedOperationException("Method setState is not supported in Lambda class")
|
||||||
|
|||||||
@@ -151,8 +151,8 @@ private fun generateUnaryBody(unaryOperationsMap: Map<CallableDescriptor, Pair<S
|
|||||||
" unaryOperation${parameters.first}(\"$methodName\", ${parameters.second}) { a -> $body }"
|
" unaryOperation${parameters.first}(\"$methodName\", ${parameters.second}) { a -> $body }"
|
||||||
} +
|
} +
|
||||||
" unaryOperation<Any?>(\"${irNullCheck.name}\", \"${irNullCheck.valueParameters.first().type}\") { a -> a!! },\n" +
|
" unaryOperation<Any?>(\"${irNullCheck.name}\", \"${irNullCheck.valueParameters.first().type}\") { a -> a!! },\n" +
|
||||||
" unaryOperation<ExceptionState>(\"<get-message>\", \"Throwable\") { a -> a.getMessage() },\n" +
|
" unaryOperation<ExceptionState>(\"message\", \"Throwable\") { a -> a.getMessage() },\n" +
|
||||||
" unaryOperation<ExceptionState>(\"<get-cause>\", \"Throwable\") { a -> a.getCause() }"
|
" unaryOperation<ExceptionState>(\"cause\", \"Throwable\") { a -> a.getCause() }"
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateBinaryBody(
|
private fun generateBinaryBody(
|
||||||
|
|||||||
Reference in New Issue
Block a user