Add synthetic function in interpreter for default args evaluation
This commit is contained in:
committed by
TeamCityServer
parent
7852d01da6
commit
10efbeb0c9
+2
-1
@@ -66,9 +66,10 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) :
|
|||||||
|
|
||||||
override fun interceptCall(call: IrCall, irFunction: IrFunction, args: List<State>, defaultAction: () -> Unit) {
|
override fun interceptCall(call: IrCall, irFunction: IrFunction, args: List<State>, defaultAction: () -> Unit) {
|
||||||
val isInlineOnly = irFunction.hasAnnotation(FqName("kotlin.internal.InlineOnly"))
|
val isInlineOnly = irFunction.hasAnnotation(FqName("kotlin.internal.InlineOnly"))
|
||||||
|
val isSyntheticDefault = irFunction.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER
|
||||||
val receiver = if (irFunction.dispatchReceiverParameter != null) args[0] else null
|
val receiver = if (irFunction.dispatchReceiverParameter != null) args[0] else null
|
||||||
when {
|
when {
|
||||||
receiver is Wrapper && !isInlineOnly -> receiver.getMethod(irFunction).invokeMethod(irFunction, args)
|
receiver is Wrapper && !isInlineOnly && !isSyntheticDefault -> receiver.getMethod(irFunction).invokeMethod(irFunction, args)
|
||||||
Wrapper.mustBeHandledWithWrapper(irFunction) -> Wrapper.getStaticMethod(irFunction).invokeMethod(irFunction, args)
|
Wrapper.mustBeHandledWithWrapper(irFunction) -> Wrapper.getStaticMethod(irFunction).invokeMethod(irFunction, args)
|
||||||
handleIntrinsicMethods(irFunction) -> return
|
handleIntrinsicMethods(irFunction) -> return
|
||||||
receiver.mustBeHandledAsReflection(call) -> Wrapper.getReflectionMethod(irFunction).invokeMethod(irFunction, args)
|
receiver.mustBeHandledAsReflection(call) -> Wrapper.getReflectionMethod(irFunction).invokeMethod(irFunction, args)
|
||||||
|
|||||||
+144
-70
@@ -5,24 +5,32 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.ir.interpreter
|
package org.jetbrains.kotlin.ir.interpreter
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||||
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
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.UNDEFINED_OFFSET
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetObjectValueImpl
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
|
||||||
import org.jetbrains.kotlin.ir.interpreter.exceptions.InterpreterError
|
import org.jetbrains.kotlin.ir.interpreter.exceptions.InterpreterError
|
||||||
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.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.interpreter.state.*
|
import org.jetbrains.kotlin.ir.interpreter.state.*
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
|
||||||
import org.jetbrains.kotlin.ir.types.classOrNull
|
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||||
|
import org.jetbrains.kotlin.ir.types.isSubtypeOf
|
||||||
import org.jetbrains.kotlin.ir.types.isUnit
|
import org.jetbrains.kotlin.ir.types.isUnit
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
internal fun IrExpression.handleAndDropResult(callStack: CallStack, dropOnlyUnit: Boolean = false) {
|
internal fun IrExpression.handleAndDropResult(callStack: CallStack, dropOnlyUnit: Boolean = false) {
|
||||||
val dropResult = fun() {
|
val dropResult = fun() {
|
||||||
@@ -38,10 +46,10 @@ internal fun unfoldInstruction(element: IrElement?, environment: IrInterpreterEn
|
|||||||
null -> return
|
null -> return
|
||||||
is IrSimpleFunction -> unfoldFunction(element, environment)
|
is IrSimpleFunction -> unfoldFunction(element, environment)
|
||||||
is IrConstructor -> unfoldConstructor(element, callStack)
|
is IrConstructor -> unfoldConstructor(element, callStack)
|
||||||
is IrCall -> unfoldCall(element, callStack)
|
is IrCall -> unfoldCall(element, environment)
|
||||||
is IrConstructorCall -> unfoldConstructorCall(element, callStack)
|
is IrConstructorCall -> unfoldConstructorCall(element, environment)
|
||||||
is IrEnumConstructorCall -> unfoldConstructorCall(element, callStack)
|
is IrEnumConstructorCall -> unfoldConstructorCall(element, environment)
|
||||||
is IrDelegatingConstructorCall -> unfoldConstructorCall(element, callStack)
|
is IrDelegatingConstructorCall -> unfoldConstructorCall(element, environment)
|
||||||
is IrInstanceInitializerCall -> unfoldInstanceInitializerCall(element, callStack)
|
is IrInstanceInitializerCall -> unfoldInstanceInitializerCall(element, callStack)
|
||||||
is IrField -> unfoldField(element, callStack)
|
is IrField -> unfoldField(element, callStack)
|
||||||
is IrBody -> unfoldBody(element, callStack)
|
is IrBody -> unfoldBody(element, callStack)
|
||||||
@@ -109,81 +117,147 @@ private fun unfoldConstructor(constructor: IrConstructor, callStack: CallStack)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun unfoldCall(call: IrCall, callStack: CallStack) {
|
private fun unfoldCall(call: IrCall, environment: IrInterpreterEnvironment) {
|
||||||
unfoldValueParameters(call, callStack)
|
unfoldValueParameters(call, environment)
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function is responsible for IrConstructorCall, IrDelegatingConstructorCall and IrEnumConstructorCall
|
// This function is responsible for IrConstructorCall, IrDelegatingConstructorCall and IrEnumConstructorCall
|
||||||
private fun unfoldConstructorCall(constructorCall: IrFunctionAccessExpression, callStack: CallStack) {
|
private fun unfoldConstructorCall(constructorCall: IrFunctionAccessExpression, environment: IrInterpreterEnvironment) {
|
||||||
unfoldValueParameters(constructorCall, callStack)
|
unfoldValueParameters(constructorCall, environment)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun unfoldValueParameters(expression: IrFunctionAccessExpression, callStack: CallStack) {
|
private fun unfoldValueParameters(expression: IrFunctionAccessExpression, environment: IrInterpreterEnvironment) {
|
||||||
|
val callStack = environment.callStack
|
||||||
val irFunction = expression.symbol.owner
|
val irFunction = expression.symbol.owner
|
||||||
// new sub frame is used to store value arguments, in case then they are used in default args evaluation
|
|
||||||
callStack.newSubFrame(expression)
|
|
||||||
callStack.addInstruction(SimpleInstruction(expression))
|
|
||||||
|
|
||||||
fun getDefaultForParameterAt(index: Int): IrExpression? {
|
val hasDefaults = (0 until expression.valueArgumentsCount).any { expression.getValueArgument(it) == null }
|
||||||
fun IrExpressionBody.replaceGetValueFromOtherClass(): IrExpressionBody {
|
if (hasDefaults) {
|
||||||
return this.deepCopyWithSymbols(irFunction).transform(
|
val visibility = if (expression is IrEnumConstructorCall || expression is IrDelegatingConstructorCall) DescriptorVisibilities.LOCAL else irFunction.visibility
|
||||||
object : IrElementTransformerVoid() {
|
val defaultFun = IrFunctionImpl(
|
||||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER,
|
||||||
val parameter = expression.symbol.owner as? IrValueParameter ?: return super.visitGetValue(expression)
|
IrSimpleFunctionSymbolImpl(), Name.identifier(irFunction.name.asString() + "\$default"),
|
||||||
if (parameter.parent == irFunction) return super.visitGetValue(expression)
|
visibility, Modality.FINAL, irFunction.returnType,
|
||||||
val newParameter = when (val indexInParameters = parameter.index) {
|
isInline = false, isExternal = false, isTailrec = false, isSuspend = false, isOperator = true, isInfix = false, isExpect = false
|
||||||
-1 -> (irFunction.dispatchReceiverParameter ?: irFunction.extensionReceiverParameter)!!
|
)
|
||||||
else -> irFunction.valueParameters[indexInParameters]
|
defaultFun.parent = irFunction.parent
|
||||||
|
expression.dispatchReceiver?.let {
|
||||||
|
defaultFun.dispatchReceiverParameter = irFunction.dispatchReceiverParameter!!//.deepCopyWithSymbols(defaultFun)
|
||||||
|
}
|
||||||
|
expression.extensionReceiver?.let {
|
||||||
|
defaultFun.extensionReceiverParameter = irFunction.extensionReceiverParameter!!//.deepCopyWithSymbols(defaultFun)
|
||||||
|
}
|
||||||
|
val parameters = mutableListOf<IrValueDeclaration>()
|
||||||
|
(0 until expression.valueArgumentsCount).forEach {
|
||||||
|
if (expression.getValueArgument(it) != null) {
|
||||||
|
val param = irFunction.valueParameters[it]//.deepCopyWithSymbols(defaultFun)
|
||||||
|
defaultFun.valueParameters += param
|
||||||
|
parameters += param
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val callToDefault = IrCallImpl.fromSymbolOwner(UNDEFINED_OFFSET, UNDEFINED_OFFSET, defaultFun.returnType, defaultFun.symbol)
|
||||||
|
expression.dispatchReceiver?.let {
|
||||||
|
callToDefault.dispatchReceiver = it
|
||||||
|
}
|
||||||
|
expression.extensionReceiver?.let {
|
||||||
|
callToDefault.extensionReceiver = it
|
||||||
|
}
|
||||||
|
var index = 0
|
||||||
|
(0 until expression.valueArgumentsCount).forEach {
|
||||||
|
if (expression.getValueArgument(it) != null) {
|
||||||
|
callToDefault.putValueArgument(index++, expression.getValueArgument(it))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getDefaultForParameterAt(index: Int): IrExpression? {
|
||||||
|
fun IrExpressionBody.replaceGetValueFromOtherClass(owner: IrFunction): IrExpressionBody {
|
||||||
|
if (this.expression is IrConst<*>) return this
|
||||||
|
return this.deepCopyWithSymbols(owner).transform(
|
||||||
|
object : IrElementTransformerVoid() {
|
||||||
|
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||||
|
val parameter = expression.symbol.owner as? IrValueParameter ?: return super.visitGetValue(expression)
|
||||||
|
if (parameter.parent != owner) return super.visitGetValue(expression)
|
||||||
|
val newParameter = when (val indexInParameters = parameter.index) {
|
||||||
|
-1 -> (irFunction.dispatchReceiverParameter ?: irFunction.extensionReceiverParameter)!!
|
||||||
|
else -> parameters[indexInParameters]//parameters[indexInParameters]
|
||||||
|
}
|
||||||
|
return IrGetValueImpl(expression.startOffset, expression.endOffset, expression.type, newParameter.symbol)
|
||||||
}
|
}
|
||||||
return IrGetValueImpl(expression.startOffset, expression.endOffset, expression.type, newParameter.symbol)
|
}, null
|
||||||
}
|
)//.deepCopyWithSymbols(defaultFun) TODO ???
|
||||||
}, null
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun IrValueParameter.getDefault(): IrExpressionBody? {
|
|
||||||
if (defaultValue != null) return defaultValue
|
|
||||||
val overriddenDefault = (this.parent as? IrSimpleFunction)?.overriddenSymbols
|
|
||||||
?.map { it.owner.valueParameters[this.index] }
|
|
||||||
?.firstNotNullOfOrNull { it.getDefault() }
|
|
||||||
|
|
||||||
if (overriddenDefault == null || overriddenDefault.expression is IrConst<*>) return overriddenDefault
|
|
||||||
|
|
||||||
return overriddenDefault.replaceGetValueFromOtherClass()
|
|
||||||
}
|
|
||||||
|
|
||||||
return irFunction.valueParameters[index].getDefault()?.expression
|
|
||||||
}
|
|
||||||
|
|
||||||
val valueParametersSymbols = irFunction.valueParameters.map { it.symbol }
|
|
||||||
|
|
||||||
// evaluate arguments
|
|
||||||
(expression.valueArgumentsCount - 1 downTo 0).forEach { index ->
|
|
||||||
when {
|
|
||||||
expression.getValueArgument(index) != null -> {
|
|
||||||
// interpret arguments that were passed
|
|
||||||
callStack.addInstruction(SimpleInstruction(irFunction.valueParameters[index]))
|
|
||||||
callStack.addInstruction(CompoundInstruction(expression.getValueArgument(index)))
|
|
||||||
}
|
}
|
||||||
else -> {
|
|
||||||
// interpret defaults for null arguments
|
|
||||||
callStack.addInstruction(SimpleInstruction(valueParametersSymbols[index].owner))
|
|
||||||
|
|
||||||
getDefaultForParameterAt(index)
|
fun IrValueParameter.getDefault(): IrExpressionBody? {
|
||||||
?.let { callStack.addInstruction(CompoundInstruction(it)) }
|
if (defaultValue != null) return defaultValue?.replaceGetValueFromOtherClass(this.parent as IrFunction)
|
||||||
?: expression.getVarargType(index)?.let { // case when value parameter is vararg and it is missing
|
return (this.parent as? IrSimpleFunction)?.overriddenSymbols
|
||||||
callStack.addInstruction(SimpleInstruction(IrConstImpl.constNull(UNDEFINED_OFFSET, UNDEFINED_OFFSET, it)))
|
?.map { it.owner.valueParameters[this.index] }
|
||||||
}
|
?.firstOrNull { it.getDefault() != null }?.let { it.getDefault()?.replaceGetValueFromOtherClass(it.parent as IrFunction) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return irFunction.valueParameters[index].getDefault()?.expression
|
||||||
}
|
}
|
||||||
}
|
|
||||||
expression.extensionReceiver?.let {
|
val newExpression = when (expression) {
|
||||||
callStack.addInstruction(SimpleInstruction(irFunction.extensionReceiverParameter!!))
|
is IrCall -> IrCallImpl.fromSymbolOwner(expression.startOffset, expression.endOffset, expression.type, expression.symbol)
|
||||||
callStack.addInstruction(CompoundInstruction(it))
|
is IrConstructorCall -> IrConstructorCallImpl.fromSymbolOwner(expression.type, expression.symbol)
|
||||||
}
|
is IrDelegatingConstructorCall -> IrDelegatingConstructorCallImpl(0, 0, expression.type, expression.symbol, expression.typeArgumentsCount, expression.valueArgumentsCount)
|
||||||
expression.dispatchReceiver?.let {
|
is IrEnumConstructorCall -> IrEnumConstructorCallImpl(0, 0, expression.type, expression.symbol, expression.typeArgumentsCount, expression.valueArgumentsCount)
|
||||||
callStack.addInstruction(SimpleInstruction(irFunction.dispatchReceiverParameter!!))
|
else -> TODO()
|
||||||
callStack.addInstruction(CompoundInstruction(it))
|
}
|
||||||
|
|
||||||
|
expression.dispatchReceiver?.let {
|
||||||
|
newExpression.dispatchReceiver = IrGetValueImpl(0, 0, defaultFun.dispatchReceiverParameter!!.type, defaultFun.dispatchReceiverParameter!!.symbol)
|
||||||
|
}
|
||||||
|
expression.extensionReceiver?.let {
|
||||||
|
newExpression.extensionReceiver = IrGetValueImpl(0, 0, defaultFun.extensionReceiverParameter!!.type, defaultFun.extensionReceiverParameter!!.symbol)
|
||||||
|
}
|
||||||
|
val variablesForDefault = mutableListOf<IrVariable>()
|
||||||
|
index = 0
|
||||||
|
(0 until expression.valueArgumentsCount).forEach {
|
||||||
|
val arg = if (expression.getValueArgument(it) != null) {
|
||||||
|
IrGetValueImpl(0, 0, defaultFun.valueParameters[index].type, defaultFun.valueParameters[index++].symbol)
|
||||||
|
} else {
|
||||||
|
val init = getDefaultForParameterAt(it)
|
||||||
|
?: expression.getVarargType(it)?.let { // case when value parameter is vararg and it is missing
|
||||||
|
IrConstImpl.constNull(UNDEFINED_OFFSET, UNDEFINED_OFFSET, it)
|
||||||
|
}
|
||||||
|
val variable = IrVariableImpl(
|
||||||
|
0, 0, IrDeclarationOrigin.IR_TEMPORARY_VARIABLE, IrVariableSymbolImpl(),
|
||||||
|
irFunction.valueParameters[it].name, irFunction.valueParameters[it].type, isVar = false, isConst = false, isLateinit = false
|
||||||
|
)
|
||||||
|
variablesForDefault += variable
|
||||||
|
parameters += variable
|
||||||
|
variable.initializer = init
|
||||||
|
IrGetValueImpl(0, 0, variable.type, variable.symbol)
|
||||||
|
|
||||||
|
}
|
||||||
|
newExpression.putValueArgument(it, arg)
|
||||||
|
}
|
||||||
|
(0 until expression.typeArgumentsCount).forEach {
|
||||||
|
newExpression.putTypeArgument(it, expression.getTypeArgument(it))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
defaultFun.body = IrBlockBodyImpl(
|
||||||
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||||
|
variablesForDefault + IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, defaultFun.returnType, defaultFun.symbol, newExpression)
|
||||||
|
)
|
||||||
|
|
||||||
|
callStack.addInstruction(CompoundInstruction(callToDefault))
|
||||||
|
} else {
|
||||||
|
// new sub frame is used to store value arguments, in case then they are used in default args evaluation
|
||||||
|
callStack.newSubFrame(expression) // TODO drop
|
||||||
|
callStack.addInstruction(SimpleInstruction(expression))
|
||||||
|
|
||||||
|
fun IrValueParameter.schedule(arg: IrExpression?) {
|
||||||
|
callStack.addInstruction(SimpleInstruction(this))
|
||||||
|
callStack.addInstruction(CompoundInstruction(arg))
|
||||||
|
}
|
||||||
|
(expression.valueArgumentsCount - 1 downTo 0).forEach {
|
||||||
|
irFunction.valueParameters[it].schedule(expression.getValueArgument(it))
|
||||||
|
}
|
||||||
|
expression.extensionReceiver?.let { irFunction.extensionReceiverParameter!!.schedule(it) }
|
||||||
|
expression.dispatchReceiver?.let { irFunction.dispatchReceiverParameter!!.schedule(it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -159,9 +159,6 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
|||||||
IllegalArgumentException("Parameter specified as non-null is null: method $method, parameter $parameter")
|
IllegalArgumentException("Parameter specified as non-null is null: method $method, parameter $parameter")
|
||||||
} ?: return
|
} ?: return
|
||||||
|
|
||||||
//must add value argument in current stack because it can be used later as default argument
|
|
||||||
callStack.addVariable(Variable(valueParameter.symbol, state))
|
|
||||||
|
|
||||||
// outer classes can be used in default args evaluation
|
// outer classes can be used in default args evaluation
|
||||||
if (isReceiver() && state is Complex) state.loadOuterClassesInto(callStack)
|
if (isReceiver() && state is Complex) state.loadOuterClassesInto(callStack)
|
||||||
callStack.pushState(state)
|
callStack.pushState(state)
|
||||||
@@ -177,7 +174,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
|||||||
|
|
||||||
val owner = call.symbol.owner
|
val owner = call.symbol.owner
|
||||||
// 1. load evaluated arguments from stack
|
// 1. load evaluated arguments from stack
|
||||||
val valueArguments = owner.valueParameters.map { callStack.popState() }.reversed().toMutableList()
|
val valueArguments = owner.valueParameters.map { callStack.popState() }.reversed()
|
||||||
val extensionReceiver = owner.getExtensionReceiver()?.let { callStack.popState() }
|
val extensionReceiver = owner.getExtensionReceiver()?.let { callStack.popState() }
|
||||||
val dispatchReceiver = owner.getDispatchReceiver()?.let { callStack.popState() }
|
val dispatchReceiver = owner.getDispatchReceiver()?.let { callStack.popState() }
|
||||||
|
|
||||||
@@ -201,7 +198,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
|||||||
// 4. store arguments in memory (remap args on actual names)
|
// 4. store arguments in memory (remap args on actual names)
|
||||||
irFunction.getDispatchReceiver()?.let { dispatchReceiver?.let { receiver -> callStack.addVariable(Variable(it, receiver)) } }
|
irFunction.getDispatchReceiver()?.let { dispatchReceiver?.let { receiver -> callStack.addVariable(Variable(it, receiver)) } }
|
||||||
irFunction.getExtensionReceiver()?.let { callStack.addVariable(Variable(it, extensionReceiver ?: callStack.getState(it))) }
|
irFunction.getExtensionReceiver()?.let { callStack.addVariable(Variable(it, extensionReceiver ?: callStack.getState(it))) }
|
||||||
irFunction.valueParameters.forEach { callStack.addVariable(Variable(it.symbol, valueArguments.removeFirst())) }
|
irFunction.valueParameters.forEachIndexed { i, param -> callStack.addVariable(Variable(param.symbol, valueArguments[i])) }
|
||||||
|
|
||||||
// 5. store reified type parameters
|
// 5. store reified type parameters
|
||||||
irFunction.typeParameters.filter { it.isReified }
|
irFunction.typeParameters.filter { it.isReified }
|
||||||
|
|||||||
+10
-8
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
|||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||||
import org.jetbrains.kotlin.ir.interpreter.*
|
import org.jetbrains.kotlin.ir.interpreter.*
|
||||||
import org.jetbrains.kotlin.ir.interpreter.exceptions.handleUserException
|
import org.jetbrains.kotlin.ir.interpreter.exceptions.handleUserException
|
||||||
import org.jetbrains.kotlin.ir.interpreter.exceptions.stop
|
import org.jetbrains.kotlin.ir.interpreter.exceptions.stop
|
||||||
@@ -227,16 +228,17 @@ internal object ArrayConstructor : IntrinsicBase() {
|
|||||||
val size = callStack.getState(sizeSymbol).asInt()
|
val size = callStack.getState(sizeSymbol).asInt()
|
||||||
|
|
||||||
val initSymbol = irFunction.valueParameters[1].symbol
|
val initSymbol = irFunction.valueParameters[1].symbol
|
||||||
val function = when (val state = callStack.getState(initSymbol)) {
|
val state = callStack.getState(initSymbol).let {
|
||||||
is KFunctionState -> state.irFunction.apply { callStack.loadUpValues(state) }
|
(it as? KFunctionState) ?: (it as KPropertyState).convertGetterToKFunctionState()
|
||||||
is KPropertyState -> state.property.getter
|
}
|
||||||
else -> TODO("Unsupported `init` in array constructor: $state")
|
// if property was converted, then we must replace symbol in memory to get correct receiver later
|
||||||
} as IrSimpleFunction
|
callStack.setState(initSymbol, state)
|
||||||
|
|
||||||
for (i in size - 1 downTo 0) {
|
for (i in size - 1 downTo 0) {
|
||||||
val call = IrCallImpl.fromSymbolOwner(UNDEFINED_OFFSET, UNDEFINED_OFFSET, function.returnType, function.symbol)
|
val invoke = state.invokeSymbol.owner as IrSimpleFunction
|
||||||
val arg = IrConstImpl.int(UNDEFINED_OFFSET, UNDEFINED_OFFSET, environment.irBuiltIns.intType, i)
|
val call = IrCallImpl.fromSymbolOwner(UNDEFINED_OFFSET, UNDEFINED_OFFSET, invoke.returnType, invoke.symbol)
|
||||||
if (function.correspondingPropertySymbol == null) call.putValueArgument(0, arg) else call.extensionReceiver = arg
|
call.dispatchReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, initSymbol)
|
||||||
|
call.putValueArgument(0, IrConstImpl.int(UNDEFINED_OFFSET, UNDEFINED_OFFSET, environment.irBuiltIns.intType, i))
|
||||||
instructions += CompoundInstruction(call)
|
instructions += CompoundInstruction(call)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.ir.interpreter.state
|
package org.jetbrains.kotlin.ir.interpreter.state
|
||||||
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||||
@@ -93,5 +94,6 @@ 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
|
||||||
return this is ReflectionState && !(this is KFunctionState && call.symbol.owner.name == OperatorNameConventions.INVOKE)
|
return this is ReflectionState && !(this is KFunctionState && call.symbol.owner.name == OperatorNameConventions.INVOKE)
|
||||||
}
|
}
|
||||||
+6
@@ -23,6 +23,12 @@ internal class KPropertyState(val property: IrProperty, override val irClass: Ir
|
|||||||
private var _parameters: List<KParameter>? = null
|
private var _parameters: List<KParameter>? = null
|
||||||
private var _returnType: KType? = null
|
private var _returnType: KType? = null
|
||||||
|
|
||||||
|
fun convertGetterToKFunctionState(): KFunctionState {
|
||||||
|
val getterClass = irClass.getIrClassOfReflection("getter")
|
||||||
|
val functionType = getterClass.superTypes.single { it.classOrNull?.owner?.name?.asString() == "Function1" }
|
||||||
|
return KFunctionState(property.getter!!, functionType.classOrNull!!.owner)
|
||||||
|
}
|
||||||
|
|
||||||
fun getParameters(callInterceptor: CallInterceptor): List<KParameter> {
|
fun getParameters(callInterceptor: CallInterceptor): List<KParameter> {
|
||||||
if (_parameters != null) return _parameters!!
|
if (_parameters != null) return _parameters!!
|
||||||
val kParameterIrClass = irClass.getIrClassOfReflectionFromList("parameters")
|
val kParameterIrClass = irClass.getIrClassOfReflectionFromList("parameters")
|
||||||
|
|||||||
Reference in New Issue
Block a user