Get rid of abstract and fake override checks in ir call interpretation
For now interpreter will find necessary method for interpretation in one step instead of checking is this method abstract or fake override
This commit is contained in:
+6
-53
@@ -164,51 +164,6 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
||||
return IntrinsicEvaluator().evaluate(irFunction, stack) { this.interpret() }
|
||||
}
|
||||
|
||||
private suspend fun calculateAbstract(irFunction: IrFunction): ExecutionResult {
|
||||
if (irFunction.body == null) {
|
||||
val receiver = stack.getVariableState(irFunction.getReceiver()!!) as Complex
|
||||
val instance = receiver.getOriginal()
|
||||
|
||||
val functionImplementation = instance.getIrFunction(irFunction.descriptor)
|
||||
if (functionImplementation?.body == null) throw InterpreterMethodNotFoundException("Method \"${irFunction.name}\" wasn't implemented")
|
||||
|
||||
val valueArguments = mutableListOf<Variable>()
|
||||
valueArguments.add(Variable(functionImplementation.getReceiver()!!, instance))
|
||||
functionImplementation.valueParameters
|
||||
.map { Variable(it.descriptor, stack.getVariableState(it.descriptor)) }
|
||||
.forEach { valueArguments.add(it) }
|
||||
return stack.newFrame(asSubFrame = true, initPool = valueArguments) {
|
||||
functionImplementation.interpret()
|
||||
}
|
||||
}
|
||||
return irFunction.body!!.interpret()
|
||||
}
|
||||
|
||||
private suspend fun calculateOverridden(owner: IrSimpleFunction): ExecutionResult {
|
||||
val variableDescriptor = owner.getReceiver()!!
|
||||
val superQualifier = (stack.getVariableState(variableDescriptor) as? Complex)?.superClass
|
||||
if (superQualifier == null) {
|
||||
// superQualifier is null for exception state => find method in builtins
|
||||
return calculateBuiltIns(owner.getLastOverridden() as IrSimpleFunction)
|
||||
}
|
||||
val overridden = owner.overriddenSymbols.single()
|
||||
|
||||
val valueArguments = mutableListOf<Variable>()
|
||||
valueArguments.add(Variable(overridden.owner.getReceiver()!!, superQualifier))
|
||||
owner.valueParameters.zip(overridden.owner.valueParameters)
|
||||
.map { Variable(it.second.descriptor, stack.getVariableState(it.first.descriptor)) }
|
||||
.forEach { valueArguments.add(it) }
|
||||
|
||||
return stack.newFrame(asSubFrame = true, initPool = valueArguments) {
|
||||
val overriddenOwner = overridden.owner
|
||||
return@newFrame when {
|
||||
overriddenOwner.body != null -> overriddenOwner.interpret()
|
||||
superQualifier.superClass == null -> calculateBuiltIns(overriddenOwner)
|
||||
else -> calculateOverridden(overriddenOwner)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun calculateBuiltIns(irFunction: IrFunction): ExecutionResult {
|
||||
val descriptor = irFunction.descriptor
|
||||
val methodName = when (val property = (irFunction as? IrSimpleFunction)?.correspondingPropertySymbol) {
|
||||
@@ -286,7 +241,7 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
||||
return stack.newFrame(asSubFrame = true, initPool = pool) {
|
||||
for (i in valueArguments.indices) {
|
||||
(valueArguments[i] ?: defaultValues[i])?.interpret()?.check { return@newFrame it }
|
||||
?: stack.pushReturnValue(listOf<Any?>().toPrimitiveStateArray(expression.getVarargType(i)!!))
|
||||
?: stack.pushReturnValue(listOf<Any?>().toPrimitiveStateArray(expression.getVarargType(i)!!)) // if vararg is empty
|
||||
|
||||
with(Variable(valueParametersDescriptors[i], stack.popReturnValue())) {
|
||||
stack.addVar(this) //must add value argument in current stack because it can be used later as default argument
|
||||
@@ -309,9 +264,9 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
||||
rawExtensionReceiver?.interpret()?.check { return it }
|
||||
val extensionReceiver = rawExtensionReceiver?.let { stack.popReturnValue() }
|
||||
|
||||
// find correct ir function
|
||||
val functionReceiver = dispatchReceiver?.getFunctionReceiver(expression.superQualifierSymbol?.owner)
|
||||
val irFunction = functionReceiver?.getIrFunction(expression.symbol.descriptor) ?: expression.symbol.owner
|
||||
// get correct ir function
|
||||
val irFunction = dispatchReceiver?.getIrFunctionByIrCall(expression) ?: expression.symbol.owner
|
||||
val functionReceiver = dispatchReceiver.getCorrectReceiverByFunction(irFunction)
|
||||
|
||||
// it is important firstly to add receiver, then arguments; this order is used in builtin method call
|
||||
irFunction.getDispatchReceiver()?.let { functionReceiver?.let { receiver -> valueArguments.add(Variable(it, receiver)) } }
|
||||
@@ -332,9 +287,7 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
||||
return@newFrame when {
|
||||
dispatchReceiver is Wrapper && !isInlineOnly -> dispatchReceiver.getMethod(irFunction).invokeMethod(irFunction)
|
||||
irFunction.hasAnnotation(evaluateIntrinsicAnnotation) -> Wrapper.getStaticMethod(irFunction).invokeMethod(irFunction)
|
||||
irFunction.isAbstract() -> calculateAbstract(irFunction) //abstract check must be before fake overridden check
|
||||
irFunction.isFakeOverridden() -> calculateOverridden(irFunction as IrSimpleFunction)
|
||||
irFunction.body == null || dispatchReceiver is Primitive<*> -> calculateBuiltIns(irFunction) // is Primitive because of js char and long
|
||||
irFunction.body == null || dispatchReceiver is Primitive<*> -> calculateBuiltIns(irFunction) // 'is Primitive' because of js char and long
|
||||
else -> irFunction.interpret()
|
||||
}
|
||||
}
|
||||
@@ -730,7 +683,7 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
||||
is Common -> {
|
||||
val toStringFun = returnValue.getToStringFunction()
|
||||
stack.newFrame(initPool = mutableListOf(Variable(toStringFun.getReceiver()!!, returnValue))) {
|
||||
toStringFun.body?.let { toStringFun.interpret() } ?: calculateOverridden(toStringFun)
|
||||
toStringFun.body?.let { toStringFun.interpret() } ?: calculateBuiltIns(toStringFun)
|
||||
}.check { executionResult -> return executionResult }
|
||||
stack.popReturnValue().asString()
|
||||
}
|
||||
|
||||
+15
-36
@@ -12,20 +12,15 @@ import org.jetbrains.kotlin.builtins.UnsignedTypes
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
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.descriptors.WrappedReceiverParameterDescriptor
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization
|
||||
import org.jetbrains.kotlin.ir.util.isFakeOverride
|
||||
import org.jetbrains.kotlin.ir.util.isInterface
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
|
||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
// main purpose is to get receiver from constructor call
|
||||
@@ -50,7 +45,7 @@ fun IrFunctionAccessExpression.getBody(): IrBody? {
|
||||
}
|
||||
|
||||
fun DeclarationDescriptor.equalTo(other: DeclarationDescriptor): Boolean {
|
||||
return this.isSubtypeOf(other) || this.hasSameNameAs(other) || this == other
|
||||
return this.isEqualByReceiverTo(other) || this.hasSameNameAs(other) || this == other
|
||||
}
|
||||
|
||||
private fun WrappedReceiverParameterDescriptor.isEqualTo(other: DeclarationDescriptor): Boolean {
|
||||
@@ -60,14 +55,14 @@ private fun WrappedReceiverParameterDescriptor.isEqualTo(other: DeclarationDescr
|
||||
}
|
||||
}
|
||||
|
||||
private fun DeclarationDescriptor.isSubtypeOf(other: DeclarationDescriptor): Boolean {
|
||||
private fun DeclarationDescriptor.isEqualByReceiverTo(other: DeclarationDescriptor): Boolean {
|
||||
if (this !is ReceiverParameterDescriptor || other !is ReceiverParameterDescriptor) return false
|
||||
return when {
|
||||
this is WrappedReceiverParameterDescriptor && other is WrappedReceiverParameterDescriptor ->
|
||||
this.isEqualTo(other) || other.isEqualTo(this)
|
||||
this is WrappedReceiverParameterDescriptor -> this.isEqualTo(other)
|
||||
other is WrappedReceiverParameterDescriptor -> other.isEqualTo(this)
|
||||
this.value is ImplicitClassReceiver && other.value is ImplicitClassReceiver -> this.value.type.isSubtypeOf(other.value.type)
|
||||
this.value is ImplicitClassReceiver && other.value is ImplicitClassReceiver -> this.value.type == other.value.type
|
||||
this.value is ExtensionReceiver && other.value is ExtensionReceiver -> this.value == other.value
|
||||
else -> false
|
||||
}
|
||||
@@ -81,14 +76,6 @@ private fun DeclarationDescriptor.hasSameNameAs(other: DeclarationDescriptor): B
|
||||
this.name == other.name)
|
||||
}
|
||||
|
||||
fun IrFunction.isAbstract(): Boolean {
|
||||
return (this as? IrSimpleFunction)?.modality == Modality.ABSTRACT
|
||||
}
|
||||
|
||||
fun IrFunction.isFakeOverridden(): Boolean {
|
||||
return this.isFakeOverride
|
||||
}
|
||||
|
||||
fun State.toIrExpression(expression: IrExpression): IrExpression {
|
||||
val start = expression.startOffset
|
||||
val end = expression.endOffset
|
||||
@@ -177,7 +164,7 @@ fun getPrimitiveClass(fqName: String, asObject: Boolean = false): Class<*>? {
|
||||
}
|
||||
|
||||
fun IrType.getFqName(): String? {
|
||||
return this.classOrNull?.owner?.fqNameForIrSerialization?.asString()
|
||||
return this.classOrNull?.owner?.fqNameWhenAvailable?.asString()
|
||||
}
|
||||
|
||||
fun IrFunction.getArgsForMethodInvocation(args: List<Variable>): List<Any?> {
|
||||
@@ -202,13 +189,9 @@ fun IrFunction.getArgsForMethodInvocation(args: List<Variable>): List<Any?> {
|
||||
}
|
||||
|
||||
fun IrFunction.getLastOverridden(): IrFunction {
|
||||
if (this !is IrFunctionImpl) return this
|
||||
if (this !is IrSimpleFunction) return this
|
||||
|
||||
var function = this as IrFunctionImpl
|
||||
while (function.overriddenSymbols.isNotEmpty()) {
|
||||
function = function.overriddenSymbols.first().owner as IrFunctionImpl
|
||||
}
|
||||
return function
|
||||
return generateSequence(listOf(this)) { it.firstOrNull()?.overriddenSymbols?.map { it.owner } }.flatten().last()
|
||||
}
|
||||
|
||||
fun List<Any?>.toPrimitiveStateArray(type: IrType): Primitive<*> {
|
||||
@@ -225,18 +208,6 @@ fun List<Any?>.toPrimitiveStateArray(type: IrType): Primitive<*> {
|
||||
}
|
||||
}
|
||||
|
||||
fun State?.getFunctionReceiver(superIrClass: IrClass?): State? {
|
||||
return when {
|
||||
superIrClass == null -> this
|
||||
superIrClass.isInterface -> {
|
||||
val interfaceState = Common(superIrClass)
|
||||
(this!!.copy() as Complex).setSuperClassInstance(interfaceState)
|
||||
interfaceState
|
||||
}
|
||||
else -> (this as Complex).superClass
|
||||
}
|
||||
}
|
||||
|
||||
fun IrFunctionAccessExpression.getVarargType(index: Int): IrType? {
|
||||
val varargType = this.symbol.owner.valueParameters[index].varargElementType ?: return null
|
||||
varargType.classOrNull?.let { return this.symbol.owner.valueParameters[index].type }
|
||||
@@ -268,4 +239,12 @@ fun State?.extractNonLocalDeclarations(): List<Variable> {
|
||||
this ?: return listOf()
|
||||
val state = this.takeIf { it !is Complex } ?: (this as Complex).getOriginal()
|
||||
return state.fields.filterNot { it.descriptor.containingDeclaration == state.irClass.descriptor }
|
||||
}
|
||||
|
||||
fun State?.getCorrectReceiverByFunction(irFunction: IrFunction): State? {
|
||||
if (this !is Complex) return this
|
||||
|
||||
val original: Complex? = this.getOriginal()
|
||||
val other = irFunction.dispatchReceiverParameter?.descriptor ?: return this
|
||||
return generateSequence(original) { it.superClass }.firstOrNull { it.irClass.descriptor.thisAsReceiverParameter.equalTo(other) } ?: this
|
||||
}
|
||||
+1
-1
@@ -137,7 +137,7 @@ object RegexReplace : IntrinsicBase() {
|
||||
object EnumHashCode : IntrinsicBase() {
|
||||
override fun equalTo(irFunction: IrFunction): Boolean {
|
||||
val fqName = irFunction.fqNameWhenAvailable.toString()
|
||||
return fqName.endsWith(".hashCode") && irFunction.parentAsClass.isEnumClass
|
||||
return fqName == "kotlin.Enum.hashCode"
|
||||
}
|
||||
|
||||
override suspend fun evaluate(
|
||||
|
||||
+6
-3
@@ -5,12 +5,14 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.common.interpreter.state
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.getLastOverridden
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.stack.Variable
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
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.types.classOrNull
|
||||
import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization
|
||||
import org.jetbrains.kotlin.ir.util.isFakeOverride
|
||||
import org.jetbrains.kotlin.ir.util.isInterface
|
||||
|
||||
class Common private constructor(
|
||||
@@ -42,10 +44,11 @@ class Common private constructor(
|
||||
return owner
|
||||
}
|
||||
|
||||
fun getToStringFunction(): IrFunctionImpl {
|
||||
fun getToStringFunction(): IrFunction {
|
||||
return irClass.declarations.filterIsInstance<IrFunction>()
|
||||
.filter { it.descriptor.name.asString() == "toString" }
|
||||
.first { it.descriptor.valueParameters.isEmpty() } as IrFunctionImpl
|
||||
.first { it.descriptor.valueParameters.isEmpty() }
|
||||
.let { getOverridden(it as IrSimpleFunction, this) }
|
||||
}
|
||||
|
||||
override fun copy(): State {
|
||||
|
||||
+42
-1
@@ -6,12 +6,17 @@
|
||||
package org.jetbrains.kotlin.backend.common.interpreter.state
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.equalTo
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.getLastOverridden
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.getCorrectReceiverByFunction
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.stack.Variable
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
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.util.fqNameForIrSerialization
|
||||
import org.jetbrains.kotlin.ir.util.isInterface
|
||||
|
||||
abstract class Complex(
|
||||
override val irClass: IrClass, override val fields: MutableList<Variable>, var superClass: Complex?, var subClass: Complex?
|
||||
@@ -47,9 +52,45 @@ abstract class Complex(
|
||||
}
|
||||
}
|
||||
|
||||
override fun getIrFunction(descriptor: FunctionDescriptor): IrFunction? {
|
||||
private fun getIrFunction(descriptor: FunctionDescriptor): IrFunction? {
|
||||
val propertyGetters = irClass.declarations.filterIsInstance<IrProperty>().mapNotNull { it.getter }
|
||||
val functions = irClass.declarations.filterIsInstance<IrFunction>()
|
||||
return (propertyGetters + functions).singleOrNull { it.descriptor.equalTo(descriptor) }
|
||||
}
|
||||
|
||||
private fun getThisOrSuperReceiver(superIrClass: IrClass?): Complex? {
|
||||
return when {
|
||||
superIrClass == null -> this.getOriginal()
|
||||
superIrClass.isInterface -> {
|
||||
val interfaceState = Common(superIrClass)
|
||||
(this.copy() as Complex).setSuperClassInstance(interfaceState)
|
||||
interfaceState
|
||||
}
|
||||
else -> this.superClass
|
||||
}
|
||||
}
|
||||
|
||||
protected fun getOverridden(owner: IrSimpleFunction, qualifier: State?): IrSimpleFunction {
|
||||
if (!owner.isFakeOverride) return owner
|
||||
if (qualifier == null || qualifier is ExceptionState || (qualifier as? Complex)?.superClass == null) {
|
||||
return owner.getLastOverridden() as IrSimpleFunction
|
||||
}
|
||||
|
||||
val overriddenOwner = owner.overriddenSymbols.single().owner
|
||||
return when {
|
||||
overriddenOwner.body != null -> overriddenOwner
|
||||
else -> getOverridden(overriddenOwner, qualifier.superClass!!)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getIrFunctionByIrCall(expression: IrCall): IrFunction? {
|
||||
val receiver = getThisOrSuperReceiver(expression.superQualifierSymbol?.owner) ?: return null
|
||||
|
||||
val irFunction = receiver.getIrFunction(expression.symbol.descriptor) ?: return null
|
||||
|
||||
return when (irFunction.body) {
|
||||
null -> getOverridden(irFunction as IrSimpleFunction, this.getCorrectReceiverByFunction(irFunction))
|
||||
else -> irFunction
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -7,9 +7,9 @@ package org.jetbrains.kotlin.backend.common.interpreter.state
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.equalTo
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.stack.Variable
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization
|
||||
import org.jetbrains.kotlin.ir.util.nameForIrSerialization
|
||||
|
||||
@@ -23,8 +23,8 @@ class Lambda(val irFunction: IrFunction, override val irClass: IrClass) : State
|
||||
throw UnsupportedOperationException("Method setState is not supported in Lambda class")
|
||||
}
|
||||
|
||||
override fun getIrFunction(descriptor: FunctionDescriptor): IrFunction? {
|
||||
return if (invokeDescriptor.equalTo(descriptor)) irFunction else null
|
||||
override fun getIrFunctionByIrCall(expression: IrCall): IrFunction? {
|
||||
return if (invokeDescriptor.equalTo(expression.symbol.descriptor)) irFunction else null
|
||||
}
|
||||
|
||||
override fun copy(): State {
|
||||
|
||||
+6
-2
@@ -5,14 +5,16 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.common.interpreter.state
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.getLastOverridden
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.stack.Variable
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
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.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||
import org.jetbrains.kotlin.ir.util.isFakeOverride
|
||||
|
||||
class Primitive<T>(var value: T, val type: IrType) : State {
|
||||
override val fields: MutableList<Variable> = mutableListOf()
|
||||
@@ -31,12 +33,14 @@ class Primitive<T>(var value: T, val type: IrType) : State {
|
||||
return Primitive(value, type)
|
||||
}
|
||||
|
||||
override fun getIrFunction(descriptor: FunctionDescriptor): IrFunction? {
|
||||
override fun getIrFunctionByIrCall(expression: IrCall): IrFunction? {
|
||||
val descriptor = expression.symbol.descriptor
|
||||
// must add property's getter to declaration's list because they are not present in ir class for primitives
|
||||
val declarations = irClass.declarations.map { if (it is IrProperty) it.getter else it }
|
||||
return declarations.filterIsInstance<IrFunction>()
|
||||
.filter { it.descriptor.name == descriptor.name }
|
||||
.firstOrNull { it.descriptor.valueParameters.map { it.type } == descriptor.valueParameters.map { it.type } }
|
||||
?.let { if (it.isFakeOverride) it.getLastOverridden() else it }
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
|
||||
+2
-2
@@ -8,9 +8,9 @@ package org.jetbrains.kotlin.backend.common.interpreter.state
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.equalTo
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.stack.Variable
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
|
||||
interface State {
|
||||
val fields: MutableList<Variable>
|
||||
@@ -31,7 +31,7 @@ interface State {
|
||||
*/
|
||||
fun copy(): State
|
||||
|
||||
fun getIrFunction(descriptor: FunctionDescriptor): IrFunction?
|
||||
fun getIrFunctionByIrCall(expression: IrCall): IrFunction?
|
||||
}
|
||||
|
||||
fun State.asInt() = (this as Primitive<*>).value as Int
|
||||
|
||||
Reference in New Issue
Block a user