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.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<*> }
|
||||||
|
|||||||
+32
-121
@@ -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))
|
||||||
|
|||||||
+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.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)
|
||||||
|
}
|
||||||
|
|||||||
+10
-12
@@ -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 {
|
||||||
|
|||||||
+21
-41
@@ -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
@@ -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)<!>
|
||||||
|
|||||||
Reference in New Issue
Block a user