Unify value arguments interpretation
This commit is contained in:
+39
-24
@@ -317,10 +317,25 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
return constructorCall.interpret(newFrame).apply { data.pushReturnValue(newFrame) }
|
return constructorCall.interpret(newFrame).apply { data.pushReturnValue(newFrame) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun interpretValueParameters(parametersContainer: IrMemberAccessExpression, data: Frame): ExecutionResult {
|
private suspend fun interpretValueParameters(
|
||||||
val defaultValues = (parametersContainer.symbol.owner as IrFunction).valueParameters.map { it.defaultValue }
|
expression: IrFunctionAccessExpression, irFunction: IrFunction, data: Frame, newFrame: Frame
|
||||||
for (i in (parametersContainer.valueArgumentsCount - 1) downTo 0) {
|
): ExecutionResult {
|
||||||
(parametersContainer.getValueArgument(i)?.interpret(data) ?: defaultValues[i]!!.expression.interpret(data)).check { return it }
|
// if irFunction is lambda and it has receiver, then first descriptor must be taken from extension receiver
|
||||||
|
val receiverAsFirstArgument = when (expression.dispatchReceiver?.type?.isFunction()) {
|
||||||
|
true -> listOfNotNull(irFunction.symbol.getExtensionReceiver())
|
||||||
|
else -> listOf()
|
||||||
|
}
|
||||||
|
val valueParametersDescriptors = receiverAsFirstArgument + irFunction.descriptor.valueParameters
|
||||||
|
|
||||||
|
val valueArguments = (0 until expression.valueArgumentsCount).map { expression.getValueArgument(it) }
|
||||||
|
val defaultValues = expression.symbol.owner.valueParameters.map { it.defaultValue?.expression }
|
||||||
|
val frameWithReceiverAndData = data.copy().apply { addAll(newFrame.getAll()) } // primary use case: copy method in data class
|
||||||
|
for ((i, valueArgument) in valueArguments.withIndex()) {
|
||||||
|
(valueArgument ?: defaultValues[i])!!.interpret(frameWithReceiverAndData).checkForReturn(frameWithReceiverAndData, data) { return it }
|
||||||
|
with(Variable(valueParametersDescriptors[i], frameWithReceiverAndData.popReturnValue())) {
|
||||||
|
frameWithReceiverAndData.addVar(this)
|
||||||
|
newFrame.addVar(this)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return Next
|
return Next
|
||||||
}
|
}
|
||||||
@@ -332,9 +347,12 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
val rawDispatchReceiver = expression.dispatchReceiver
|
val rawDispatchReceiver = expression.dispatchReceiver
|
||||||
rawDispatchReceiver?.interpret(data)?.check { return it }
|
rawDispatchReceiver?.interpret(data)?.check { return it }
|
||||||
val dispatchReceiver = rawDispatchReceiver?.let { data.popReturnValue() }
|
val dispatchReceiver = rawDispatchReceiver?.let { data.popReturnValue() }
|
||||||
val irFunctionReceiver = when (expression.superQualifierSymbol) {
|
|
||||||
null -> dispatchReceiver
|
val superQualifier = expression.superQualifierSymbol
|
||||||
else -> (dispatchReceiver as Complex).superClass?.takeIf { it.irClass.isSubclassOf(expression.superQualifierSymbol!!.owner) }
|
val irFunctionReceiver = when {
|
||||||
|
superQualifier == null -> dispatchReceiver
|
||||||
|
superQualifier.owner.isInterface -> null
|
||||||
|
else -> (dispatchReceiver as Complex).superClass
|
||||||
}
|
}
|
||||||
// it is important firstly to add receiver, then arguments; this order is used in builtin method call
|
// it is important firstly to add receiver, then arguments; this order is used in builtin method call
|
||||||
val irFunction = irFunctionReceiver?.getIrFunction(expression.symbol.descriptor) ?: expression.symbol.owner
|
val irFunction = irFunctionReceiver?.getIrFunction(expression.symbol.descriptor) ?: expression.symbol.owner
|
||||||
@@ -349,13 +367,9 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
val extensionReceiver = rawExtensionReceiver?.let { data.popReturnValue() }
|
val extensionReceiver = rawExtensionReceiver?.let { data.popReturnValue() }
|
||||||
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
|
interpretValueParameters(expression, irFunction, data, newFrame).check { return it }
|
||||||
val receiverAsFirstArgument = if (dispatchReceiver is Lambda) listOfNotNull(irFunction.symbol.getExtensionReceiver()) else listOf()
|
|
||||||
val valueParametersDescriptors = receiverAsFirstArgument + irFunction.descriptor.valueParameters
|
|
||||||
val frameWithReceiverAndData = data.copy().apply { addAll(newFrame.getAll()) } // primary use case: copy method in data class
|
|
||||||
interpretValueParameters(expression, frameWithReceiverAndData).checkForReturn(frameWithReceiverAndData, data) { return it }
|
|
||||||
newFrame.addAll(valueParametersDescriptors.map { Variable(it, frameWithReceiverAndData.popReturnValue()) })
|
|
||||||
|
|
||||||
|
// TODO fun saveReifiedParameters
|
||||||
irFunction.takeIf { it.isInline }?.typeParameters?.forEachIndexed { index, typeParameter ->
|
irFunction.takeIf { it.isInline }?.typeParameters?.forEachIndexed { index, typeParameter ->
|
||||||
if (typeParameter.isReified) {
|
if (typeParameter.isReified) {
|
||||||
val typeArgumentState = Common(expression.getTypeArgument(index)?.classOrNull!!.owner)
|
val typeArgumentState = Common(expression.getTypeArgument(index)?.classOrNull!!.owner)
|
||||||
@@ -397,23 +411,23 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun interpretConstructor(constructorCall: IrFunctionAccessExpression, data: Frame): ExecutionResult {
|
private suspend fun interpretConstructor(constructorCall: IrFunctionAccessExpression, data: Frame): ExecutionResult {
|
||||||
val isPrimary = (constructorCall.symbol.owner as IrConstructor).isPrimary
|
|
||||||
interpretValueParameters(constructorCall, data).check { return it }
|
|
||||||
val valueParameters = constructorCall.symbol.descriptor.valueParameters.map { Variable(it, data.popReturnValue()) }.toMutableList()
|
|
||||||
val newFrame = InterpreterFrame(valueParameters)
|
|
||||||
|
|
||||||
val owner = constructorCall.symbol.owner
|
val owner = constructorCall.symbol.owner
|
||||||
|
val isPrimary = (owner as IrConstructor).isPrimary
|
||||||
|
val newFrame = InterpreterFrame()
|
||||||
|
|
||||||
|
interpretValueParameters(constructorCall, owner, data, newFrame)
|
||||||
|
|
||||||
val parent = owner.parent as IrClass
|
val parent = owner.parent as IrClass
|
||||||
if (parent.hasAnnotation(evaluateIntrinsicAnnotation)) {
|
if (parent.hasAnnotation(evaluateIntrinsicAnnotation)) {
|
||||||
return when (constructorCall.symbol.owner.parentAsClass.getEvaluateIntrinsicValue()) {
|
return when (owner.parentAsClass.getEvaluateIntrinsicValue()) {
|
||||||
"kotlin.Long" -> {
|
"kotlin.Long" -> {
|
||||||
val low = (valueParameters[0].state as Primitive<*>).value as Int
|
val low = (newFrame.getVariableState(owner.valueParameters[0].descriptor) as Primitive<*>).value as Int
|
||||||
val high = (valueParameters[1].state as Primitive<*>).value as Int
|
val high = (newFrame.getVariableState(owner.valueParameters[1].descriptor) as Primitive<*>).value as Int
|
||||||
data.pushReturnValue((high.toLong().shl(32) + low).toState(irBuiltIns.longType))
|
data.pushReturnValue((high.toLong().shl(32) + low).toState(irBuiltIns.longType))
|
||||||
Next
|
Next
|
||||||
}
|
}
|
||||||
"kotlin.Char" -> {
|
"kotlin.Char" -> {
|
||||||
val value = (valueParameters.single().state as Primitive<*>).value as Int
|
val value = (newFrame.getVariableState(owner.valueParameters[0].descriptor) as Primitive<*>).value as Int
|
||||||
data.pushReturnValue(value.toChar().toState(irBuiltIns.longType))
|
data.pushReturnValue(value.toChar().toState(irBuiltIns.longType))
|
||||||
Next
|
Next
|
||||||
}
|
}
|
||||||
@@ -428,7 +442,7 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
val size = (newFrame.getVariableState(sizeDescriptor) as Primitive<*>).value as Int
|
val size = (newFrame.getVariableState(sizeDescriptor) as Primitive<*>).value as Int
|
||||||
|
|
||||||
val arrayValue = Array<Any?>(size) { 0 }
|
val arrayValue = Array<Any?>(size) { 0 }
|
||||||
if (valueParameters.size == 2) {
|
if (owner.valueParameters.size == 2) {
|
||||||
val initDescriptor = arrayConstructor.owner.valueParameters.single { it.name.asString() == "init" }.descriptor
|
val initDescriptor = arrayConstructor.owner.valueParameters.single { it.name.asString() == "init" }.descriptor
|
||||||
val initLambda = newFrame.getVariableState(initDescriptor) as Lambda
|
val initLambda = newFrame.getVariableState(initDescriptor) as Lambda
|
||||||
val indexDescriptor = initLambda.irFunction.valueParameters.single().descriptor
|
val indexDescriptor = initLambda.irFunction.valueParameters.single().descriptor
|
||||||
@@ -575,6 +589,7 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
val executionResult = expression.value.interpret(data)
|
val executionResult = expression.value.interpret(data)
|
||||||
if (executionResult.returnLabel != ReturnLabel.NEXT) return executionResult
|
if (executionResult.returnLabel != ReturnLabel.NEXT) return executionResult
|
||||||
|
|
||||||
|
// receiver is null only for top level var, but it cannot be used in constexpr; corresponding check is on frontend
|
||||||
val receiver = (expression.receiver as IrDeclarationReference).symbol.descriptor
|
val receiver = (expression.receiver as IrDeclarationReference).symbol.descriptor
|
||||||
data.getVariableState(receiver).setState(Variable(expression.symbol.owner.descriptor, data.popReturnValue()))
|
data.getVariableState(receiver).setState(Variable(expression.symbol.owner.descriptor, data.popReturnValue()))
|
||||||
return Next
|
return Next
|
||||||
@@ -596,7 +611,7 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun interpretVariable(expression: IrVariable, data: Frame): ExecutionResult {
|
private suspend fun interpretVariable(expression: IrVariable, data: Frame): ExecutionResult {
|
||||||
val executionResult = expression.initializer?.interpret(data)
|
val executionResult = expression.initializer?.interpret(data)// TODO replace with check
|
||||||
if (executionResult?.returnLabel != ReturnLabel.NEXT) return executionResult ?: Next
|
if (executionResult?.returnLabel != ReturnLabel.NEXT) return executionResult ?: Next
|
||||||
data.addVar(Variable(expression.descriptor, data.popReturnValue()))
|
data.addVar(Variable(expression.descriptor, data.popReturnValue()))
|
||||||
return Next
|
return Next
|
||||||
|
|||||||
Reference in New Issue
Block a user