Unify logic of creation new ir tree nodes in interpreter

This commit is contained in:
Ivan Kylchik
2021-06-21 23:44:29 +03:00
committed by TeamCityServer
parent 6ce2f8eb14
commit 4ad88679fd
8 changed files with 286 additions and 259 deletions
@@ -7,11 +7,8 @@ package org.jetbrains.kotlin.ir.interpreter
import org.jetbrains.kotlin.ir.IrBuiltIns import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
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.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
import org.jetbrains.kotlin.ir.interpreter.builtins.interpretBinaryFunction import org.jetbrains.kotlin.ir.interpreter.builtins.interpretBinaryFunction
import org.jetbrains.kotlin.ir.interpreter.builtins.interpretTernaryFunction import org.jetbrains.kotlin.ir.interpreter.builtins.interpretTernaryFunction
import org.jetbrains.kotlin.ir.interpreter.builtins.interpretUnaryFunction import org.jetbrains.kotlin.ir.interpreter.builtins.interpretUnaryFunction
@@ -24,7 +21,6 @@ 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.interpreter.state.reflection.KTypeState import org.jetbrains.kotlin.ir.interpreter.state.reflection.KTypeState
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.IrType 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.types.isArray import org.jetbrains.kotlin.ir.types.isArray
@@ -55,9 +51,7 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) :
private val bodyMap: Map<IdSignature, IrBody> = interpreter.bodyMap private val bodyMap: Map<IdSignature, IrBody> = interpreter.bodyMap
override fun interceptProxy(irFunction: IrFunction, valueArguments: List<Variable>, expectedResultClass: Class<*>): Any? { override fun interceptProxy(irFunction: IrFunction, valueArguments: List<Variable>, expectedResultClass: Class<*>): Any? {
val irCall = IrCallImpl.fromSymbolOwner( val irCall = irFunction.createCall()
UNDEFINED_OFFSET, UNDEFINED_OFFSET, irFunction.returnType, irFunction.symbol as IrSimpleFunctionSymbol
)
return interpreter.withNewCallStack(irCall) { return interpreter.withNewCallStack(irCall) {
this@withNewCallStack.environment.callStack.addInstruction(SimpleInstruction(irCall)) this@withNewCallStack.environment.callStack.addInstruction(SimpleInstruction(irCall))
valueArguments.forEach { this@withNewCallStack.environment.callStack.pushState(it.state) } valueArguments.forEach { this@withNewCallStack.environment.callStack.pushState(it.state) }
@@ -186,7 +180,7 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) :
private fun calculateRangeTo(type: IrType, args: List<State>) { private fun calculateRangeTo(type: IrType, args: List<State>) {
val constructor = type.classOrNull!!.owner.constructors.first() val constructor = type.classOrNull!!.owner.constructors.first()
val constructorCall = IrConstructorCallImpl.fromSymbolOwner(constructor.returnType, constructor.symbol) val constructorCall = constructor.createConstructorCall()
val constructorValueParameters = constructor.valueParameters.map { it.symbol } val constructorValueParameters = constructor.valueParameters.map { it.symbol }
val primitiveValueParameters = args.map { it as Primitive<*> } val primitiveValueParameters = args.map { it as Primitive<*> }
@@ -6,30 +6,19 @@
package org.jetbrains.kotlin.ir.interpreter package org.jetbrains.kotlin.ir.interpreter
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities 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.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.*
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.name.Name import org.jetbrains.kotlin.name.Name
internal fun IrExpression.handleAndDropResult(callStack: CallStack, dropOnlyUnit: Boolean = false) { internal fun IrExpression.handleAndDropResult(callStack: CallStack, dropOnlyUnit: Boolean = false) {
@@ -118,132 +107,54 @@ private fun unfoldConstructor(constructor: IrConstructor, callStack: CallStack)
} }
private fun unfoldValueParameters(expression: IrFunctionAccessExpression, callStack: CallStack) { private fun unfoldValueParameters(expression: IrFunctionAccessExpression, callStack: CallStack) {
val irFunction = expression.symbol.owner
val hasDefaults = (0 until expression.valueArgumentsCount).any { expression.getValueArgument(it) == null } val hasDefaults = (0 until expression.valueArgumentsCount).any { expression.getValueArgument(it) == null }
if (hasDefaults) { if (hasDefaults) {
val visibility = if (expression is IrEnumConstructorCall || expression is IrDelegatingConstructorCall) DescriptorVisibilities.LOCAL else irFunction.visibility // if some arguments are not defined, then it is necessary to create temp function where defaults will be evaluated
val defaultFun = IrFunctionImpl( val actualParameters = MutableList<IrValueDeclaration?>(expression.valueArgumentsCount) { null }
UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER, val ownerWithDefaults = expression.getFunctionThatContainsDefaults()
IrSimpleFunctionSymbolImpl(), Name.identifier(irFunction.name.asString() + "\$default"),
visibility, Modality.FINAL, irFunction.returnType, val visibility = when (expression) {
isInline = false, isExternal = false, isTailrec = false, isSuspend = false, isOperator = true, isInfix = false, isExpect = false is IrEnumConstructorCall, is IrDelegatingConstructorCall -> DescriptorVisibilities.LOCAL
) else -> ownerWithDefaults.visibility
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) val defaultFun = createTempFunction(
expression.dispatchReceiver?.let { Name.identifier(ownerWithDefaults.name.asString() + "\$default"), ownerWithDefaults.returnType,
callToDefault.dispatchReceiver = it origin = IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER, visibility
} ).apply {
expression.extensionReceiver?.let { this.parent = ownerWithDefaults.parent
callToDefault.extensionReceiver = it this.dispatchReceiverParameter = ownerWithDefaults.dispatchReceiverParameter?.deepCopyWithSymbols(this)
} this.extensionReceiverParameter = ownerWithDefaults.extensionReceiverParameter?.deepCopyWithSymbols(this)
var index = 0 (0 until expression.valueArgumentsCount).forEach { index ->
(0 until expression.valueArgumentsCount).forEach { val parameter = ownerWithDefaults.valueParameters[index]
if (expression.getValueArgument(it) != null) { actualParameters[index] = if (expression.getValueArgument(index) != null) {
callToDefault.putValueArgument(index++, expression.getValueArgument(it)) parameter.deepCopyWithSymbols(this).also { this.valueParameters += it }
} } else {
} parameter.createTempVariable().apply variable@{
this@variable.initializer = parameter.getDefaultWithActualParameters(this@apply, actualParameters)
fun getDefaultForParameterAt(index: Int): IrExpression? { ?: expression.getVarargType(index)?.let { null.toIrConst(it) } // if parameter is vararg and it is missing
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)
}
}, null
)//.deepCopyWithSymbols(defaultFun) TODO ???
}
fun IrValueParameter.getDefault(): IrExpressionBody? {
if (defaultValue != null) return defaultValue?.replaceGetValueFromOtherClass(this.parent as IrFunction)
return (this.parent as? IrSimpleFunction)?.overriddenSymbols
?.map { it.owner.valueParameters[this.index] }
?.firstOrNull { it.getDefault() != null }?.let { it.getDefault()?.replaceGetValueFromOtherClass(it.parent as IrFunction) }
}
return irFunction.valueParameters[index].getDefault()?.expression
}
val newExpression = when (expression) {
is IrCall -> IrCallImpl.fromSymbolOwner(expression.startOffset, expression.endOffset, expression.type, expression.symbol)
is IrConstructorCall -> IrConstructorCallImpl.fromSymbolOwner(expression.type, expression.symbol)
is IrDelegatingConstructorCall -> IrDelegatingConstructorCallImpl(0, 0, expression.type, expression.symbol, expression.typeArgumentsCount, expression.valueArgumentsCount)
is IrEnumConstructorCall -> IrEnumConstructorCallImpl(0, 0, expression.type, expression.symbol, expression.typeArgumentsCount, expression.valueArgumentsCount)
else -> TODO()
}
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))
} }
val callWithAllArgs = expression.shallowCopy() // just a copy of given call, but with all arguments in place
expression.dispatchReceiver?.let { callWithAllArgs.dispatchReceiver = defaultFun.dispatchReceiverParameter!!.createGetValue() }
expression.extensionReceiver?.let { callWithAllArgs.extensionReceiver = defaultFun.extensionReceiverParameter!!.createGetValue() }
(0 until expression.valueArgumentsCount).forEach { callWithAllArgs.putValueArgument(it, actualParameters[it]?.createGetValue()) }
defaultFun.body = (actualParameters.filterIsInstance<IrVariable>() + defaultFun.createReturn(callWithAllArgs)).wrapWithBlockBody()
defaultFun.body = IrBlockBodyImpl( val callToDefault = defaultFun.createCall().apply { expression.copyArgsInto(this) }
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
variablesForDefault + IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, defaultFun.returnType, defaultFun.symbol, newExpression)
)
callStack.addInstruction(CompoundInstruction(callToDefault)) callStack.addInstruction(CompoundInstruction(callToDefault))
} else { } else {
val irFunction = expression.symbol.owner
callStack.addInstruction(SimpleInstruction(expression)) callStack.addInstruction(SimpleInstruction(expression))
fun IrValueParameter.schedule(arg: IrExpression?) { fun IrValueParameter.schedule(arg: IrExpression?) {
callStack.addInstruction(SimpleInstruction(this)) callStack.addInstruction(SimpleInstruction(this))
callStack.addInstruction(CompoundInstruction(arg)) callStack.addInstruction(CompoundInstruction(arg))
} }
(expression.valueArgumentsCount - 1 downTo 0).forEach { (expression.valueArgumentsCount - 1 downTo 0).forEach { irFunction.valueParameters[it].schedule(expression.getValueArgument(it)) }
irFunction.valueParameters[it].schedule(expression.getValueArgument(it))
}
expression.extensionReceiver?.let { irFunction.extensionReceiverParameter!!.schedule(it) } expression.extensionReceiver?.let { irFunction.extensionReceiverParameter!!.schedule(it) }
expression.dispatchReceiver?.let { irFunction.dispatchReceiverParameter!!.schedule(it) } expression.dispatchReceiver?.let { irFunction.dispatchReceiverParameter!!.schedule(it) }
} }
@@ -311,7 +222,7 @@ private fun unfoldGetValue(expression: IrGetValue, environment: IrInterpreterEnv
// used to evaluate constants inside object // used to evaluate constants inside object
if (expectedClass != null && expectedClass.isObject && expression.symbol.owner.origin == IrDeclarationOrigin.INSTANCE_RECEIVER) { if (expectedClass != null && expectedClass.isObject && expression.symbol.owner.origin == IrDeclarationOrigin.INSTANCE_RECEIVER) {
// TODO is this correct behaviour? // TODO is this correct behaviour?
val irGetObject = IrGetObjectValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, expectedClass.defaultType, expectedClass.symbol) val irGetObject = expectedClass.createGetObject()
return unfoldGetObjectValue(irGetObject, environment) return unfoldGetObjectValue(irGetObject, environment)
} }
environment.callStack.pushState(environment.callStack.getState(expression.symbol)) environment.callStack.pushState(environment.callStack.getState(expression.symbol))
@@ -0,0 +1,174 @@
/*
* Copyright 2010-2021 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.ir.interpreter
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.builtins.UnsignedType
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
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.impl.*
import org.jetbrains.kotlin.ir.interpreter.state.Complex
import org.jetbrains.kotlin.ir.interpreter.state.ExceptionState
import org.jetbrains.kotlin.ir.interpreter.state.Primitive
import org.jetbrains.kotlin.ir.interpreter.state.State
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.name.Name
internal val TEMP_CLASS_FOR_INTERPRETER = object : IrDeclarationOriginImpl("TEMP_CLASS_FOR_INTERPRETER") {}
internal val TEMP_FUNCTION_FOR_INTERPRETER = object : IrDeclarationOriginImpl("TEMP_FUNCTION_FOR_INTERPRETER") {}
fun Any?.toIrConstOrNull(irType: IrType, startOffset: Int = UNDEFINED_OFFSET, endOffset: Int = UNDEFINED_OFFSET): IrConst<*>? {
if (this == null) return IrConstImpl.constNull(startOffset, endOffset, irType)
val constType = irType.makeNotNull()
return when (irType.getPrimitiveType()) {
PrimitiveType.BOOLEAN -> IrConstImpl.boolean(startOffset, endOffset, constType, this as Boolean)
PrimitiveType.CHAR -> IrConstImpl.char(startOffset, endOffset, constType, this as Char)
PrimitiveType.BYTE -> IrConstImpl.byte(startOffset, endOffset, constType, (this as Number).toByte())
PrimitiveType.SHORT -> IrConstImpl.short(startOffset, endOffset, constType, (this as Number).toShort())
PrimitiveType.INT -> IrConstImpl.int(startOffset, endOffset, constType, (this as Number).toInt())
PrimitiveType.FLOAT -> IrConstImpl.float(startOffset, endOffset, constType, (this as Number).toFloat())
PrimitiveType.LONG -> IrConstImpl.long(startOffset, endOffset, constType, (this as Number).toLong())
PrimitiveType.DOUBLE -> IrConstImpl.double(startOffset, endOffset, constType, (this as Number).toDouble())
null -> when (constType.getUnsignedType()) {
UnsignedType.UBYTE -> IrConstImpl.byte(startOffset, endOffset, constType, (this as Number).toByte())
UnsignedType.USHORT -> IrConstImpl.short(startOffset, endOffset, constType, (this as Number).toShort())
UnsignedType.UINT -> IrConstImpl.int(startOffset, endOffset, constType, (this as Number).toInt())
UnsignedType.ULONG -> IrConstImpl.long(startOffset, endOffset, constType, (this as Number).toLong())
null -> when {
constType.isString() -> IrConstImpl.string(startOffset, endOffset, constType, this as String)
else -> null
}
}
}
}
fun Any?.toIrConst(irType: IrType, startOffset: Int = UNDEFINED_OFFSET, endOffset: Int = UNDEFINED_OFFSET): IrConst<*> =
toIrConstOrNull(irType, startOffset, endOffset)
?: throw UnsupportedOperationException("Unsupported const element type ${irType.makeNotNull().render()}")
fun Any?.toIrConst(
irType: IrType, irBuiltIns: IrBuiltIns,
startOffset: Int = UNDEFINED_OFFSET, endOffset: Int = UNDEFINED_OFFSET
): IrConst<*> =
toIrConstOrNull(irType, startOffset, endOffset) ?: run {
if (irType == irBuiltIns.stringType) IrConstImpl.string(startOffset, endOffset, irType.makeNotNull(), this as String)
else throw UnsupportedOperationException("Unsupported const element type ${irType.makeNotNull().render()}")
}
internal fun State.toIrExpression(expression: IrExpression): IrExpression {
val start = expression.startOffset
val end = expression.endOffset
val type = expression.type.makeNotNull()
return when (this) {
is Primitive<*> ->
when {
this.value == null -> this.value.toIrConst(type, start, end)
type.isPrimitiveType() || type.isString() -> this.value.toIrConst(type, start, end)
else -> expression // TODO support for arrays
}
is ExceptionState -> {
IrErrorExpressionImpl(expression.startOffset, expression.endOffset, expression.type, "\n" + this.getFullDescription())
}
is Complex -> {
val stateType = this.irClass.defaultType
when {
stateType.isUnsignedType() -> (this.fields.single().state as Primitive<*>).value.toIrConst(type, start, end)
else -> expression
}
}
else -> expression // TODO support
}
}
internal fun IrFunction.createCall(): IrCall {
this as IrSimpleFunction
return IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, returnType, symbol, typeParameters.size, valueParameters.size)
}
internal fun IrConstructor.createConstructorCall(): IrConstructorCall {
return IrConstructorCallImpl.fromSymbolOwner(returnType, symbol)
}
internal fun IrValueDeclaration.createGetValue(): IrGetValue {
return IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, this.type, this.symbol)
}
internal fun IrValueDeclaration.createTempVariable(): IrVariable {
return IrVariableImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.IR_TEMPORARY_VARIABLE, IrVariableSymbolImpl(),
this.name, this.type, isVar = false, isConst = false, isLateinit = false
)
}
internal fun IrClass.createGetObject(): IrGetObjectValue {
return IrGetObjectValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, this.defaultType, this.symbol)
}
internal fun IrFunction.createReturn(value: IrExpression): IrReturn {
return IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, this.returnType, this.symbol, value)
}
internal fun createTempFunction(
name: Name,
type: IrType,
origin: IrDeclarationOrigin = TEMP_FUNCTION_FOR_INTERPRETER,
visibility: DescriptorVisibility = DescriptorVisibilities.PUBLIC
): IrSimpleFunction {
return IrFunctionImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, IrSimpleFunctionSymbolImpl(), name, visibility, Modality.FINAL, type,
isInline = false, isExternal = false, isTailrec = false, isSuspend = false, isOperator = true, isInfix = false, isExpect = false
)
}
internal fun createTempClass(name: Name, origin: IrDeclarationOrigin = TEMP_CLASS_FOR_INTERPRETER): IrClass {
return IrFactoryImpl.createClass(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, IrClassSymbolImpl(), name,
ClassKind.CLASS, DescriptorVisibilities.PRIVATE, Modality.FINAL
)
}
internal fun List<IrStatement>.wrapWithBlockBody(): IrBlockBody {
return IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, this)
}
internal fun IrFunctionAccessExpression.shallowCopy(copyTypeArguments: Boolean = true): IrFunctionAccessExpression {
return when (this) {
is IrCall -> IrCallImpl.fromSymbolOwner(startOffset, endOffset, type, symbol)
is IrConstructorCall -> IrConstructorCallImpl.fromSymbolOwner(type, symbol)
is IrDelegatingConstructorCall -> IrDelegatingConstructorCallImpl.fromSymbolOwner(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, symbol)
is IrEnumConstructorCall ->
IrEnumConstructorCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, symbol, typeArgumentsCount, valueArgumentsCount)
else -> TODO("Expression $this cannot be copied")
}.apply {
if (copyTypeArguments) {
(0 until this@shallowCopy.typeArgumentsCount).forEach { this.putTypeArgument(it, this@shallowCopy.getTypeArgument(it)) }
}
}
}
internal fun IrFunctionAccessExpression.copyArgsInto(newCall: IrFunctionAccessExpression) {
newCall.dispatchReceiver = this.dispatchReceiver
newCall.extensionReceiver = this.extensionReceiver
(0 until this.valueArgumentsCount)
.mapNotNull { this.getValueArgument(it) }
.forEachIndexed { i, arg -> newCall.putValueArgument(i, arg) }
}
@@ -7,23 +7,23 @@ 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.builtins.UnsignedType
import org.jetbrains.kotlin.ir.IrBuiltIns
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.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl
import org.jetbrains.kotlin.ir.interpreter.exceptions.handleUserException import org.jetbrains.kotlin.ir.interpreter.exceptions.handleUserException
import org.jetbrains.kotlin.ir.interpreter.proxy.Proxy import org.jetbrains.kotlin.ir.interpreter.proxy.Proxy
import org.jetbrains.kotlin.ir.interpreter.proxy.wrap import org.jetbrains.kotlin.ir.interpreter.proxy.wrap
import org.jetbrains.kotlin.ir.interpreter.state.* import org.jetbrains.kotlin.ir.interpreter.state.Primitive
import org.jetbrains.kotlin.ir.interpreter.state.State
import org.jetbrains.kotlin.ir.interpreter.state.Wrapper
import org.jetbrains.kotlin.ir.interpreter.state.isSubtypeOf
import org.jetbrains.kotlin.ir.interpreter.state.reflection.KTypeState import org.jetbrains.kotlin.ir.interpreter.state.reflection.KTypeState
import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.buildSimpleType import org.jetbrains.kotlin.ir.types.impl.buildSimpleType
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
@@ -42,31 +42,6 @@ internal fun IrFunction.getReceiver(): IrSymbol? = this.getDispatchReceiver() ?:
internal fun IrFunctionAccessExpression.getThisReceiver(): IrValueSymbol = this.symbol.owner.parentAsClass.thisReceiver!!.symbol internal fun IrFunctionAccessExpression.getThisReceiver(): IrValueSymbol = this.symbol.owner.parentAsClass.thisReceiver!!.symbol
internal fun State.toIrExpression(expression: IrExpression): IrExpression {
val start = expression.startOffset
val end = expression.endOffset
val type = expression.type.makeNotNull()
return when (this) {
is Primitive<*> ->
when {
this.value == null -> this.value.toIrConst(type, start, end)
type.isPrimitiveType() || type.isString() -> this.value.toIrConst(type, start, end)
else -> expression // TODO support for arrays
}
is ExceptionState -> {
IrErrorExpressionImpl(expression.startOffset, expression.endOffset, expression.type, "\n" + this.getFullDescription())
}
is Complex -> {
val stateType = this.irClass.defaultType
when {
stateType.isUnsignedType() -> (this.fields.single().state as Primitive<*>).value.toIrConst(type, start, end)
else -> expression
}
}
else -> expression // TODO support
}
}
/** /**
* Convert object from outer world to state * Convert object from outer world to state
*/ */
@@ -81,45 +56,6 @@ internal fun Any?.toState(irType: IrType): State {
} }
} }
fun Any?.toIrConstOrNull(irType: IrType, startOffset: Int = UNDEFINED_OFFSET, endOffset: Int = UNDEFINED_OFFSET): IrConst<*>? {
if (this == null) return IrConstImpl.constNull(startOffset, endOffset, irType)
val constType = irType.makeNotNull()
return when (irType.getPrimitiveType()) {
PrimitiveType.BOOLEAN -> IrConstImpl.boolean(startOffset, endOffset, constType, this as Boolean)
PrimitiveType.CHAR -> IrConstImpl.char(startOffset, endOffset, constType, this as Char)
PrimitiveType.BYTE -> IrConstImpl.byte(startOffset, endOffset, constType, (this as Number).toByte())
PrimitiveType.SHORT -> IrConstImpl.short(startOffset, endOffset, constType, (this as Number).toShort())
PrimitiveType.INT -> IrConstImpl.int(startOffset, endOffset, constType, (this as Number).toInt())
PrimitiveType.FLOAT -> IrConstImpl.float(startOffset, endOffset, constType, (this as Number).toFloat())
PrimitiveType.LONG -> IrConstImpl.long(startOffset, endOffset, constType, (this as Number).toLong())
PrimitiveType.DOUBLE -> IrConstImpl.double(startOffset, endOffset, constType, (this as Number).toDouble())
null -> when (constType.getUnsignedType()) {
UnsignedType.UBYTE -> IrConstImpl.byte(startOffset, endOffset, constType, (this as Number).toByte())
UnsignedType.USHORT -> IrConstImpl.short(startOffset, endOffset, constType, (this as Number).toShort())
UnsignedType.UINT -> IrConstImpl.int(startOffset, endOffset, constType, (this as Number).toInt())
UnsignedType.ULONG -> IrConstImpl.long(startOffset, endOffset, constType, (this as Number).toLong())
null -> when {
constType.isString() -> IrConstImpl.string(startOffset, endOffset, constType, this as String)
else -> null
}
}
}
}
fun Any?.toIrConst(irType: IrType, startOffset: Int = UNDEFINED_OFFSET, endOffset: Int = UNDEFINED_OFFSET): IrConst<*> =
toIrConstOrNull(irType, startOffset, endOffset)
?: throw UnsupportedOperationException("Unsupported const element type ${irType.makeNotNull().render()}")
fun Any?.toIrConst(
irType: IrType, irBuiltIns: IrBuiltIns,
startOffset: Int = UNDEFINED_OFFSET, endOffset: Int = UNDEFINED_OFFSET
): IrConst<*> =
toIrConstOrNull(irType, startOffset, endOffset) ?: run {
if (irType == irBuiltIns.stringType) IrConstImpl.string(startOffset, endOffset, irType.makeNotNull(), this as String)
else throw UnsupportedOperationException("Unsupported const element type ${irType.makeNotNull().render()}")
}
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
internal fun <T> IrConst<T>.toPrimitive(): Primitive<T> = when { internal fun <T> IrConst<T>.toPrimitive(): Primitive<T> = when {
type.isByte() -> Primitive((value as Number).toByte() as T, type) type.isByte() -> Primitive((value as Number).toByte() as T, type)
@@ -276,3 +212,38 @@ internal fun IrType.getOnlyName(): String {
internal fun IrFieldAccessExpression.accessesTopLevelOrObjectField(): Boolean { internal fun IrFieldAccessExpression.accessesTopLevelOrObjectField(): Boolean {
return this.receiver == null || (this.receiver?.type?.classifierOrNull?.owner as? IrClass)?.isObject == true return this.receiver == null || (this.receiver?.type?.classifierOrNull?.owner as? IrClass)?.isObject == true
} }
internal fun IrFunctionAccessExpression.getFunctionThatContainsDefaults(): IrFunction {
val irFunction = this.symbol.owner
fun IrValueParameter.lookup(): IrFunction? {
return defaultValue?.let { this.parent as IrFunction }
?: (this.parent as? IrSimpleFunction)?.overriddenSymbols
?.map { it.owner.valueParameters[this.index] }
?.firstNotNullOfOrNull { it.lookup() }
}
return (0 until this.valueArgumentsCount)
.first { this.getValueArgument(it) == null }
.let { irFunction.valueParameters[it].lookup() ?: irFunction }
}
internal fun IrValueParameter.getDefaultWithActualParameters(
newParent: IrFunction, actualParameters: List<IrValueDeclaration?>
): IrExpression? {
val expression = this.defaultValue?.expression
if (expression is IrConst<*>) return expression
val parameterOwner = this.parent as IrFunction
val transformer = object : IrElementTransformerVoid() {
override fun visitGetValue(expression: IrGetValue): IrExpression {
val parameter = expression.symbol.owner as? IrValueParameter ?: return super.visitGetValue(expression)
if (parameter.parent != parameterOwner) return super.visitGetValue(expression)
val newParameter = when (parameter.index) {
-1 -> newParent.dispatchReceiverParameter ?: newParent.extensionReceiverParameter
else -> actualParameters[parameter.index]
}
return IrGetValueImpl(expression.startOffset, expression.endOffset, expression.type, newParameter!!.symbol)
}
}
return expression?.deepCopyWithSymbols(newParent)?.transform(transformer, null)
}
@@ -5,12 +5,11 @@
package org.jetbrains.kotlin.ir.interpreter.intrinsics package org.jetbrains.kotlin.ir.interpreter.intrinsics
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.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.createCall
import org.jetbrains.kotlin.ir.interpreter.createGetValue
import org.jetbrains.kotlin.ir.interpreter.toIrConst
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
import org.jetbrains.kotlin.ir.interpreter.state.* import org.jetbrains.kotlin.ir.interpreter.state.*
@@ -235,10 +234,9 @@ internal object ArrayConstructor : IntrinsicBase() {
callStack.setState(initSymbol, state) callStack.setState(initSymbol, state)
for (i in size - 1 downTo 0) { for (i in size - 1 downTo 0) {
val invoke = state.invokeSymbol.owner as IrSimpleFunction val call = (state.invokeSymbol.owner as IrSimpleFunction).createCall()
val call = IrCallImpl.fromSymbolOwner(UNDEFINED_OFFSET, UNDEFINED_OFFSET, invoke.returnType, invoke.symbol) call.dispatchReceiver = initSymbol.owner.createGetValue()
call.dispatchReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, initSymbol) call.putValueArgument(0, i.toIrConst(environment.irBuiltIns.intType))
call.putValueArgument(0, IrConstImpl.int(UNDEFINED_OFFSET, UNDEFINED_OFFSET, environment.irBuiltIns.intType, i))
instructions += CompoundInstruction(call) instructions += CompoundInstruction(call)
} }
@@ -292,10 +290,10 @@ internal object AssertIntrinsic : IntrinsicBase() {
override fun unwind(irFunction: IrFunction, environment: IrInterpreterEnvironment): List<Instruction> { override fun unwind(irFunction: IrFunction, environment: IrInterpreterEnvironment): List<Instruction> {
if (irFunction.valueParameters.size == 1) return listOf(customEvaluateInstruction(irFunction, environment)) if (irFunction.valueParameters.size == 1) return listOf(customEvaluateInstruction(irFunction, environment))
val messageLambda = environment.callStack.getState(irFunction.valueParameters.last().symbol) as KFunctionState val lambdaParameter = irFunction.valueParameters.last()
val function = messageLambda.irFunction as IrSimpleFunction val lambdaState = environment.callStack.getState(lambdaParameter.symbol) as KFunctionState
environment.callStack.loadUpValues(messageLambda) val call = (lambdaState.invokeSymbol.owner as IrSimpleFunction).createCall()
val call = IrCallImpl.fromSymbolOwner(UNDEFINED_OFFSET, UNDEFINED_OFFSET, function.returnType, function.symbol) call.dispatchReceiver = lambdaParameter.createGetValue()
return listOf(customEvaluateInstruction(irFunction, environment), CompoundInstruction(call)) return listOf(customEvaluateInstruction(irFunction, environment), CompoundInstruction(call))
} }
@@ -5,13 +5,12 @@
package org.jetbrains.kotlin.ir.interpreter.state package org.jetbrains.kotlin.ir.interpreter.state
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
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.IrSimpleFunction import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.interpreter.createCall
import org.jetbrains.kotlin.ir.interpreter.stack.Variable import org.jetbrains.kotlin.ir.interpreter.stack.Variable
import org.jetbrains.kotlin.ir.types.isNullableAny import org.jetbrains.kotlin.ir.types.isNullableAny
import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization
@@ -69,8 +68,7 @@ internal class Common private constructor(override val irClass: IrClass, overrid
} }
fun createToStringIrCall(): IrCall { fun createToStringIrCall(): IrCall {
val toStringFun = getToStringFunction() return getToStringFunction().createCall()
return IrCallImpl.fromSymbolOwner(UNDEFINED_OFFSET, UNDEFINED_OFFSET, toStringFun.returnType, toStringFun.symbol)
} }
override fun toString(): String { override fun toString(): String {
@@ -5,29 +5,25 @@
package org.jetbrains.kotlin.ir.interpreter.state.reflection package org.jetbrains.kotlin.ir.interpreter.state.reflection
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.IrBuiltIns import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
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
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.expressions.putArgument import org.jetbrains.kotlin.ir.expressions.putArgument
import org.jetbrains.kotlin.ir.interpreter.*
import org.jetbrains.kotlin.ir.interpreter.CallInterceptor import org.jetbrains.kotlin.ir.interpreter.CallInterceptor
import org.jetbrains.kotlin.ir.interpreter.TEMP_FUNCTION_FOR_INTERPRETER
import org.jetbrains.kotlin.ir.interpreter.createTempClass
import org.jetbrains.kotlin.ir.interpreter.createTempFunction
import org.jetbrains.kotlin.ir.interpreter.proxy.reflection.KParameterProxy import org.jetbrains.kotlin.ir.interpreter.proxy.reflection.KParameterProxy
import org.jetbrains.kotlin.ir.interpreter.proxy.reflection.KTypeParameterProxy import org.jetbrains.kotlin.ir.interpreter.proxy.reflection.KTypeParameterProxy
import org.jetbrains.kotlin.ir.interpreter.proxy.reflection.KTypeProxy 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.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
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
@@ -51,20 +47,11 @@ internal class KFunctionState(
init { init {
val invokeFunction = irClass.declarations.filterIsInstance<IrSimpleFunction>().single { it.name == OperatorNameConventions.INVOKE } val invokeFunction = irClass.declarations.filterIsInstance<IrSimpleFunction>().single { it.name == OperatorNameConventions.INVOKE }
// TODO do we need new class here? if yes, do we need different names for temp classes? // TODO do we need new class here? if yes, do we need different names for temp classes?
functionClass = IrFactoryImpl.createClass( functionClass = createTempClass(Name.identifier("Function\$0")).apply { parent = irFunction.parent }
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
object : IrDeclarationOriginImpl("TEMP_CLASS_FOR_INTERPRETER") {}, IrClassSymbolImpl(),
Name.identifier("Function\$0"), ClassKind.CLASS, DescriptorVisibilities.PRIVATE, Modality.FINAL
).apply {
parent = irFunction.parent
}
functionClass.superTypes += irClass.defaultType functionClass.superTypes += irClass.defaultType
functionClass.declarations += IrFunctionImpl( functionClass.declarations += createTempFunction(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, OperatorNameConventions.INVOKE, irFunction.returnType, TEMP_FUNCTION_FOR_INTERPRETER
object : IrDeclarationOriginImpl("TEMP_FUNCTION_FOR_INTERPRETER") {}, IrSimpleFunctionSymbolImpl(),
OperatorNameConventions.INVOKE, DescriptorVisibilities.PUBLIC, Modality.FINAL, irFunction.returnType,
isInline = false, isExternal = false, isTailrec = false, isSuspend = false, isOperator = true, isInfix = false, isExpect = false
).apply impl@{ ).apply impl@{
parent = functionClass parent = functionClass
overriddenSymbols = listOf(invokeFunction.symbol) overriddenSymbols = listOf(invokeFunction.symbol)
@@ -72,36 +59,29 @@ internal class KFunctionState(
dispatchReceiverParameter = invokeFunction.dispatchReceiverParameter?.deepCopyWithSymbols(initialParent = this) dispatchReceiverParameter = invokeFunction.dispatchReceiverParameter?.deepCopyWithSymbols(initialParent = this)
valueParameters = mutableListOf() valueParameters = mutableListOf()
val call = when (val symbol = irFunction.symbol) { val call = when (irFunction) {
is IrSimpleFunctionSymbol -> IrCallImpl( is IrSimpleFunction -> irFunction.createCall()
UNDEFINED_OFFSET, UNDEFINED_OFFSET, is IrConstructor -> irFunction.createConstructorCall()
irFunction.returnType, symbol, irFunction.typeParameters.size, irFunction.valueParameters.size
)
is IrConstructorSymbol -> IrConstructorCallImpl.fromSymbolOwner(irFunction.returnType, symbol)
else -> TODO("Unsupported symbol $symbol for invoke") else -> TODO("Unsupported symbol $symbol for invoke")
}.apply { }.apply {
val dispatchParameter = irFunction.dispatchReceiverParameter val dispatchParameter = irFunction.dispatchReceiverParameter
val extensionParameter = irFunction.extensionReceiverParameter val extensionParameter = irFunction.extensionReceiverParameter
if (dispatchParameter != null) { if (dispatchParameter != null) {
dispatchReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, dispatchParameter.type, dispatchParameter.symbol) dispatchReceiver = dispatchParameter.createGetValue()
if (getField(dispatchParameter.symbol) == null) (this@impl.valueParameters as MutableList).add(dispatchParameter) if (getField(dispatchParameter.symbol) == null) (this@impl.valueParameters as MutableList) += dispatchParameter
} }
if (extensionParameter != null) { if (extensionParameter != null) {
extensionReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, extensionParameter.type, extensionParameter.symbol) extensionReceiver = extensionParameter.createGetValue()
if (getField(extensionParameter.symbol) == null) (this@impl.valueParameters as MutableList).add(extensionParameter) if (getField(extensionParameter.symbol) == null) (this@impl.valueParameters as MutableList) += extensionParameter
} }
irFunction.valueParameters.forEach { irFunction.valueParameters.forEach {
putArgument(it, IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, it.type, it.symbol)) putArgument(it, it.createGetValue())
(this@impl.valueParameters as MutableList).add(it) (this@impl.valueParameters as MutableList) += it
} }
} }
body = IrBlockBodyImpl( body = listOf(this.createReturn(call)).wrapWithBlockBody()
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
listOf(IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, this.returnType, this.symbol, call))
)
invokeSymbol = this.symbol invokeSymbol = this.symbol
} }
} }
+4 -3
View File
@@ -2,7 +2,7 @@
fun sum(a: Int = 1, b: Int = 2, c: Int = 3) = a + b + c fun sum(a: Int = 1, b: Int = 2, c: Int = 3) = a + b + c
@CompileTimeCalculation @CompileTimeCalculation
fun sumBasedOnPrevious(a: Int = 1, b: Int = a * 2, c: Int = b * 2) = a + b + c fun sumBasedOnPrevious(a: Int = 1, b: Int = a * 2, c: Int = b * 2, d: Int = b * 2) = a + b + c + d
@CompileTimeCalculation @CompileTimeCalculation
interface A { interface A {
@@ -16,8 +16,9 @@ const val sum1 = <!EVALUATED: `6`!>sum()<!>
const val sum2 = <!EVALUATED: `1`!>sum(b = -3)<!> const val sum2 = <!EVALUATED: `1`!>sum(b = -3)<!>
const val sum3 = <!EVALUATED: `3`!>sum(c = 1, a = 1, b = 1)<!> const val sum3 = <!EVALUATED: `3`!>sum(c = 1, a = 1, b = 1)<!>
const val sumBasedOnPrevious1 = <!EVALUATED: `7`!>sumBasedOnPrevious()<!> const val sumBasedOnPrevious1 = <!EVALUATED: `11`!>sumBasedOnPrevious()<!>
const val sumBasedOnPrevious2 = <!EVALUATED: `3`!>sumBasedOnPrevious(b = 1, c = 1)<!> const val sumBasedOnPrevious2 = <!EVALUATED: `5`!>sumBasedOnPrevious(b = 1, c = 1)<!>
const val sumBasedOnPrevious3 = <!EVALUATED: `8`!>sumBasedOnPrevious(a = 1, c = 1)<!>
const val sumInInterfaceDefault1 = B().<!EVALUATED: `42`!>foo(1)<!> const val sumInInterfaceDefault1 = B().<!EVALUATED: `42`!>foo(1)<!>
const val sumInInterfaceDefault2 = B().<!EVALUATED: `4`!>foo(x = 1, y = 2)<!> const val sumInInterfaceDefault2 = B().<!EVALUATED: `4`!>foo(x = 1, y = 2)<!>