Implement method to calculate EQEQ ir builtin function
This commit is contained in:
committed by
TeamCityServer
parent
9b1f11b22b
commit
4010eb11bd
+25
-5
@@ -173,13 +173,14 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
|
|||||||
val argsType = listOfNotNull(receiverType) + irFunction.valueParameters.map { it.type }
|
val argsType = listOfNotNull(receiverType) + irFunction.valueParameters.map { it.type }
|
||||||
val argsValues = args.map {
|
val argsValues = args.map {
|
||||||
when (it) {
|
when (it) {
|
||||||
|
is Wrapper -> it.value // wrapper can be used in built in calculation, for example, in null or equality checks
|
||||||
is Complex -> when (irFunction.fqNameWhenAvailable?.asString()) {
|
is Complex -> when (irFunction.fqNameWhenAvailable?.asString()) {
|
||||||
// must explicitly convert Common to String in String plus method or else will be taken default toString from Common
|
// must explicitly convert Common to String in String plus method or else will be taken default toString from Common
|
||||||
"kotlin.String.plus" -> stack.apply { interpretToString(it) }.popReturnValue().asString()
|
"kotlin.String.plus" -> stack.apply { interpretToString(it) }.popReturnValue().asString()
|
||||||
else -> it.getOriginal()
|
else -> it.getOriginal()
|
||||||
}
|
}
|
||||||
is Primitive<*> -> it.value
|
is Primitive<*> -> it.value
|
||||||
is Lambda -> it // lambda can be used in built in calculation, for example, in null check or toString
|
is Lambda -> it // lambda also can be used, for example, in null check or toString
|
||||||
else -> TODO("unsupported type of argument for builtins calculations: ${it::class.java}")
|
else -> TODO("unsupported type of argument for builtins calculations: ${it::class.java}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -207,6 +208,7 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
|
|||||||
?: throw InterpreterMethodNotFoundError("For given function $signature there is no entry in binary map")
|
?: throw InterpreterMethodNotFoundError("For given function $signature there is no entry in binary map")
|
||||||
when (methodName) {
|
when (methodName) {
|
||||||
"rangeTo" -> return calculateRangeTo(irFunction.returnType)
|
"rangeTo" -> return calculateRangeTo(irFunction.returnType)
|
||||||
|
"EQEQ" -> return calculateEquals(argsValues[0], argsValues[1])
|
||||||
else -> function.invoke(argsValues[0], argsValues[1])
|
else -> function.invoke(argsValues[0], argsValues[1])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -238,6 +240,24 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun calculateEquals(first: Any?, second: Any?): ExecutionResult {
|
||||||
|
if (first == null || second == null || first !is Common || second !is Common) {
|
||||||
|
return Next.apply { stack.pushReturnValue((first == second).toState(irBuiltIns.booleanType)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
val valueArguments = mutableListOf<Variable>()
|
||||||
|
val equalsFun = first.getEqualsFunction()
|
||||||
|
if (equalsFun.isFakeOverriddenFromAny()) {
|
||||||
|
return Next.apply { stack.pushReturnValue((first == second).toState(irBuiltIns.booleanType)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
equalsFun.getDispatchReceiver()!!.let { valueArguments.add(Variable(it, first)) }
|
||||||
|
valueArguments.add(Variable(equalsFun.valueParameters.single().symbol, second))
|
||||||
|
return stack.newFrame(initPool = valueArguments) {
|
||||||
|
equalsFun.interpret()
|
||||||
|
}.check { return it }
|
||||||
|
}
|
||||||
|
|
||||||
private fun interpretValueParameters(
|
private fun interpretValueParameters(
|
||||||
expression: IrFunctionAccessExpression, irFunction: IrFunction, pool: MutableList<Variable>
|
expression: IrFunctionAccessExpression, irFunction: IrFunction, pool: MutableList<Variable>
|
||||||
): ExecutionResult {
|
): ExecutionResult {
|
||||||
@@ -663,12 +683,12 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
IrTypeOperator.INSTANCEOF -> {
|
IrTypeOperator.INSTANCEOF -> {
|
||||||
val isInstance = isErased || stack.peekReturnValue().isSubtypeOf(typeOperand)
|
val isInstance = stack.popReturnValue().isSubtypeOf(typeOperand) || isErased
|
||||||
stack.pushReturnValue(isInstance.toState(irBuiltIns.nothingType))
|
stack.pushReturnValue(isInstance.toState(irBuiltIns.booleanType))
|
||||||
}
|
}
|
||||||
IrTypeOperator.NOT_INSTANCEOF -> {
|
IrTypeOperator.NOT_INSTANCEOF -> {
|
||||||
val isInstance = isErased || stack.peekReturnValue().isSubtypeOf(typeOperand)
|
val isInstance = stack.popReturnValue().isSubtypeOf(typeOperand) || isErased
|
||||||
stack.pushReturnValue((!isInstance).toState(irBuiltIns.nothingType))
|
stack.pushReturnValue((!isInstance).toState(irBuiltIns.booleanType))
|
||||||
}
|
}
|
||||||
IrTypeOperator.IMPLICIT_NOTNULL -> {
|
IrTypeOperator.IMPLICIT_NOTNULL -> {
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,9 @@ 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.IrSimpleFunction
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
import org.jetbrains.kotlin.ir.types.classOrNull
|
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||||
|
import org.jetbrains.kotlin.ir.types.isNullableAny
|
||||||
import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization
|
import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
internal class Common private constructor(
|
internal class Common private constructor(
|
||||||
override val irClass: IrClass, override val fields: MutableList<Variable>
|
override val irClass: IrClass, override val fields: MutableList<Variable>
|
||||||
@@ -48,6 +50,16 @@ internal class Common private constructor(
|
|||||||
.let { getOverridden(it as IrSimpleFunction, this) }
|
.let { getOverridden(it as IrSimpleFunction, this) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getEqualsFunction(): IrFunction {
|
||||||
|
val equalsFun = irClass.declarations
|
||||||
|
.filterIsInstance<IrSimpleFunction>()
|
||||||
|
.single {
|
||||||
|
it.name == Name.identifier("equals") && it.dispatchReceiverParameter != null
|
||||||
|
&& it.valueParameters.size == 1 && it.valueParameters[0].type.isNullableAny()
|
||||||
|
}
|
||||||
|
return getOverridden(equalsFun, this)
|
||||||
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "Common(obj='${irClass.fqNameForIrSerialization}', super=$superClass, values=$fields)"
|
return "Common(obj='${irClass.fqNameForIrSerialization}', super=$superClass, values=$fields)"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user