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 argsValues = args.map {
|
||||
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()) {
|
||||
// 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()
|
||||
else -> it.getOriginal()
|
||||
}
|
||||
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}")
|
||||
}
|
||||
}
|
||||
@@ -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")
|
||||
when (methodName) {
|
||||
"rangeTo" -> return calculateRangeTo(irFunction.returnType)
|
||||
"EQEQ" -> return calculateEquals(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(
|
||||
expression: IrFunctionAccessExpression, irFunction: IrFunction, pool: MutableList<Variable>
|
||||
): ExecutionResult {
|
||||
@@ -663,12 +683,12 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
|
||||
}
|
||||
}
|
||||
IrTypeOperator.INSTANCEOF -> {
|
||||
val isInstance = isErased || stack.peekReturnValue().isSubtypeOf(typeOperand)
|
||||
stack.pushReturnValue(isInstance.toState(irBuiltIns.nothingType))
|
||||
val isInstance = stack.popReturnValue().isSubtypeOf(typeOperand) || isErased
|
||||
stack.pushReturnValue(isInstance.toState(irBuiltIns.booleanType))
|
||||
}
|
||||
IrTypeOperator.NOT_INSTANCEOF -> {
|
||||
val isInstance = isErased || stack.peekReturnValue().isSubtypeOf(typeOperand)
|
||||
stack.pushReturnValue((!isInstance).toState(irBuiltIns.nothingType))
|
||||
val isInstance = stack.popReturnValue().isSubtypeOf(typeOperand) || isErased
|
||||
stack.pushReturnValue((!isInstance).toState(irBuiltIns.booleanType))
|
||||
}
|
||||
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.IrSimpleFunction
|
||||
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.name.Name
|
||||
|
||||
internal class Common private constructor(
|
||||
override val irClass: IrClass, override val fields: MutableList<Variable>
|
||||
@@ -48,6 +50,16 @@ internal class Common private constructor(
|
||||
.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 {
|
||||
return "Common(obj='${irClass.fqNameForIrSerialization}', super=$superClass, values=$fields)"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user