Rewrite interpreter logic around arguments evaluation
For now calculated arguments will be stored on stack instead of memory. At first this was done because of problems with default arguments, but in the next commit this problem will be solved.
This commit is contained in:
committed by
TeamCityServer
parent
d41c6e900a
commit
7852d01da6
+1
-1
@@ -60,7 +60,7 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) :
|
||||
)
|
||||
return interpreter.withNewCallStack(irCall) {
|
||||
this@withNewCallStack.environment.callStack.addInstruction(SimpleInstruction(irCall))
|
||||
valueArguments.forEach { this@withNewCallStack.environment.callStack.addVariable(it) }
|
||||
valueArguments.forEach { this@withNewCallStack.environment.callStack.pushState(it.state) }
|
||||
}.wrap(this@DefaultCallInterceptor, remainArraysAsIs = false, extendFrom = expectedResultClass)
|
||||
}
|
||||
|
||||
|
||||
+27
-24
@@ -157,31 +157,34 @@ private fun unfoldValueParameters(expression: IrFunctionAccessExpression, callSt
|
||||
|
||||
val valueParametersSymbols = irFunction.valueParameters.map { it.symbol }
|
||||
|
||||
// interpret defaults for null arguments (at the end)
|
||||
(expression.valueArgumentsCount - 1 downTo 0).forEach { index ->
|
||||
if (expression.getValueArgument(index) != null) return@forEach
|
||||
callStack.addInstruction(SimpleInstruction(valueParametersSymbols[index].owner))
|
||||
|
||||
getDefaultForParameterAt(index)
|
||||
?.let { callStack.addInstruction(CompoundInstruction(it)) }
|
||||
?: expression.getVarargType(index)?.let { // case when value parameter is vararg and it is missing
|
||||
callStack.addInstruction(SimpleInstruction(IrConstImpl.constNull(UNDEFINED_OFFSET, UNDEFINED_OFFSET, it)))
|
||||
}
|
||||
}
|
||||
|
||||
// interpret not null arguments (after evaluation of arguments)
|
||||
expression.dispatchReceiver?.let { callStack.addInstruction(SimpleInstruction(irFunction.dispatchReceiverParameter!!)) }
|
||||
expression.extensionReceiver?.let { callStack.addInstruction(SimpleInstruction(irFunction.extensionReceiverParameter!!)) }
|
||||
(0 until expression.valueArgumentsCount).forEach {
|
||||
if (expression.getValueArgument(it) != null) callStack.addInstruction(SimpleInstruction(irFunction.valueParameters[it]))
|
||||
}
|
||||
|
||||
// evaluate arguments
|
||||
(expression.valueArgumentsCount - 1 downTo 0).forEach {
|
||||
callStack.addInstruction(CompoundInstruction(expression.getValueArgument(it)))
|
||||
(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)
|
||||
?.let { callStack.addInstruction(CompoundInstruction(it)) }
|
||||
?: expression.getVarargType(index)?.let { // case when value parameter is vararg and it is missing
|
||||
callStack.addInstruction(SimpleInstruction(IrConstImpl.constNull(UNDEFINED_OFFSET, UNDEFINED_OFFSET, it)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
expression.extensionReceiver?.let {
|
||||
callStack.addInstruction(SimpleInstruction(irFunction.extensionReceiverParameter!!))
|
||||
callStack.addInstruction(CompoundInstruction(it))
|
||||
}
|
||||
expression.dispatchReceiver?.let {
|
||||
callStack.addInstruction(SimpleInstruction(irFunction.dispatchReceiverParameter!!))
|
||||
callStack.addInstruction(CompoundInstruction(it))
|
||||
}
|
||||
expression.extensionReceiver?.let { callStack.addInstruction(CompoundInstruction(it)) }
|
||||
expression.dispatchReceiver?.let { callStack.addInstruction(CompoundInstruction(it)) }
|
||||
}
|
||||
|
||||
private fun unfoldInstanceInitializerCall(instanceInitializerCall: IrInstanceInitializerCall, callStack: CallStack) {
|
||||
@@ -378,7 +381,7 @@ private fun unfoldStringConcatenation(expression: IrStringConcatenation, environ
|
||||
val toStringCall = state.createToStringIrCall()
|
||||
callStack.newSubFrame(toStringCall)
|
||||
callStack.addInstruction(SimpleInstruction(toStringCall))
|
||||
callStack.addVariable(Variable(toStringCall.symbol.owner.dispatchReceiverParameter!!.symbol, state))
|
||||
callStack.pushState(state)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+10
-10
@@ -164,6 +164,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
||||
|
||||
// outer classes can be used in default args evaluation
|
||||
if (isReceiver() && state is Complex) state.loadOuterClassesInto(callStack)
|
||||
callStack.pushState(state)
|
||||
}
|
||||
|
||||
private fun interpretCall(call: IrCall) {
|
||||
@@ -176,9 +177,9 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
||||
|
||||
val owner = call.symbol.owner
|
||||
// 1. load evaluated arguments from stack
|
||||
val dispatchReceiver = owner.getDispatchReceiver()?.let { callStack.getState(it) }
|
||||
val extensionReceiver = owner.getExtensionReceiver()?.let { callStack.getState(it) }
|
||||
val valueArguments = owner.valueParameters.map { callStack.getState(it.symbol) }.toMutableList()
|
||||
val valueArguments = owner.valueParameters.map { callStack.popState() }.reversed().toMutableList()
|
||||
val extensionReceiver = owner.getExtensionReceiver()?.let { callStack.popState() }
|
||||
val dispatchReceiver = owner.getDispatchReceiver()?.let { callStack.popState() }
|
||||
|
||||
// 2. get correct function for interpretation
|
||||
val irFunction = dispatchReceiver?.getIrFunctionByIrCall(call) ?: call.symbol.owner
|
||||
@@ -199,7 +200,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
||||
|
||||
// 4. store arguments in memory (remap args on actual names)
|
||||
irFunction.getDispatchReceiver()?.let { dispatchReceiver?.let { receiver -> callStack.addVariable(Variable(it, receiver)) } }
|
||||
irFunction.getExtensionReceiver()?.let { callStack.addVariable(Variable(it, extensionReceiver ?: valueArguments.removeFirst())) }
|
||||
irFunction.getExtensionReceiver()?.let { callStack.addVariable(Variable(it, extensionReceiver ?: callStack.getState(it))) }
|
||||
irFunction.valueParameters.forEach { callStack.addVariable(Variable(it.symbol, valueArguments.removeFirst())) }
|
||||
|
||||
// 5. store reified type parameters
|
||||
@@ -240,7 +241,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
||||
|
||||
private fun interpretConstructorCall(constructorCall: IrFunctionAccessExpression) {
|
||||
val constructor = constructorCall.symbol.owner
|
||||
val valueArguments = constructor.valueParameters.map { callStack.getState(it.symbol) }
|
||||
val valueArguments = constructor.valueParameters.map { callStack.popState() }.reversed()
|
||||
val irClass = constructor.parentAsClass
|
||||
val receiverSymbol = constructor.dispatchReceiverParameter?.symbol
|
||||
|
||||
@@ -255,7 +256,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
||||
}
|
||||
|
||||
if (irClass.isLocal) callStack.storeUpValues(objectState as StateWithClosure)
|
||||
val outerClass = receiverSymbol?.let { callStack.getState(it) }
|
||||
val outerClass = receiverSymbol?.let { callStack.popState() }
|
||||
|
||||
callStack.dropSubFrame()
|
||||
callStack.newFrame(constructor)
|
||||
@@ -603,8 +604,8 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
||||
private fun interpretFunctionReference(reference: IrFunctionReference) {
|
||||
val irFunction = reference.symbol.owner
|
||||
|
||||
val dispatchReceiver = reference.dispatchReceiver?.let { callStack.getState(irFunction.getDispatchReceiver()!!) }
|
||||
val extensionReceiver = reference.extensionReceiver?.let { callStack.getState(irFunction.getExtensionReceiver()!!) }
|
||||
val dispatchReceiver = reference.dispatchReceiver?.let { callStack.popState() }
|
||||
val extensionReceiver = reference.extensionReceiver?.let { callStack.popState() }
|
||||
|
||||
callStack.dropSubFrame()
|
||||
|
||||
@@ -618,10 +619,9 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
||||
}
|
||||
|
||||
private fun interpretPropertyReference(propertyReference: IrPropertyReference) {
|
||||
val receiverSymbol = propertyReference.getter?.owner?.let { it.getDispatchReceiver() ?: it.getExtensionReceiver() }
|
||||
// it is impossible to get KProperty2 through ::, so only one receiver can be not null (or both null)
|
||||
val receiver = (propertyReference.dispatchReceiver ?: propertyReference.extensionReceiver)
|
||||
?.let { callStack.getState(receiverSymbol!!) }
|
||||
?.let { callStack.popState() }
|
||||
|
||||
callStack.dropSubFrame()
|
||||
val propertyState = KPropertyState(propertyReference, receiver)
|
||||
|
||||
+4
-4
@@ -83,13 +83,13 @@ internal class KFunctionState(
|
||||
val dispatchParameter = irFunction.dispatchReceiverParameter
|
||||
val extensionParameter = irFunction.extensionReceiverParameter
|
||||
|
||||
if (dispatchParameter != null && getField(dispatchParameter.symbol) == null) {
|
||||
if (dispatchParameter != null) {
|
||||
dispatchReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, dispatchParameter.type, dispatchParameter.symbol)
|
||||
(this@impl.valueParameters as MutableList).add(dispatchParameter)
|
||||
if (getField(dispatchParameter.symbol) == null) (this@impl.valueParameters as MutableList).add(dispatchParameter)
|
||||
}
|
||||
if (extensionParameter != null && getField(extensionParameter.symbol) == null) {
|
||||
if (extensionParameter != null) {
|
||||
extensionReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, extensionParameter.type, extensionParameter.symbol)
|
||||
(this@impl.valueParameters as MutableList).add(extensionParameter)
|
||||
if (getField(extensionParameter.symbol) == null) (this@impl.valueParameters as MutableList).add(extensionParameter)
|
||||
}
|
||||
irFunction.valueParameters.forEach {
|
||||
putArgument(it, IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, it.type, it.symbol))
|
||||
|
||||
Reference in New Issue
Block a user