Unify logic of creation new ir tree nodes in interpreter
This commit is contained in:
committed by
TeamCityServer
parent
6ce2f8eb14
commit
4ad88679fd
+2
-8
@@ -7,11 +7,8 @@ package org.jetbrains.kotlin.ir.interpreter
|
||||
|
||||
import org.jetbrains.kotlin.ir.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
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.interpretTernaryFunction
|
||||
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.state.*
|
||||
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.classOrNull
|
||||
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
|
||||
|
||||
override fun interceptProxy(irFunction: IrFunction, valueArguments: List<Variable>, expectedResultClass: Class<*>): Any? {
|
||||
val irCall = IrCallImpl.fromSymbolOwner(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, irFunction.returnType, irFunction.symbol as IrSimpleFunctionSymbol
|
||||
)
|
||||
val irCall = irFunction.createCall()
|
||||
return interpreter.withNewCallStack(irCall) {
|
||||
this@withNewCallStack.environment.callStack.addInstruction(SimpleInstruction(irCall))
|
||||
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>) {
|
||||
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 primitiveValueParameters = args.map { it as Primitive<*> }
|
||||
|
||||
+32
-121
@@ -6,30 +6,19 @@
|
||||
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.IrStatement
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
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.impl.*
|
||||
import org.jetbrains.kotlin.ir.interpreter.exceptions.InterpreterError
|
||||
import org.jetbrains.kotlin.ir.interpreter.exceptions.handleUserException
|
||||
import org.jetbrains.kotlin.ir.interpreter.exceptions.verify
|
||||
import org.jetbrains.kotlin.ir.interpreter.stack.CallStack
|
||||
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
|
||||
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.isSubtypeOf
|
||||
import org.jetbrains.kotlin.ir.types.isUnit
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
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) {
|
||||
val irFunction = expression.symbol.owner
|
||||
|
||||
val hasDefaults = (0 until expression.valueArgumentsCount).any { expression.getValueArgument(it) == null }
|
||||
if (hasDefaults) {
|
||||
val visibility = if (expression is IrEnumConstructorCall || expression is IrDelegatingConstructorCall) DescriptorVisibilities.LOCAL else irFunction.visibility
|
||||
val defaultFun = IrFunctionImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER,
|
||||
IrSimpleFunctionSymbolImpl(), Name.identifier(irFunction.name.asString() + "\$default"),
|
||||
visibility, Modality.FINAL, irFunction.returnType,
|
||||
isInline = false, isExternal = false, isTailrec = false, isSuspend = false, isOperator = true, isInfix = false, isExpect = false
|
||||
)
|
||||
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
|
||||
}
|
||||
// if some arguments are not defined, then it is necessary to create temp function where defaults will be evaluated
|
||||
val actualParameters = MutableList<IrValueDeclaration?>(expression.valueArgumentsCount) { null }
|
||||
val ownerWithDefaults = expression.getFunctionThatContainsDefaults()
|
||||
|
||||
val visibility = when (expression) {
|
||||
is IrEnumConstructorCall, is IrDelegatingConstructorCall -> DescriptorVisibilities.LOCAL
|
||||
else -> ownerWithDefaults.visibility
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}, 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 defaultFun = createTempFunction(
|
||||
Name.identifier(ownerWithDefaults.name.asString() + "\$default"), ownerWithDefaults.returnType,
|
||||
origin = IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER, visibility
|
||||
).apply {
|
||||
this.parent = ownerWithDefaults.parent
|
||||
this.dispatchReceiverParameter = ownerWithDefaults.dispatchReceiverParameter?.deepCopyWithSymbols(this)
|
||||
this.extensionReceiverParameter = ownerWithDefaults.extensionReceiverParameter?.deepCopyWithSymbols(this)
|
||||
(0 until expression.valueArgumentsCount).forEach { index ->
|
||||
val parameter = ownerWithDefaults.valueParameters[index]
|
||||
actualParameters[index] = if (expression.getValueArgument(index) != null) {
|
||||
parameter.deepCopyWithSymbols(this).also { this.valueParameters += it }
|
||||
} else {
|
||||
parameter.createTempVariable().apply variable@{
|
||||
this@variable.initializer = parameter.getDefaultWithActualParameters(this@apply, actualParameters)
|
||||
?: expression.getVarargType(index)?.let { null.toIrConst(it) } // if parameter is vararg and it is missing
|
||||
}
|
||||
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(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
variablesForDefault + IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, defaultFun.returnType, defaultFun.symbol, newExpression)
|
||||
)
|
||||
|
||||
val callToDefault = defaultFun.createCall().apply { expression.copyArgsInto(this) }
|
||||
callStack.addInstruction(CompoundInstruction(callToDefault))
|
||||
} else {
|
||||
val irFunction = expression.symbol.owner
|
||||
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.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) }
|
||||
}
|
||||
@@ -311,7 +222,7 @@ private fun unfoldGetValue(expression: IrGetValue, environment: IrInterpreterEnv
|
||||
// used to evaluate constants inside object
|
||||
if (expectedClass != null && expectedClass.isObject && expression.symbol.owner.origin == IrDeclarationOrigin.INSTANCE_RECEIVER) {
|
||||
// TODO is this correct behaviour?
|
||||
val irGetObject = IrGetObjectValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, expectedClass.defaultType, expectedClass.symbol)
|
||||
val irGetObject = expectedClass.createGetObject()
|
||||
return unfoldGetObjectValue(irGetObject, environment)
|
||||
}
|
||||
environment.callStack.pushState(environment.callStack.getState(expression.symbol))
|
||||
|
||||
+174
@@ -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.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.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
import org.jetbrains.kotlin.ir.interpreter.exceptions.handleUserException
|
||||
import org.jetbrains.kotlin.ir.interpreter.proxy.Proxy
|
||||
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.symbols.*
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.types.impl.buildSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
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 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
|
||||
*/
|
||||
@@ -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")
|
||||
internal fun <T> IrConst<T>.toPrimitive(): Primitive<T> = when {
|
||||
type.isByte() -> Primitive((value as Number).toByte() as T, type)
|
||||
@@ -276,3 +212,38 @@ internal fun IrType.getOnlyName(): String {
|
||||
internal fun IrFieldAccessExpression.accessesTopLevelOrObjectField(): Boolean {
|
||||
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)
|
||||
}
|
||||
|
||||
+10
-12
@@ -5,12 +5,11 @@
|
||||
|
||||
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.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.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.stop
|
||||
import org.jetbrains.kotlin.ir.interpreter.state.*
|
||||
@@ -235,10 +234,9 @@ internal object ArrayConstructor : IntrinsicBase() {
|
||||
callStack.setState(initSymbol, state)
|
||||
|
||||
for (i in size - 1 downTo 0) {
|
||||
val invoke = state.invokeSymbol.owner as IrSimpleFunction
|
||||
val call = IrCallImpl.fromSymbolOwner(UNDEFINED_OFFSET, UNDEFINED_OFFSET, invoke.returnType, invoke.symbol)
|
||||
call.dispatchReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, initSymbol)
|
||||
call.putValueArgument(0, IrConstImpl.int(UNDEFINED_OFFSET, UNDEFINED_OFFSET, environment.irBuiltIns.intType, i))
|
||||
val call = (state.invokeSymbol.owner as IrSimpleFunction).createCall()
|
||||
call.dispatchReceiver = initSymbol.owner.createGetValue()
|
||||
call.putValueArgument(0, i.toIrConst(environment.irBuiltIns.intType))
|
||||
instructions += CompoundInstruction(call)
|
||||
}
|
||||
|
||||
@@ -292,10 +290,10 @@ internal object AssertIntrinsic : IntrinsicBase() {
|
||||
override fun unwind(irFunction: IrFunction, environment: IrInterpreterEnvironment): List<Instruction> {
|
||||
if (irFunction.valueParameters.size == 1) return listOf(customEvaluateInstruction(irFunction, environment))
|
||||
|
||||
val messageLambda = environment.callStack.getState(irFunction.valueParameters.last().symbol) as KFunctionState
|
||||
val function = messageLambda.irFunction as IrSimpleFunction
|
||||
environment.callStack.loadUpValues(messageLambda)
|
||||
val call = IrCallImpl.fromSymbolOwner(UNDEFINED_OFFSET, UNDEFINED_OFFSET, function.returnType, function.symbol)
|
||||
val lambdaParameter = irFunction.valueParameters.last()
|
||||
val lambdaState = environment.callStack.getState(lambdaParameter.symbol) as KFunctionState
|
||||
val call = (lambdaState.invokeSymbol.owner as IrSimpleFunction).createCall()
|
||||
call.dispatchReceiver = lambdaParameter.createGetValue()
|
||||
|
||||
return listOf(customEvaluateInstruction(irFunction, environment), CompoundInstruction(call))
|
||||
}
|
||||
|
||||
@@ -5,13 +5,12 @@
|
||||
|
||||
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.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
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.types.isNullableAny
|
||||
import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization
|
||||
@@ -69,8 +68,7 @@ internal class Common private constructor(override val irClass: IrClass, overrid
|
||||
}
|
||||
|
||||
fun createToStringIrCall(): IrCall {
|
||||
val toStringFun = getToStringFunction()
|
||||
return IrCallImpl.fromSymbolOwner(UNDEFINED_OFFSET, UNDEFINED_OFFSET, toStringFun.returnType, toStringFun.symbol)
|
||||
return getToStringFunction().createCall()
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
|
||||
+21
-41
@@ -5,29 +5,25 @@
|
||||
|
||||
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.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.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
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.interpreter.*
|
||||
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.KTypeParameterProxy
|
||||
import org.jetbrains.kotlin.ir.interpreter.proxy.reflection.KTypeProxy
|
||||
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
|
||||
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.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.util.deepCopyWithSymbols
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
@@ -51,20 +47,11 @@ internal class KFunctionState(
|
||||
init {
|
||||
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?
|
||||
functionClass = IrFactoryImpl.createClass(
|
||||
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 = createTempClass(Name.identifier("Function\$0")).apply { parent = irFunction.parent }
|
||||
|
||||
functionClass.superTypes += irClass.defaultType
|
||||
functionClass.declarations += IrFunctionImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
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
|
||||
functionClass.declarations += createTempFunction(
|
||||
OperatorNameConventions.INVOKE, irFunction.returnType, TEMP_FUNCTION_FOR_INTERPRETER
|
||||
).apply impl@{
|
||||
parent = functionClass
|
||||
overriddenSymbols = listOf(invokeFunction.symbol)
|
||||
@@ -72,36 +59,29 @@ internal class KFunctionState(
|
||||
dispatchReceiverParameter = invokeFunction.dispatchReceiverParameter?.deepCopyWithSymbols(initialParent = this)
|
||||
valueParameters = mutableListOf()
|
||||
|
||||
val call = when (val symbol = irFunction.symbol) {
|
||||
is IrSimpleFunctionSymbol -> IrCallImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
irFunction.returnType, symbol, irFunction.typeParameters.size, irFunction.valueParameters.size
|
||||
)
|
||||
is IrConstructorSymbol -> IrConstructorCallImpl.fromSymbolOwner(irFunction.returnType, symbol)
|
||||
val call = when (irFunction) {
|
||||
is IrSimpleFunction -> irFunction.createCall()
|
||||
is IrConstructor -> irFunction.createConstructorCall()
|
||||
else -> TODO("Unsupported symbol $symbol for invoke")
|
||||
}.apply {
|
||||
val dispatchParameter = irFunction.dispatchReceiverParameter
|
||||
val extensionParameter = irFunction.extensionReceiverParameter
|
||||
|
||||
if (dispatchParameter != null) {
|
||||
dispatchReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, dispatchParameter.type, dispatchParameter.symbol)
|
||||
if (getField(dispatchParameter.symbol) == null) (this@impl.valueParameters as MutableList).add(dispatchParameter)
|
||||
dispatchReceiver = dispatchParameter.createGetValue()
|
||||
if (getField(dispatchParameter.symbol) == null) (this@impl.valueParameters as MutableList) += dispatchParameter
|
||||
}
|
||||
if (extensionParameter != null) {
|
||||
extensionReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, extensionParameter.type, extensionParameter.symbol)
|
||||
if (getField(extensionParameter.symbol) == null) (this@impl.valueParameters as MutableList).add(extensionParameter)
|
||||
extensionReceiver = extensionParameter.createGetValue()
|
||||
if (getField(extensionParameter.symbol) == null) (this@impl.valueParameters as MutableList) += extensionParameter
|
||||
}
|
||||
irFunction.valueParameters.forEach {
|
||||
putArgument(it, IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, it.type, it.symbol))
|
||||
(this@impl.valueParameters as MutableList).add(it)
|
||||
putArgument(it, it.createGetValue())
|
||||
(this@impl.valueParameters as MutableList) += it
|
||||
}
|
||||
}
|
||||
|
||||
body = IrBlockBodyImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
listOf(IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, this.returnType, this.symbol, call))
|
||||
)
|
||||
|
||||
body = listOf(this.createReturn(call)).wrapWithBlockBody()
|
||||
invokeSymbol = this.symbol
|
||||
}
|
||||
}
|
||||
|
||||
+4
-3
@@ -2,7 +2,7 @@
|
||||
fun sum(a: Int = 1, b: Int = 2, c: Int = 3) = a + b + c
|
||||
|
||||
@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
|
||||
interface A {
|
||||
@@ -16,8 +16,9 @@ const val sum1 = <!EVALUATED: `6`!>sum()<!>
|
||||
const val sum2 = <!EVALUATED: `1`!>sum(b = -3)<!>
|
||||
const val sum3 = <!EVALUATED: `3`!>sum(c = 1, a = 1, b = 1)<!>
|
||||
|
||||
const val sumBasedOnPrevious1 = <!EVALUATED: `7`!>sumBasedOnPrevious()<!>
|
||||
const val sumBasedOnPrevious2 = <!EVALUATED: `3`!>sumBasedOnPrevious(b = 1, c = 1)<!>
|
||||
const val sumBasedOnPrevious1 = <!EVALUATED: `11`!>sumBasedOnPrevious()<!>
|
||||
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 sumInInterfaceDefault2 = B().<!EVALUATED: `4`!>foo(x = 1, y = 2)<!>
|
||||
|
||||
Reference in New Issue
Block a user