Implement LambdaProxy class
This commit is contained in:
committed by
TeamCityServer
parent
1d0acedc48
commit
96a090f2ab
+19
-59
@@ -16,6 +16,10 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl
|
||||
import org.jetbrains.kotlin.ir.interpreter.builtins.*
|
||||
import org.jetbrains.kotlin.ir.interpreter.exceptions.*
|
||||
import org.jetbrains.kotlin.ir.interpreter.intrinsics.IntrinsicEvaluator
|
||||
import org.jetbrains.kotlin.ir.interpreter.proxy.CommonProxy
|
||||
import org.jetbrains.kotlin.ir.interpreter.proxy.LambdaProxy.Companion.asProxy
|
||||
import org.jetbrains.kotlin.ir.interpreter.proxy.Proxy
|
||||
import org.jetbrains.kotlin.ir.interpreter.proxy.unwrap
|
||||
import org.jetbrains.kotlin.ir.interpreter.stack.StackImpl
|
||||
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
|
||||
import org.jetbrains.kotlin.ir.interpreter.state.*
|
||||
@@ -89,62 +93,14 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* calledFromBuiltIns - used to avoid cyclic calls. For example:
|
||||
* override fun toString(): String {
|
||||
* return super.toString()
|
||||
* }
|
||||
*/
|
||||
internal class Proxy(val state: Common, val interpreter: IrInterpreter, private val calledFromBuiltIns: Boolean = false) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as Proxy
|
||||
|
||||
val valueArguments = mutableListOf<Variable>()
|
||||
val equalsFun = state.getEqualsFunction()
|
||||
if (equalsFun.isFakeOverriddenFromAny() || calledFromBuiltIns) return this.state === other.state
|
||||
|
||||
equalsFun.getDispatchReceiver()!!.let { valueArguments.add(Variable(it, state)) }
|
||||
valueArguments.add(Variable(equalsFun.valueParameters.single().symbol, other.state))
|
||||
|
||||
return with(interpreter) {
|
||||
stack.newFrame(initPool = valueArguments) {
|
||||
equalsFun.interpret()
|
||||
}
|
||||
(stack.popReturnValue() as Primitive<*>).value as Boolean
|
||||
} // TODO check
|
||||
internal fun IrFunction.interpret(valueArguments: List<Variable>): Any? {
|
||||
val returnLabel = stack.newFrame(initPool = valueArguments) {
|
||||
this@interpret.interpret()
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
val valueArguments = mutableListOf<Variable>()
|
||||
val hashCodeFun = state.getHashCodeFunction()
|
||||
if (hashCodeFun.isFakeOverriddenFromAny() || calledFromBuiltIns) return System.identityHashCode(state)
|
||||
|
||||
hashCodeFun.getDispatchReceiver()!!.let { valueArguments.add(Variable(it, state)) }
|
||||
return with(interpreter) {
|
||||
stack.newFrame(initPool = valueArguments) {
|
||||
hashCodeFun.interpret()
|
||||
}
|
||||
(stack.popReturnValue() as Primitive<*>).value as Int
|
||||
}// TODO check
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
val valueArguments = mutableListOf<Variable>()
|
||||
val toStringFun = state.getToStringFunction()
|
||||
if (toStringFun.isFakeOverriddenFromAny() || calledFromBuiltIns) {
|
||||
return "${state.irClass.internalName()}@" + hashCode().toString(16).padStart(8, '0')
|
||||
}
|
||||
|
||||
toStringFun.getDispatchReceiver()!!.let { valueArguments.add(Variable(it, state)) }
|
||||
return with(interpreter) {
|
||||
stack.newFrame(initPool = valueArguments) {
|
||||
toStringFun.interpret()
|
||||
}
|
||||
(stack.popReturnValue() as Primitive<*>).value as String
|
||||
}// TODO check
|
||||
return when (returnLabel.returnLabel) {
|
||||
ReturnLabel.REGULAR -> stack.popReturnValue().unwrap(this@IrInterpreter)
|
||||
ReturnLabel.EXCEPTION -> throw stack.popReturnValue() as ExceptionState
|
||||
else -> TODO("$returnLabel not supported as result of interpretation")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,8 +109,8 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
|
||||
is ExceptionState -> this
|
||||
is Wrapper -> this.value
|
||||
is Primitive<*> -> this.value
|
||||
is Common -> Proxy(this, this@IrInterpreter, calledFromBuiltIns)
|
||||
is Lambda -> this // TODO as Proxy
|
||||
is Common -> CommonProxy(this, this@IrInterpreter, calledFromBuiltIns)
|
||||
is Lambda -> this.asProxy(this@IrInterpreter)
|
||||
else -> throw AssertionError("${this::class} is unsupported as argument for wrap function")
|
||||
}
|
||||
}
|
||||
@@ -350,7 +306,7 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
|
||||
// dispatch receiver processing
|
||||
val rawDispatchReceiver = expression.dispatchReceiver
|
||||
rawDispatchReceiver?.interpret()?.check { return it }
|
||||
val dispatchReceiver = rawDispatchReceiver?.let { stack.popReturnValue() }?.checkNullability(expression.dispatchReceiver?.type)
|
||||
var dispatchReceiver = rawDispatchReceiver?.let { stack.popReturnValue() }?.checkNullability(expression.dispatchReceiver?.type)
|
||||
|
||||
// extension receiver processing
|
||||
val rawExtensionReceiver = expression.extensionReceiver
|
||||
@@ -358,6 +314,10 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
|
||||
val extensionReceiver = rawExtensionReceiver?.let { stack.popReturnValue() }?.checkNullability(expression.extensionReceiver?.type)
|
||||
|
||||
val irFunction = dispatchReceiver?.getIrFunctionByIrCall(expression) ?: expression.symbol.owner
|
||||
dispatchReceiver = when (irFunction.parent) {
|
||||
(dispatchReceiver as? Complex)?.superWrapperClass?.irClass -> dispatchReceiver.superWrapperClass
|
||||
else -> dispatchReceiver
|
||||
}
|
||||
|
||||
// it is important firstly to add receiver, then arguments; this order is used in builtin method call
|
||||
irFunction.getDispatchReceiver()?.let { dispatchReceiver?.let { receiver -> valueArguments.add(Variable(it, receiver)) } }
|
||||
@@ -774,7 +734,7 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
|
||||
is Primitive<*> -> arrayToList(result.value)
|
||||
is Common -> when {
|
||||
result.irClass.defaultType.isUnsignedArray() -> arrayToList((result.fields.single().state as Primitive<*>).value)
|
||||
else -> listOf(Proxy(result, this))
|
||||
else -> listOf(CommonProxy(result, this))
|
||||
}
|
||||
else -> listOf(result)
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.ir.interpreter.builtins.evaluateIntrinsicAnnotation
|
||||
import org.jetbrains.kotlin.ir.interpreter.exceptions.throwAsUserException
|
||||
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
|
||||
import org.jetbrains.kotlin.ir.interpreter.state.*
|
||||
import org.jetbrains.kotlin.ir.interpreter.proxy.Proxy
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
@@ -57,7 +58,7 @@ internal fun State.toIrExpression(expression: IrExpression): IrExpression {
|
||||
|
||||
internal fun Any?.toState(irType: IrType): State {
|
||||
return when (this) {
|
||||
is IrInterpreter.Proxy -> this.state
|
||||
is Proxy -> this.state
|
||||
is State -> this
|
||||
is Boolean, is Char, is Byte, is Short, is Int, is Long, is String, is Float, is Double, is Array<*>, is ByteArray,
|
||||
is CharArray, is ShortArray, is IntArray, is LongArray, is FloatArray, is DoubleArray, is BooleanArray -> Primitive(this, irType)
|
||||
@@ -197,6 +198,7 @@ internal fun IrType.isPrimitiveArray(): Boolean {
|
||||
}
|
||||
|
||||
internal fun IrType.isFunction() = this.getClass()?.fqNameWhenAvailable?.asString()?.startsWith("kotlin.Function") ?: false
|
||||
internal fun IrType.isKFunction() = this.getClass()?.fqNameWhenAvailable?.asString()?.startsWith("kotlin.reflect.KFunction") ?: false
|
||||
|
||||
internal fun IrType.isTypeParameter() = classifierOrNull is IrTypeParameterSymbol
|
||||
|
||||
|
||||
+2
-2
@@ -16,7 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.interpreter.builtins
|
||||
|
||||
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
|
||||
import org.jetbrains.kotlin.ir.interpreter.proxy.Proxy
|
||||
|
||||
/** This file is generated by org.jetbrains.kotlin.backend.common.interpreter.builtins.GenerateBuiltInsMap.generateMap(). DO NOT MODIFY MANUALLY */
|
||||
|
||||
@@ -447,7 +447,7 @@ val binaryFunctions = mapOf<CompileTimeFunction, Function2<Any?, Any?, Any?>>(
|
||||
binaryOperation<Long, Long>("greaterOrEqual", "Long", "Long") { a, b -> a >= b },
|
||||
binaryOperation<Double, Double>("greaterOrEqual", "Double", "Double") { a, b -> a >= b },
|
||||
binaryOperation<Any?, Any?>("EQEQ", "Any?", "Any?") { a, b -> a == b },
|
||||
binaryOperation<Any?, Any?>("EQEQEQ", "Any?", "Any?") { a, b -> if (a is IrInterpreter.Proxy && b is IrInterpreter.Proxy) a.state === b.state else a === b },
|
||||
binaryOperation<Any?, Any?>("EQEQEQ", "Any?", "Any?") { a, b -> if (a is Proxy && b is Proxy) a.state === b.state else a === b },
|
||||
binaryOperation<Float?, Float?>("ieee754equals", "Float?", "Float?") { a, b -> a == b },
|
||||
binaryOperation<Double?, Double?>("ieee754equals", "Double?", "Double?") { a, b -> a == b },
|
||||
binaryOperation<Boolean, Boolean>("ANDAND", "Boolean", "Boolean") { a, b -> a && b },
|
||||
|
||||
-1
@@ -19,7 +19,6 @@ internal class IntrinsicEvaluator {
|
||||
ArrayOfNulls.equalTo(irFunction) -> ArrayOfNulls.evaluate(irFunction, stack, interpret)
|
||||
EnumValues.equalTo(irFunction) -> EnumValues.evaluate(irFunction, stack, interpret)
|
||||
EnumValueOf.equalTo(irFunction) -> EnumValueOf.evaluate(irFunction, stack, interpret)
|
||||
RegexReplace.equalTo(irFunction) -> RegexReplace.evaluate(irFunction, stack, interpret)
|
||||
EnumHashCode.equalTo(irFunction) -> EnumHashCode.evaluate(irFunction, stack, interpret)
|
||||
JsPrimitives.equalTo(irFunction) -> JsPrimitives.evaluate(irFunction, stack, interpret)
|
||||
ArrayConstructor.equalTo(irFunction) -> ArrayConstructor.evaluate(irFunction, stack, interpret)
|
||||
|
||||
-22
@@ -105,28 +105,6 @@ internal object EnumValueOf : IntrinsicBase() {
|
||||
}
|
||||
}
|
||||
|
||||
internal object RegexReplace : IntrinsicBase() {
|
||||
override fun equalTo(irFunction: IrFunction): Boolean {
|
||||
val fqName = irFunction.fqNameWhenAvailable.toString()
|
||||
return fqName == "kotlin.text.Regex.replace" && irFunction.valueParameters.size == 2
|
||||
}
|
||||
|
||||
override fun evaluate(irFunction: IrFunction, stack: Stack, interpret: IrElement.() -> ExecutionResult): ExecutionResult {
|
||||
val states = stack.getAll().map { it.state }
|
||||
val regex = states.filterIsInstance<Wrapper>().single().value as Regex
|
||||
val input = states.filterIsInstance<Primitive<*>>().single().asString()
|
||||
val transform = states.filterIsInstance<Lambda>().single().irFunction
|
||||
val matchResultParameter = transform.valueParameters.single()
|
||||
val result = regex.replace(input) {
|
||||
val itAsState = Variable(matchResultParameter.symbol, Wrapper(it, matchResultParameter.type.classOrNull!!.owner))
|
||||
stack.newFrame(initPool = listOf(itAsState)) { transform.interpret() }//.check { return it }
|
||||
stack.popReturnValue().asString()
|
||||
}
|
||||
stack.pushReturnValue(result.toState(irFunction.returnType))
|
||||
return Next
|
||||
}
|
||||
}
|
||||
|
||||
internal object EnumHashCode : IntrinsicBase() {
|
||||
override fun equalTo(irFunction: IrFunction): Boolean {
|
||||
val fqName = irFunction.fqNameWhenAvailable.toString()
|
||||
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.interpreter.IrInterpreter
|
||||
import org.jetbrains.kotlin.ir.interpreter.getDispatchReceiver
|
||||
import org.jetbrains.kotlin.ir.interpreter.internalName
|
||||
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
|
||||
import org.jetbrains.kotlin.ir.interpreter.state.Common
|
||||
import org.jetbrains.kotlin.ir.util.isFakeOverriddenFromAny
|
||||
|
||||
/**
|
||||
* calledFromBuiltIns - used to avoid cyclic calls. For example:
|
||||
* override fun toString(): String {
|
||||
* return super.toString()
|
||||
* }
|
||||
*/
|
||||
internal class CommonProxy(override val state: Common, override val interpreter: IrInterpreter, private val calledFromBuiltIns: Boolean = false): Proxy {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as CommonProxy
|
||||
|
||||
val valueArguments = mutableListOf<Variable>()
|
||||
val equalsFun = state.getEqualsFunction()
|
||||
if (equalsFun.isFakeOverriddenFromAny() || calledFromBuiltIns) return this.state === other.state
|
||||
|
||||
equalsFun.getDispatchReceiver()!!.let { valueArguments.add(Variable(it, state)) }
|
||||
valueArguments.add(Variable(equalsFun.valueParameters.single().symbol, other.state))
|
||||
|
||||
return with(interpreter) { equalsFun.interpret(valueArguments) } as Boolean
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
val valueArguments = mutableListOf<Variable>()
|
||||
val hashCodeFun = state.getHashCodeFunction()
|
||||
if (hashCodeFun.isFakeOverriddenFromAny() || calledFromBuiltIns) return System.identityHashCode(state)
|
||||
|
||||
hashCodeFun.getDispatchReceiver()!!.let { valueArguments.add(Variable(it, state)) }
|
||||
return with(interpreter) { hashCodeFun.interpret(valueArguments) } as Int
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
val valueArguments = mutableListOf<Variable>()
|
||||
val toStringFun = state.getToStringFunction()
|
||||
if (toStringFun.isFakeOverriddenFromAny() || calledFromBuiltIns) {
|
||||
return "${state.irClass.internalName()}@" + hashCode().toString(16).padStart(8, '0')
|
||||
}
|
||||
|
||||
toStringFun.getDispatchReceiver()!!.let { valueArguments.add(Variable(it, state)) }
|
||||
return with(interpreter) { toStringFun.interpret(valueArguments) } as String
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.builtins.functions.FunctionInvokeDescriptor
|
||||
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
|
||||
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
|
||||
import org.jetbrains.kotlin.ir.interpreter.state.Lambda
|
||||
import org.jetbrains.kotlin.ir.interpreter.toState
|
||||
|
||||
internal class LambdaProxy(override val state: Lambda, override val interpreter: IrInterpreter): Proxy {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as LambdaProxy
|
||||
|
||||
return state == other.state
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return state.hashCode()
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return state.toString()
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun Lambda.asProxy(interpreter: IrInterpreter): Any {
|
||||
val lambdaProxy = LambdaProxy(this, interpreter)
|
||||
val arity = this.getArity()
|
||||
val hasBigArity = arity == null || arity >= FunctionInvokeDescriptor.BIG_ARITY
|
||||
|
||||
val functionClass = when {
|
||||
!hasBigArity && this.isFunction -> Class.forName("kotlin.jvm.functions." + this.irClass.name)
|
||||
hasBigArity && this.isFunction -> Class.forName("kotlin.jvm.functions.FunctionN")
|
||||
this.isKFunction -> Class.forName("kotlin.reflect.KFunction")
|
||||
else -> throw InternalError("Cannot handle lambda $this as proxy")
|
||||
}
|
||||
return java.lang.reflect.Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), arrayOf(functionClass))
|
||||
{ proxy, method, args ->
|
||||
when {
|
||||
method.name == "invoke" && method.parameterTypes.single().isObject() -> {
|
||||
val valueArguments = this.irFunction.valueParameters
|
||||
.mapIndexed { index, parameter -> Variable(parameter.symbol, args[index].toState(parameter.type)) }
|
||||
with(interpreter) { lambdaProxy.state.irFunction.interpret(valueArguments) }
|
||||
}
|
||||
method.name == "equals" && method.parameterTypes.single().isObject() -> lambdaProxy.equals(args.single())
|
||||
method.name == "hashCode" && method.parameterTypes.isEmpty() -> lambdaProxy.hashCode()
|
||||
method.name == "toString" && method.parameterTypes.isEmpty() -> lambdaProxy.toString()
|
||||
else -> throw InternalError("Cannot invoke method ${method.name} from lambda $this")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.interpreter.IrInterpreter
|
||||
import org.jetbrains.kotlin.ir.interpreter.proxy.LambdaProxy.Companion.asProxy
|
||||
import org.jetbrains.kotlin.ir.interpreter.state.*
|
||||
|
||||
internal interface Proxy {
|
||||
val state: State
|
||||
val interpreter: IrInterpreter
|
||||
|
||||
override fun equals(other: Any?): Boolean
|
||||
override fun hashCode(): Int
|
||||
override fun toString(): String
|
||||
}
|
||||
|
||||
internal fun State.unwrap(interpreter: IrInterpreter): Any? {
|
||||
return when (this) {
|
||||
is Proxy -> this.state
|
||||
is Primitive<*> -> this.value
|
||||
is Common -> CommonProxy(this, interpreter)
|
||||
is Lambda -> this.asProxy(interpreter)
|
||||
is Wrapper -> this.value
|
||||
else -> throw AssertionError("Unsupported state for proxy unwrap: ${this::class.java}")
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Class<*>.isObject(): Boolean {
|
||||
return this.name == "java.lang.Object"
|
||||
}
|
||||
@@ -50,6 +50,7 @@ internal interface Complex: State {
|
||||
}
|
||||
|
||||
private fun getOverridden(owner: IrSimpleFunction): IrSimpleFunction {
|
||||
if (owner.parent == superWrapperClass?.irClass) return owner
|
||||
if (!owner.isFakeOverride || owner.body != null || owner.parentAsClass.defaultType.isAny()) return owner
|
||||
|
||||
val overriddenOwner = owner.overriddenSymbols.singleOrNull { !it.owner.parentAsClass.isInterface }?.owner
|
||||
|
||||
@@ -11,6 +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.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.interpreter.isFunction
|
||||
import org.jetbrains.kotlin.ir.interpreter.isKFunction
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.util.nameForIrSerialization
|
||||
import org.jetbrains.kotlin.ir.util.render
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
@@ -18,12 +21,18 @@ import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
internal class Lambda(val irFunction: IrFunction, override val irClass: IrClass) : State {
|
||||
override val fields: MutableList<Variable> = mutableListOf()
|
||||
override val typeArguments: MutableList<Variable> = mutableListOf()
|
||||
val isKFunction = irClass.defaultType.isKFunction()
|
||||
val isFunction = irClass.defaultType.isFunction()
|
||||
|
||||
private val invokeSymbol = irClass.declarations
|
||||
.single { it.nameForIrSerialization.asString() == "invoke" }
|
||||
.cast<IrSimpleFunction>()
|
||||
.getLastOverridden().symbol
|
||||
|
||||
fun getArity(): Int? {
|
||||
return irClass.name.asString().removePrefix("Function").removePrefix("KFunction").toIntOrNull()
|
||||
}
|
||||
|
||||
override fun getIrFunctionByIrCall(expression: IrCall): IrFunction? {
|
||||
return if (invokeSymbol == expression.symbol) irFunction else null
|
||||
}
|
||||
|
||||
+16
-5
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.interpreter.state
|
||||
|
||||
import org.jetbrains.kotlin.builtins.functions.BuiltInFunctionArity
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrField
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
@@ -124,19 +125,28 @@ internal class Wrapper(val value: Any, override val irClass: IrClass) : Complex
|
||||
//TODO check if primitive array is possible here
|
||||
return when {
|
||||
notNullType.isPrimitiveType() || notNullType.isString() -> getPrimitiveClass(notNullType, asObject)!!
|
||||
notNullType.isArray() -> if (asObject) Array<Any?>::class.javaObjectType else Array<Any?>::class.java
|
||||
notNullType.isArray() -> {
|
||||
val argumentFqName = (this as IrSimpleType).arguments.single().typeOrNull?.classOrNull?.owner?.fqNameWhenAvailable
|
||||
argumentFqName?.let { Class.forName("[L$it;") } ?: Array<Any?>::class.java
|
||||
}
|
||||
notNullType.isNothing() -> Nothing::class.java
|
||||
notNullType.isAny() -> Any::class.java
|
||||
notNullType.isUnit() -> if (asObject) Void::class.javaObjectType else Void::class.javaPrimitiveType!!
|
||||
notNullType.isNumber() -> Number::class.java
|
||||
notNullType.isCharSequence() -> CharSequence::class.java
|
||||
notNullType.isComparable() -> Comparable::class.java
|
||||
notNullType.isThrowable() -> Throwable::class.java
|
||||
notNullType.isIterable() -> Iterable::class.java
|
||||
|
||||
// TODO implement function mapping; all complexity is to map big arity to FunctionN
|
||||
//notNullType.isKFunction() -> Class.forName("kotlin.reflect.KFunction")
|
||||
//notNullType.isFunction() -> Class.forName("kotlin.jvm.functions.Function_TODO")
|
||||
//notNullType.isSuspendFunction() || notNullType.isKSuspendFunction() -> throw AssertionError()
|
||||
notNullType.isKFunction() -> Class.forName("kotlin.reflect.KFunction")
|
||||
notNullType.isFunction() -> {
|
||||
val arity = fqName?.removePrefix("kotlin.Function")?.toIntOrNull()
|
||||
return when {
|
||||
arity == null || arity >= BuiltInFunctionArity.BIG_ARITY -> Class.forName("kotlin.jvm.functions.FunctionN")
|
||||
else -> Class.forName("kotlin.jvm.functions.${fqName.removePrefix("kotlin.")}")
|
||||
}
|
||||
}
|
||||
//notNullType.isSuspendFunction() || notNullType.isKSuspendFunction() -> throw AssertionError() //TODO
|
||||
|
||||
fqName == "kotlin.Enum" -> Enum::class.java
|
||||
fqName == "kotlin.collections.Collection" || fqName == "kotlin.collections.MutableCollection" -> Collection::class.java
|
||||
@@ -147,6 +157,7 @@ internal class Wrapper(val value: Any, override val irClass: IrClass) : Complex
|
||||
fqName == "kotlin.collections.Iterator" || fqName == "kotlin.collections.MutableIterator" -> Iterator::class.java
|
||||
fqName == "kotlin.collections.Map.Entry" || fqName == "kotlin.collections.MutableMap.MutableEntry" -> Map.Entry::class.java
|
||||
fqName == "kotlin.collections.ListIterator" || fqName == "kotlin.collections.MutableListIterator" -> ListIterator::class.java
|
||||
fqName == "kotlin.collections.HashMap" -> HashMap::class.java
|
||||
|
||||
owner.hasAnnotation(evaluateIntrinsicAnnotation) -> Class.forName(owner!!.getEvaluateIntrinsicValue())
|
||||
fqName == null -> Any::class.java // null if this.isTypeParameter()
|
||||
|
||||
@@ -39,7 +39,7 @@ fun generateMap(): String {
|
||||
p.println(File("license/COPYRIGHT.txt").readText())
|
||||
p.println("package org.jetbrains.kotlin.ir.interpreter.builtins")
|
||||
p.println()
|
||||
p.println("import org.jetbrains.kotlin.ir.interpreter.IrInterpreter")
|
||||
p.println("import org.jetbrains.kotlin.ir.interpreter.proxy.Proxy")
|
||||
p.println()
|
||||
p.println("/** This file is generated by org.jetbrains.kotlin.backend.common.interpreter.builtins.GenerateBuiltInsMap.generateMap(). DO NOT MODIFY MANUALLY */")
|
||||
p.println()
|
||||
@@ -150,7 +150,7 @@ private fun generateBinaryBody(
|
||||
val methodName = "${function.name}"
|
||||
val methodSymbol = getIrMethodSymbolByName(methodName)
|
||||
val body = when (methodName) {
|
||||
IrBuiltIns.OperatorNames.EQEQEQ -> "if (a is IrInterpreter.Proxy && b is IrInterpreter.Proxy) a.state === b.state else a === b"
|
||||
IrBuiltIns.OperatorNames.EQEQEQ -> "if (a is Proxy && b is Proxy) a.state === b.state else a === b"
|
||||
else -> "a $methodSymbol b"
|
||||
}
|
||||
" binaryOperation${parameters.first}(\"$methodName\", ${parameters.second}) { a, b -> $body }"
|
||||
|
||||
Reference in New Issue
Block a user