org.jetbrains.kotlin.ir.interpreter.proxy.Proxy.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlin-compiler-embeddable Show documentation
Show all versions of kotlin-compiler-embeddable Show documentation
the Kotlin compiler embeddable
/*
* Copyright 2010-2020 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.proxy
import org.jetbrains.kotlin.ir.BuiltInOperatorNames
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.interpreter.CallInterceptor
import org.jetbrains.kotlin.ir.interpreter.fqName
import org.jetbrains.kotlin.ir.interpreter.isPrimitiveArray
import org.jetbrains.kotlin.ir.interpreter.proxy.CommonProxy.Companion.asProxy
import org.jetbrains.kotlin.ir.interpreter.proxy.reflection.ReflectionProxy.Companion.asProxy
import org.jetbrains.kotlin.ir.interpreter.state.*
import org.jetbrains.kotlin.ir.interpreter.state.reflection.ReflectionState
import org.jetbrains.kotlin.ir.types.isArray
import org.jetbrains.kotlin.ir.types.isFloat
import org.jetbrains.kotlin.name.Name
import java.lang.invoke.MethodType
internal interface Proxy {
val state: State
val callInterceptor: CallInterceptor
val environment
get() = callInterceptor.environment
override fun equals(other: Any?): Boolean
override fun hashCode(): Int
override fun toString(): String
}
internal fun State.wrap(callInterceptor: CallInterceptor, remainArraysAsIs: Boolean, extendFrom: Class<*>? = null): Any? {
return when (this) {
is ExceptionState -> this
is Wrapper -> this.value
is Primitive -> when {
this.isNull() -> null
this.type.isArray() || this.type.isPrimitiveArray() -> if (remainArraysAsIs) this else this.value
else -> this.value
}
is Common -> this.asProxy(callInterceptor, extendFrom)
is ReflectionState -> this.asProxy(callInterceptor)
else -> throw AssertionError("${this::class} is unsupported as argument for wrap function")
}
}
private val eqeqName = IrBuiltIns.KOTLIN_INTERNAL_IR_FQN.child(Name.identifier(BuiltInOperatorNames.EQEQ)).asString()
private val checkNotNullName = IrBuiltIns.KOTLIN_INTERNAL_IR_FQN.child(Name.identifier(BuiltInOperatorNames.CHECK_NOT_NULL)).asString()
/**
* Prepare state object to be passed in outer world
*/
internal fun List.wrap(callInterceptor: CallInterceptor, irFunction: IrFunction, methodType: MethodType? = null): List {
val name = irFunction.fqName
if (name == eqeqName && this.any { it is Common }) {
// in case of custom `equals` it is important not to lose information obout type
// so all states remain as is, only common will be converted to Proxy
return mapIndexed { index, state ->
if (state !is Common) return@mapIndexed state
state.wrap(callInterceptor, remainArraysAsIs = true, methodType?.parameterType(index))
}
}
return this.mapIndexed { index, state ->
// don't get arrays from Primitive in case of "set" and "Pair."; information about type will be lost
val unwrapArrays = (name == "kotlin.Array.set" && index != 0) || name == "kotlin.Pair." || name == checkNotNullName
state.wrap(callInterceptor, unwrapArrays, methodType?.parameterType(index))
}
}
internal fun Class<*>.isObject(): Boolean {
return this == java.lang.Object::class.java
}