Support sam conversion in ir interpreter

This commit is contained in:
Ivan Kylchik
2021-08-05 13:12:52 +03:00
committed by TeamCityServer
parent b85a796492
commit 23b315446f
12 changed files with 156 additions and 22 deletions
@@ -289,6 +289,12 @@ public class IrInterpreterAfterFir2IrTestGenerated extends AbstractIrInterpreter
runTest("compiler/testData/ir/interpreter/safeClassCast.kt"); runTest("compiler/testData/ir/interpreter/safeClassCast.kt");
} }
@Test
@TestMetadata("samConversion.kt")
public void testSamConversion() throws Exception {
runTest("compiler/testData/ir/interpreter/samConversion.kt");
}
@Test @Test
@TestMetadata("scopeFunctions.kt") @TestMetadata("scopeFunctions.kt")
public void testScopeFunctions() throws Exception { public void testScopeFunctions() throws Exception {
@@ -289,6 +289,12 @@ public class IrInterpreterAfterPsi2IrTestGenerated extends AbstractIrInterpreter
runTest("compiler/testData/ir/interpreter/safeClassCast.kt"); runTest("compiler/testData/ir/interpreter/safeClassCast.kt");
} }
@Test
@TestMetadata("samConversion.kt")
public void testSamConversion() throws Exception {
runTest("compiler/testData/ir/interpreter/samConversion.kt");
}
@Test @Test
@TestMetadata("scopeFunctions.kt") @TestMetadata("scopeFunctions.kt")
public void testScopeFunctions() throws Exception { public void testScopeFunctions() throws Exception {
@@ -11,8 +11,7 @@ import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
import org.jetbrains.kotlin.ir.interpreter.exceptions.InterpreterError import org.jetbrains.kotlin.ir.interpreter.exceptions.*
import org.jetbrains.kotlin.ir.interpreter.exceptions.InterpreterTimeOutError
import org.jetbrains.kotlin.ir.interpreter.exceptions.handleUserException import org.jetbrains.kotlin.ir.interpreter.exceptions.handleUserException
import org.jetbrains.kotlin.ir.interpreter.exceptions.verify import org.jetbrains.kotlin.ir.interpreter.exceptions.verify
import org.jetbrains.kotlin.ir.interpreter.proxy.CommonProxy.Companion.asProxy import org.jetbrains.kotlin.ir.interpreter.proxy.CommonProxy.Companion.asProxy
@@ -24,6 +23,7 @@ import org.jetbrains.kotlin.ir.interpreter.state.reflection.*
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.util.OperatorNameConventions
internal interface Instruction { internal interface Instruction {
val element: IrElement? val element: IrElement?
@@ -188,7 +188,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
if (irFunction.isLocal) callStack.copyUpValuesFromPreviousFrame() if (irFunction.isLocal) callStack.copyUpValuesFromPreviousFrame()
// 5. store arguments in memory (remap args on actual names) // 5. store arguments in memory (remap args on actual names)
irFunction.getDispatchReceiver()?.let { dispatchReceiver?.let { receiver -> callStack.addVariable(Variable(it, receiver)) } } irFunction.getDispatchReceiver()?.let { callStack.addVariable(Variable(it, dispatchReceiver!!)) }
irFunction.getExtensionReceiver()?.let { callStack.addVariable(Variable(it, extensionReceiver ?: callStack.getState(it))) } irFunction.getExtensionReceiver()?.let { callStack.addVariable(Variable(it, extensionReceiver ?: callStack.getState(it))) }
irFunction.valueParameters.forEachIndexed { i, param -> callStack.addVariable(Variable(param.symbol, valueArguments[i])) } irFunction.valueParameters.forEachIndexed { i, param -> callStack.addVariable(Variable(param.symbol, valueArguments[i])) }
// `call.type` is used in check cast and emptyArray // `call.type` is used in check cast and emptyArray
@@ -481,7 +481,29 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
else -> callStack.pushState(state) else -> callStack.pushState(state)
} }
} }
else -> TODO("${expression.operator} not implemented") IrTypeOperator.SAM_CONVERSION -> {
val newState = when {
state.isNull() -> state
state is KFunctionState -> state.apply { this.funInterface = typeOperand }
else -> {
// this case supports implicit conversion of `invoke` method from FunctionN to similar in fun interface
val samClass = typeOperand.classOrNull!!.owner
val samFunction = samClass.getSingleAbstractMethod()
val invokeFunction = state.irClass.declarations.filterIsInstance<IrFunction>()
.first { it.name == OperatorNameConventions.INVOKE && it.valueParameters.size == samFunction.valueParameters.size }
val functionClass = invokeFunction.getLastOverridden().parentAsClass
// receiver will be stored as up value
val dispatchReceiver = Variable(invokeFunction.dispatchReceiverParameter!!.symbol, state)
val newInvoke = invokeFunction.deepCopyWithSymbols(samClass).apply { dispatchReceiverParameter = null }
KFunctionState(newInvoke, functionClass, environment, mutableListOf(dispatchReceiver))
.apply { this.funInterface = typeOperand }
}
}
callStack.pushState(newState)
}
else -> stop { "Type operator ${expression.operator} is not supported for interpretation" }
} }
} }
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.ir.interpreter
import org.jetbrains.kotlin.builtins.PrimitiveType import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
@@ -272,4 +273,12 @@ internal fun IrFunctionAccessExpression.getSuperEnumCall(): IrEnumConstructorCal
is IrTypeOperatorCall -> (delegatingCall.argument as IrFunctionAccessExpression).getSuperEnumCall() is IrTypeOperatorCall -> (delegatingCall.argument as IrFunctionAccessExpression).getSuperEnumCall()
else -> TODO("$delegatingCall is unexpected") else -> TODO("$delegatingCall is unexpected")
} }
}
internal fun IrFunction.hasFunInterfaceParent(): Boolean {
return this.parentClassOrNull?.isFun == true
}
internal fun IrClass.getSingleAbstractMethod(): IrFunction {
return declarations.filterIsInstance<IrSimpleFunction>().single { it.modality == Modality.ABSTRACT }
} }
@@ -215,14 +215,12 @@ class IrCompileTimeChecker(
override fun visitTypeOperator(expression: IrTypeOperatorCall, data: Nothing?): Boolean { override fun visitTypeOperator(expression: IrTypeOperatorCall, data: Nothing?): Boolean {
return when (expression.operator) { return when (expression.operator) {
IrTypeOperator.INSTANCEOF, IrTypeOperator.NOT_INSTANCEOF, IrTypeOperator.INSTANCEOF, IrTypeOperator.NOT_INSTANCEOF,
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, IrTypeOperator.IMPLICIT_NOTNULL, IrTypeOperator.SAM_CONVERSION,
IrTypeOperator.CAST, IrTypeOperator.IMPLICIT_CAST, IrTypeOperator.SAFE_CAST, IrTypeOperator.CAST, IrTypeOperator.IMPLICIT_CAST, IrTypeOperator.SAFE_CAST -> {
IrTypeOperator.IMPLICIT_NOTNULL -> {
val operand = expression.typeOperand.classifierOrNull?.owner val operand = expression.typeOperand.classifierOrNull?.owner
if (operand is IrTypeParameter && !visitedStack.contains(operand.parent)) return false if (operand is IrTypeParameter && !visitedStack.contains(operand.parent)) return false
expression.argument.accept(this, data) expression.argument.accept(this, data)
} }
IrTypeOperator.IMPLICIT_DYNAMIC_CAST -> false
else -> false else -> false
} }
} }
@@ -7,9 +7,13 @@ package org.jetbrains.kotlin.ir.interpreter.proxy.reflection
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.interpreter.CallInterceptor import org.jetbrains.kotlin.ir.interpreter.CallInterceptor
import org.jetbrains.kotlin.ir.interpreter.exceptions.verify
import org.jetbrains.kotlin.ir.interpreter.internalName import org.jetbrains.kotlin.ir.interpreter.internalName
import org.jetbrains.kotlin.ir.interpreter.proxy.Proxy import org.jetbrains.kotlin.ir.interpreter.proxy.Proxy
import org.jetbrains.kotlin.ir.interpreter.state.State
import org.jetbrains.kotlin.ir.interpreter.state.isSubtypeOf
import org.jetbrains.kotlin.ir.interpreter.state.reflection.KClassState import org.jetbrains.kotlin.ir.interpreter.state.reflection.KClassState
import org.jetbrains.kotlin.ir.util.defaultType
import kotlin.reflect.* import kotlin.reflect.*
internal class KClassProxy( internal class KClassProxy(
@@ -60,7 +64,9 @@ internal class KClassProxy(
get() = state.classReference.isInline get() = state.classReference.isInline
override fun isInstance(value: Any?): Boolean { override fun isInstance(value: Any?): Boolean {
TODO("Not yet implemented") verify(value is State) { "Cannot interpret `isInstance` method for $value" }
// TODO fix problems with typealias and java classes subtype check
return (value as State).isSubtypeOf(state.classReference.defaultType)
} }
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
@@ -15,8 +15,10 @@ import org.jetbrains.kotlin.ir.expressions.IrReturn
import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall
import org.jetbrains.kotlin.ir.interpreter.CallInterceptor import org.jetbrains.kotlin.ir.interpreter.CallInterceptor
import org.jetbrains.kotlin.ir.interpreter.stack.Variable import org.jetbrains.kotlin.ir.interpreter.stack.Variable
import org.jetbrains.kotlin.ir.interpreter.state.hasTheSameFieldsWith
import org.jetbrains.kotlin.ir.interpreter.state.reflection.KFunctionState import org.jetbrains.kotlin.ir.interpreter.state.reflection.KFunctionState
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.types.classOrNull
import org.jetbrains.kotlin.ir.util.isSuspend import org.jetbrains.kotlin.ir.util.isSuspend
import org.jetbrains.kotlin.ir.util.statements import org.jetbrains.kotlin.ir.util.statements
import kotlin.reflect.* import kotlin.reflect.*
@@ -80,7 +82,9 @@ internal class KFunctionProxy(
if (this === other) return true if (this === other) return true
if (other !is KFunctionProxy) return false if (other !is KFunctionProxy) return false
if (arity != other.arity || isSuspend != other.isSuspend) return false if (arity != other.arity || isSuspend != other.isSuspend) return false
if (state.fields.zip(other.state.fields).any { (first, second) -> first.state !== second.state }) return false // SAM wrappers for Java do not implement equals
if (this.state.funInterface?.classOrNull?.owner?.origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB) return this.state === other.state
if (!state.hasTheSameFieldsWith(other.state)) return false
return when { return when {
state.irFunction.isAdapter() && other.state.irFunction.isAdapter() -> state.irFunction.eqaulsByAdapteeCall(other.state.irFunction) state.irFunction.isAdapter() && other.state.irFunction.isAdapter() -> state.irFunction.eqaulsByAdapteeCall(other.state.irFunction)
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.interpreter.fqName import org.jetbrains.kotlin.ir.interpreter.fqName
import org.jetbrains.kotlin.ir.interpreter.stack.CallStack import org.jetbrains.kotlin.ir.interpreter.stack.CallStack
import org.jetbrains.kotlin.ir.interpreter.stack.Variable import org.jetbrains.kotlin.ir.interpreter.stack.Variable
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
import org.jetbrains.kotlin.ir.util.overrides import org.jetbrains.kotlin.ir.util.overrides
import org.jetbrains.kotlin.ir.util.resolveFakeOverride import org.jetbrains.kotlin.ir.util.resolveFakeOverride
@@ -21,15 +20,14 @@ internal interface Complex : State {
fun irClassFqName() = irClass.fqName fun irClassFqName() = irClass.fqName
private fun getIrFunctionFromGivenClass(irClass: IrClass, symbol: IrFunctionSymbol): IrFunction? { private fun getIrFunctionFromGivenClass(irClass: IrClass, owner: IrFunction): IrFunction? {
val propertyGetters = irClass.declarations.filterIsInstance<IrProperty>().mapNotNull { it.getter } val propertyGetters = irClass.declarations.filterIsInstance<IrProperty>().mapNotNull { it.getter }
val propertySetters = irClass.declarations.filterIsInstance<IrProperty>().mapNotNull { it.setter } val propertySetters = irClass.declarations.filterIsInstance<IrProperty>().mapNotNull { it.setter }
val functions = irClass.declarations.filterIsInstance<IrFunction>() val functions = irClass.declarations.filterIsInstance<IrFunction>()
return (propertyGetters + propertySetters + functions).firstOrNull { return (propertyGetters + propertySetters + functions).firstOrNull {
val owner = symbol.owner
when { when {
it is IrSimpleFunction && owner is IrSimpleFunction -> it.overrides(owner) || owner.overrides(it) it is IrSimpleFunction && owner is IrSimpleFunction -> it.overrides(owner) || owner.overrides(it)
else -> it == symbol.owner else -> it == owner
} }
} }
} }
@@ -40,7 +38,7 @@ internal interface Complex : State {
override fun getIrFunctionByIrCall(expression: IrCall): IrFunction? { override fun getIrFunctionByIrCall(expression: IrCall): IrFunction? {
val receiver = expression.superQualifierSymbol?.owner ?: irClass val receiver = expression.superQualifierSymbol?.owner ?: irClass
val irFunction = getIrFunctionFromGivenClass(receiver, expression.symbol) ?: return null val irFunction = getIrFunctionFromGivenClass(receiver, expression.symbol.owner) ?: return null
return (irFunction as IrSimpleFunction).resolveFakeOverride() return (irFunction as IrSimpleFunction).resolveFakeOverride()
} }
@@ -63,4 +61,4 @@ internal interface Complex : State {
(variable.state as? StateWithClosure)?.let { callStack.loadUpValues(it) } (variable.state as? StateWithClosure)?.let { callStack.loadUpValues(it) }
} }
} }
} }
@@ -66,6 +66,10 @@ internal fun State.isSubtypeOf(other: IrType): Boolean {
return this.type.arraySubtypeCheck(other) return this.type.arraySubtypeCheck(other)
} }
if (other.classOrNull?.owner?.isFun == true) {
return this is KFunctionState && this.funInterface?.isSubtypeOfClass(other.classOrNull!!) == true
}
val thisType = this.irClass.defaultType val thisType = this.irClass.defaultType
if (other.isFunction() && thisType.isKFunction()/* TODO || (other.isSuspendFunction && thisType.isKSuspendFunction())*/) { if (other.isFunction() && thisType.isKFunction()/* TODO || (other.isSuspendFunction && thisType.isKSuspendFunction())*/) {
// KFunction{n} has no super type of Function{n}, // KFunction{n} has no super type of Function{n},
@@ -92,6 +96,20 @@ internal fun State.checkNullability(
} }
internal fun State?.mustBeHandledAsReflection(call: IrCall): Boolean { internal fun State?.mustBeHandledAsReflection(call: IrCall): Boolean {
if (call.symbol.owner.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER) return false val owner = call.symbol.owner
return this is ReflectionState && !(this is KFunctionState && call.symbol.owner.name == OperatorNameConventions.INVOKE) if (owner.body != null || owner.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER) return false
} return this is ReflectionState && !(this is KFunctionState && KFunctionState.isCallToInvokeOrMethodFromFunInterface(call))
}
internal fun State.hasTheSameFieldsWith(other: State): Boolean {
if (this.fields.size != other.fields.size) return false
for (i in 0 until this.fields.size) {
val firstState = this.fields[i].state
val secondState = other.fields[i].state
when {
firstState is Primitive<*> && secondState is Primitive<*> -> if (firstState.value != secondState.value) return false
else -> if (firstState !== secondState) return false
}
}
return true
}
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.ir.interpreter.state.reflection package org.jetbrains.kotlin.ir.interpreter.state.reflection
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
@@ -16,9 +17,11 @@ import org.jetbrains.kotlin.ir.interpreter.proxy.reflection.KTypeProxy
import org.jetbrains.kotlin.ir.interpreter.stack.Variable import org.jetbrains.kotlin.ir.interpreter.stack.Variable
import org.jetbrains.kotlin.ir.interpreter.state.StateWithClosure import org.jetbrains.kotlin.ir.interpreter.state.StateWithClosure
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classOrNull import org.jetbrains.kotlin.ir.types.classOrNull
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.resolveFakeOverride
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.name.SpecialNames
@@ -33,6 +36,17 @@ internal class KFunctionState(
override val fields: MutableList<Variable> = mutableListOf() override val fields: MutableList<Variable> = mutableListOf()
) : ReflectionState(), StateWithClosure { ) : ReflectionState(), StateWithClosure {
override val upValues: MutableList<Variable> = mutableListOf() override val upValues: MutableList<Variable> = mutableListOf()
var funInterface: IrType? = null
set(value) {
field = value ?: return
val samFunction = value.classOrNull!!.owner.getSingleAbstractMethod()
if (samFunction.extensionReceiverParameter != null) {
// this change of parameter is needed because of difference in `invoke` and sam calls
invokeSymbol.owner.extensionReceiverParameter = invokeSymbol.owner.valueParameters[0]
invokeSymbol.owner.valueParameters = invokeSymbol.owner.valueParameters.drop(1)
}
}
private var _parameters: List<KParameter>? = null private var _parameters: List<KParameter>? = null
private var _returnType: KType? = null private var _returnType: KType? = null
private var _typeParameters: List<KTypeParameter>? = null private var _typeParameters: List<KTypeParameter>? = null
@@ -47,7 +61,7 @@ internal class KFunctionState(
} }
companion object { companion object {
fun createInvokeFunction( private fun createInvokeFunction(
irFunction: IrFunction, irClass: IrClass, hasDispatchReceiver: Boolean, hasExtensionReceiver: Boolean irFunction: IrFunction, irClass: IrClass, hasDispatchReceiver: Boolean, hasExtensionReceiver: Boolean
): IrSimpleFunction { ): IrSimpleFunction {
val invokeFunction = irClass.declarations val invokeFunction = irClass.declarations
@@ -86,14 +100,24 @@ internal class KFunctionState(
putArgument(it, it.createGetValue()) putArgument(it, it.createGetValue())
newValueParameters += it newValueParameters += it
} }
this@impl.valueParameters = newValueParameters
} }
valueParameters = newValueParameters
body = listOf(this.createReturn(call)).wrapWithBlockBody() body = listOf(this.createReturn(call)).wrapWithBlockBody()
} }
functionClass.declarations += newFunctionToInvoke functionClass.declarations += newFunctionToInvoke
return newFunctionToInvoke return newFunctionToInvoke
} }
private fun isCallToNonAbstractMethodOfFunInterface(expression: IrCall): Boolean {
val owner = expression.symbol.owner
return owner.hasFunInterfaceParent() && owner.modality != Modality.ABSTRACT
}
fun isCallToInvokeOrMethodFromFunInterface(expression: IrCall): Boolean {
val owner = expression.symbol.owner
return owner.name == OperatorNameConventions.INVOKE || owner.hasFunInterfaceParent()
}
} }
constructor( constructor(
@@ -112,7 +136,8 @@ internal class KFunctionState(
} }
override fun getIrFunctionByIrCall(expression: IrCall): IrFunction? { override fun getIrFunctionByIrCall(expression: IrCall): IrFunction? {
if (expression.symbol.owner.name == OperatorNameConventions.INVOKE) return invokeSymbol.owner if (isCallToNonAbstractMethodOfFunInterface(expression)) return expression.symbol.owner.resolveFakeOverride()
if (isCallToInvokeOrMethodFromFunInterface(expression)) return invokeSymbol.owner
return super.getIrFunctionByIrCall(expression) return super.getIrFunctionByIrCall(expression)
} }
+10
View File
@@ -136,6 +136,16 @@ public fun <T, C : MutableCollection<in T>> Iterable<T>.toCollection(destination
return destination return destination
} }
public inline fun <T, R> Iterable<T>.map(transform: (T) -> R): List<R> {
return mapTo(ArrayList<R>(if (this is Collection<*>) this.size else 10), transform)
}
public inline fun <T, R, C : MutableCollection<in R>> Iterable<T>.mapTo(destination: C, transform: (T) -> R): C {
for (item in this)
destination.add(transform(item))
return destination
}
internal fun <T> List<T>.optimizeReadOnlyList() = when (size) { internal fun <T> List<T>.optimizeReadOnlyList() = when (size) {
0 -> emptyList() 0 -> emptyList()
1 -> listOf(this[0]) 1 -> listOf(this[0])
+32
View File
@@ -0,0 +1,32 @@
import kotlin.*
import kotlin.collections.*
@CompileTimeCalculation
fun interface IntPredicate {
fun accept(i: Int): Boolean
fun defaultMethod() = 1
}
const val isEven = IntPredicate { it % 2 == 0 }
.<!EVALUATED: `false, true, false, true, false`!>let { predicate -> listOf(1, 2, 3, 4, 5).map { predicate.accept(it) }.joinToString() }<!>
const val isOdd = IntPredicate { it % 2 != 0 }
.<!EVALUATED: `true, false, true, false, true`!>let { predicate -> listOf(1, 2, 3, 4, 5).map { predicate.accept(it) }.joinToString() }<!>
const val callToDefault = IntPredicate { false }.<!EVALUATED: `1`!>defaultMethod()<!>
const val callToString = IntPredicate { false }.<!EVALUATED: `(kotlin.Int) -> kotlin.Boolean`!>toString()<!>
@CompileTimeCalculation
fun interface KRunnable {
fun invoke(): String
}
@CompileTimeCalculation
object OK : () -> String {
override fun invoke(): String = "OK"
}
@CompileTimeCalculation
fun foo(k: KRunnable) = k.invoke()
const val invokeFromObject = <!EVALUATED: `OK`!>foo(OK)<!>
const val invokeFromFunInterface = <!EVALUATED: `OK`!>foo(KRunnable { "OK" })<!>