Change all usages of descriptors in interpreter to usages of ir symbols
This commit is contained in:
+6
-1
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrNull
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -204,7 +205,11 @@ class IrCompileTimeChecker(
|
||||
IrTypeOperator.INSTANCEOF, IrTypeOperator.NOT_INSTANCEOF,
|
||||
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT,
|
||||
IrTypeOperator.CAST, IrTypeOperator.IMPLICIT_CAST, IrTypeOperator.SAFE_CAST,
|
||||
IrTypeOperator.IMPLICIT_NOTNULL -> expression.argument.accept(this, data)
|
||||
IrTypeOperator.IMPLICIT_NOTNULL -> {
|
||||
val operand = expression.typeOperand.classifierOrNull?.owner
|
||||
if (operand is IrTypeParameter && !callStack.contains((operand.parent as IrSymbolOwner).symbol)) return false
|
||||
expression.argument.accept(this, data)
|
||||
}
|
||||
IrTypeOperator.IMPLICIT_DYNAMIC_CAST -> false
|
||||
else -> false
|
||||
}
|
||||
|
||||
+28
-28
@@ -56,7 +56,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
|
||||
is Double -> irBuiltIns.doubleType
|
||||
null -> irBuiltIns.nothingType
|
||||
else -> when (defaultType.classifierOrNull?.owner) {
|
||||
is IrTypeParameter -> stack.getVariable(defaultType.classifierOrFail.descriptor).state.irClass.defaultType
|
||||
is IrTypeParameter -> stack.getVariable(defaultType.classifierOrFail).state.irClass.defaultType
|
||||
else -> defaultType
|
||||
}
|
||||
}
|
||||
@@ -225,7 +225,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
|
||||
constructorCall.putValueArgument(index, primitive.value.toIrConst(primitive.type))
|
||||
}
|
||||
|
||||
val constructorValueParameters = constructor.valueParameters.map { it.descriptor }.zip(primitiveValueParameters)
|
||||
val constructorValueParameters = constructor.valueParameters.map { it.symbol }.zip(primitiveValueParameters)
|
||||
return stack.newFrame(initPool = constructorValueParameters.map { Variable(it.first, it.second) }) {
|
||||
constructorCall.interpret()
|
||||
}
|
||||
@@ -239,7 +239,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
|
||||
true -> listOfNotNull(irFunction.getExtensionReceiver())
|
||||
else -> listOf()
|
||||
}
|
||||
val valueParametersDescriptors = receiverAsFirstArgument + irFunction.descriptor.valueParameters
|
||||
val valueParametersDescriptors = receiverAsFirstArgument + irFunction.valueParameters.map { it.symbol }
|
||||
|
||||
val valueArguments = (0 until expression.valueArgumentsCount).map { expression.getValueArgument(it) }
|
||||
val defaultValues = expression.symbol.owner.valueParameters.map { it.defaultValue?.expression }
|
||||
@@ -326,11 +326,11 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
|
||||
val classProperties = irClass.declarations.filterIsInstance<IrProperty>()
|
||||
classProperties.forEach { property ->
|
||||
property.backingField?.initializer?.expression?.interpret()?.check { return it }
|
||||
val receiver = irClass.descriptor.thisAsReceiverParameter
|
||||
val receiver = irClass.thisReceiver!!.symbol
|
||||
if (property.backingField?.initializer != null) {
|
||||
val receiverState = stack.getVariable(receiver).state
|
||||
val property = Variable(property.backingField!!.descriptor, stack.popReturnValue())
|
||||
receiverState.setField(property)
|
||||
val propertyVar = Variable(property.backingField!!.symbol, stack.popReturnValue())
|
||||
receiverState.setField(propertyVar)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -363,9 +363,9 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
|
||||
if (irClass.isLocal) state.fields.addAll(stack.getAll()) // TODO save only necessary declarations
|
||||
if (irClass.isInner) {
|
||||
constructorCall.dispatchReceiver!!.interpret().check { return it }
|
||||
state.outerClass = Variable(constructorCall.symbol.owner.dispatchReceiverParameter!!.descriptor, stack.popReturnValue())
|
||||
state.outerClass = Variable(irClass.parentAsClass.thisReceiver!!.symbol, stack.popReturnValue())
|
||||
}
|
||||
valueArguments.add(Variable(irClass.thisReceiver!!.descriptor, state)) //used to set up fields in body
|
||||
valueArguments.add(Variable(irClass.thisReceiver!!.symbol, state)) //used to set up fields in body
|
||||
return stack.newFrame(initPool = valueArguments + state.typeArguments) {
|
||||
val statements = constructorCall.getBody()!!.statements
|
||||
// enum entry use IrTypeOperatorCall with IMPLICIT_COERCION_TO_UNIT as delegation call, but we need the value
|
||||
@@ -443,7 +443,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
|
||||
|
||||
private suspend fun interpretReturn(expression: IrReturn): ExecutionResult {
|
||||
expression.value.interpret().check { return it }
|
||||
return Return.addInfo(expression.returnTargetSymbol.descriptor.toString())
|
||||
return Return.addOwnerInfo(expression.returnTargetSymbol.owner)
|
||||
}
|
||||
|
||||
private suspend fun interpretWhile(expression: IrWhileLoop): ExecutionResult {
|
||||
@@ -487,24 +487,24 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
|
||||
}
|
||||
|
||||
private fun interpretBreak(breakStatement: IrBreak): ExecutionResult {
|
||||
return BreakLoop.addInfo(breakStatement.label ?: "")
|
||||
return BreakLoop.addOwnerInfo(breakStatement.loop)
|
||||
}
|
||||
|
||||
private fun interpretContinue(continueStatement: IrContinue): ExecutionResult {
|
||||
return Continue.addInfo(continueStatement.label ?: "")
|
||||
return Continue.addOwnerInfo(continueStatement.loop)
|
||||
}
|
||||
|
||||
private suspend fun interpretSetField(expression: IrSetField): ExecutionResult {
|
||||
expression.value.interpret().check { return it }
|
||||
|
||||
// receiver is null only for top level var, but it cannot be used in constexpr; corresponding check is on frontend
|
||||
val receiver = (expression.receiver as IrDeclarationReference).symbol.descriptor
|
||||
stack.getVariable(receiver).apply { this.state.setField(Variable(expression.symbol.owner.descriptor, stack.popReturnValue())) }
|
||||
val receiver = (expression.receiver as IrDeclarationReference).symbol
|
||||
stack.getVariable(receiver).apply { this.state.setField(Variable(expression.symbol, stack.popReturnValue())) }
|
||||
return Next
|
||||
}
|
||||
|
||||
private suspend fun interpretGetField(expression: IrGetField): ExecutionResult {
|
||||
val receiver = (expression.receiver as? IrDeclarationReference)?.symbol?.descriptor
|
||||
val receiver = (expression.receiver as? IrDeclarationReference)?.symbol
|
||||
val field = expression.symbol.owner
|
||||
// for java static variables
|
||||
if (field.origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB && field.isStatic) {
|
||||
@@ -512,7 +512,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
|
||||
return Next
|
||||
}
|
||||
// receiver is null, for example, for top level fields
|
||||
val result = receiver?.let { stack.getVariable(receiver).state.getState(expression.symbol.descriptor) }
|
||||
val result = receiver?.let { stack.getVariable(receiver).state.getState(expression.symbol) }
|
||||
?: return (expression.symbol.owner.initializer?.expression?.interpret() ?: Next)
|
||||
stack.pushReturnValue(result)
|
||||
return Next
|
||||
@@ -522,23 +522,23 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
|
||||
val owner = expression.type.classOrNull?.owner
|
||||
// used to evaluate constants inside object
|
||||
if (owner != null && owner.isObject) return getOrCreateObjectValue(owner) // TODO is this correct behaviour?
|
||||
stack.pushReturnValue(stack.getVariable(expression.symbol.descriptor).state)
|
||||
stack.pushReturnValue(stack.getVariable(expression.symbol).state)
|
||||
return Next
|
||||
}
|
||||
|
||||
private suspend fun interpretVariable(expression: IrVariable): ExecutionResult {
|
||||
expression.initializer?.interpret()?.check { return it } ?: return Next
|
||||
stack.addVar(Variable(expression.descriptor, stack.popReturnValue()))
|
||||
stack.addVar(Variable(expression.symbol, stack.popReturnValue()))
|
||||
return Next
|
||||
}
|
||||
|
||||
private suspend fun interpretSetVariable(expression: IrSetVariable): ExecutionResult {
|
||||
expression.value.interpret().check { return it }
|
||||
|
||||
if (stack.contains(expression.symbol.descriptor)) {
|
||||
stack.getVariable(expression.symbol.descriptor).apply { this.state = stack.popReturnValue() }
|
||||
if (stack.contains(expression.symbol)) {
|
||||
stack.getVariable(expression.symbol).apply { this.state = stack.popReturnValue() }
|
||||
} else {
|
||||
stack.addVar(Variable(expression.symbol.descriptor, stack.popReturnValue()))
|
||||
stack.addVar(Variable(expression.symbol, stack.popReturnValue()))
|
||||
}
|
||||
return Next
|
||||
}
|
||||
@@ -569,7 +569,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
|
||||
val executionResult = when {
|
||||
enumClass.hasAnnotation(evaluateIntrinsicAnnotation) -> {
|
||||
val enumEntryName = it.name.asString().toState(irBuiltIns.stringType)
|
||||
val enumNameAsVariable = Variable(valueOfFun.valueParameters.first().descriptor, enumEntryName)
|
||||
val enumNameAsVariable = Variable(valueOfFun.valueParameters.first().symbol, enumEntryName)
|
||||
stack.newFrame(initPool = listOf(enumNameAsVariable)) { Wrapper.getEnumEntry(enumClass)!!.invokeMethod(valueOfFun) }
|
||||
}
|
||||
else -> interpretEnumEntry(it)
|
||||
@@ -601,7 +601,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
|
||||
|
||||
private suspend fun interpretTypeOperatorCall(expression: IrTypeOperatorCall): ExecutionResult {
|
||||
val executionResult = expression.argument.interpret().check { return it }
|
||||
val typeOperandDescriptor = expression.typeOperand.classifierOrFail.descriptor
|
||||
val typeOperandDescriptor = expression.typeOperand.classifierOrFail
|
||||
val typeOperandClass = expression.typeOperand.classOrNull?.owner ?: stack.getVariable(typeOperandDescriptor).state.irClass
|
||||
|
||||
when (expression.operator) {
|
||||
@@ -657,16 +657,16 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
|
||||
}
|
||||
}
|
||||
|
||||
val array = when (expression.type.classifierOrFail.descriptor.name.asString()) {
|
||||
val array = when ((expression.type.classifierOrFail.owner as? IrDeclaration)?.nameForIrSerialization?.asString()) {
|
||||
"UByteArray", "UShortArray", "UIntArray", "ULongArray" -> {
|
||||
val owner = expression.type.classOrNull!!.owner
|
||||
val constructor = owner.primaryConstructor!!
|
||||
val storageParameter = constructor.valueParameters.single()
|
||||
val storageProperty = owner.declarations.filterIsInstance<IrProperty>().first { it.name.asString() == "storage" }
|
||||
val storageField = storageProperty.backingField!!
|
||||
val primitiveArray = args.map { ((it as Common).fields.single().state as Primitive<*>).value }
|
||||
val unsignedArray = primitiveArray.toPrimitiveStateArray(storageParameter.type)
|
||||
val unsignedArray = primitiveArray.toPrimitiveStateArray(storageField.type)
|
||||
Common(owner).apply {
|
||||
setSuperClassRecursive()
|
||||
fields.add(Variable(storageParameter.descriptor, unsignedArray))
|
||||
fields.add(Variable(storageField.symbol, unsignedArray))
|
||||
}
|
||||
}
|
||||
else -> args.toPrimitiveStateArray(expression.type)
|
||||
@@ -697,7 +697,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
|
||||
}
|
||||
|
||||
private suspend fun interpretCatch(expression: IrCatch): ExecutionResult {
|
||||
val catchParameter = Variable(expression.parameter, stack.popReturnValue())
|
||||
val catchParameter = Variable(expression.catchParameter.symbol, stack.popReturnValue())
|
||||
return stack.newFrame(asSubFrame = true, initPool = listOf(catchParameter)) {
|
||||
expression.result.interpret()
|
||||
}
|
||||
|
||||
+16
-15
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.backend.common.interpreter
|
||||
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyFunction
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrReturnableBlock
|
||||
import org.jetbrains.kotlin.ir.expressions.IrWhen
|
||||
@@ -27,7 +28,7 @@ inline fun ExecutionResult.check(toCheckLabel: ReturnLabel = ReturnLabel.NEXT, r
|
||||
return this
|
||||
}
|
||||
|
||||
open class ExecutionResultWithoutInfo(override val returnLabel: ReturnLabel) : ExecutionResult {
|
||||
open class ExecutionResultWithoutInfoAboutOwner(override val returnLabel: ReturnLabel) : ExecutionResult {
|
||||
override suspend fun getNextLabel(irElement: IrElement, interpret: suspend IrElement.() -> ExecutionResult): ExecutionResult {
|
||||
return when (returnLabel) {
|
||||
ReturnLabel.RETURN -> this
|
||||
@@ -42,18 +43,18 @@ open class ExecutionResultWithoutInfo(override val returnLabel: ReturnLabel) : E
|
||||
}
|
||||
}
|
||||
|
||||
fun addInfo(info: String): ExecutionResultWithInfo {
|
||||
return ExecutionResultWithInfo(returnLabel, info)
|
||||
fun addOwnerInfo(owner: IrElement): ExecutionResultWithInfoAboutOwner {
|
||||
return ExecutionResultWithInfoAboutOwner(returnLabel, owner)
|
||||
}
|
||||
}
|
||||
|
||||
class ExecutionResultWithInfo(override val returnLabel: ReturnLabel, val info: String) : ExecutionResultWithoutInfo(returnLabel) {
|
||||
class ExecutionResultWithInfoAboutOwner(
|
||||
override val returnLabel: ReturnLabel, private val owner: IrElement
|
||||
) : ExecutionResultWithoutInfoAboutOwner(returnLabel) {
|
||||
override suspend fun getNextLabel(irElement: IrElement, interpret: suspend IrElement.() -> ExecutionResult): ExecutionResult {
|
||||
return when (returnLabel) {
|
||||
ReturnLabel.RETURN -> when (irElement) {
|
||||
is IrCall -> if (info == irElement.symbol.descriptor.toString()) Next else this
|
||||
is IrReturnableBlock -> if (info == irElement.symbol.descriptor.toString()) Next else this
|
||||
is IrFunctionImpl -> if (info == irElement.descriptor.toString()) Next else this
|
||||
is IrCall, is IrReturnableBlock, is IrFunctionImpl, is IrLazyFunction -> if (owner == irElement) Next else this
|
||||
else -> this
|
||||
}
|
||||
ReturnLabel.BREAK_WHEN -> when (irElement) {
|
||||
@@ -61,11 +62,11 @@ class ExecutionResultWithInfo(override val returnLabel: ReturnLabel, val info: S
|
||||
else -> this
|
||||
}
|
||||
ReturnLabel.BREAK_LOOP -> when (irElement) {
|
||||
is IrWhileLoop -> if ((irElement.label ?: "") == info) Next else this
|
||||
is IrWhileLoop -> if (owner == irElement) Next else this
|
||||
else -> this
|
||||
}
|
||||
ReturnLabel.CONTINUE -> when (irElement) {
|
||||
is IrWhileLoop -> if ((irElement.label ?: "") == info) irElement.interpret() else this
|
||||
is IrWhileLoop -> if (owner == irElement) irElement.interpret() else this
|
||||
else -> this
|
||||
}
|
||||
ReturnLabel.EXCEPTION -> Exception
|
||||
@@ -74,9 +75,9 @@ class ExecutionResultWithInfo(override val returnLabel: ReturnLabel, val info: S
|
||||
}
|
||||
}
|
||||
|
||||
object Next : ExecutionResultWithoutInfo(ReturnLabel.NEXT)
|
||||
object Return : ExecutionResultWithoutInfo(ReturnLabel.RETURN)
|
||||
object BreakLoop : ExecutionResultWithoutInfo(ReturnLabel.BREAK_LOOP)
|
||||
object BreakWhen : ExecutionResultWithoutInfo(ReturnLabel.BREAK_WHEN)
|
||||
object Continue : ExecutionResultWithoutInfo(ReturnLabel.CONTINUE)
|
||||
object Exception : ExecutionResultWithoutInfo(ReturnLabel.EXCEPTION)
|
||||
object Next : ExecutionResultWithoutInfoAboutOwner(ReturnLabel.NEXT)
|
||||
object Return : ExecutionResultWithoutInfoAboutOwner(ReturnLabel.RETURN)
|
||||
object BreakLoop : ExecutionResultWithoutInfoAboutOwner(ReturnLabel.BREAK_LOOP)
|
||||
object BreakWhen : ExecutionResultWithoutInfoAboutOwner(ReturnLabel.BREAK_WHEN)
|
||||
object Continue : ExecutionResultWithoutInfoAboutOwner(ReturnLabel.CONTINUE)
|
||||
object Exception : ExecutionResultWithoutInfoAboutOwner(ReturnLabel.EXCEPTION)
|
||||
+18
-53
@@ -9,30 +9,28 @@ import org.jetbrains.kotlin.backend.common.interpreter.builtins.evaluateIntrinsi
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.stack.Variable
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.state.*
|
||||
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.descriptors.WrappedReceiverParameterDescriptor
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
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.utils.addToStdlib.safeAs
|
||||
|
||||
fun IrFunction.getDispatchReceiver(): DeclarationDescriptor? {
|
||||
return (this.symbol.descriptor.containingDeclaration as? ClassDescriptor)?.thisAsReceiverParameter
|
||||
fun IrFunction.getDispatchReceiver(): IrSymbol? {
|
||||
return this.dispatchReceiverParameter?.symbol
|
||||
}
|
||||
|
||||
fun IrFunction.getExtensionReceiver(): DeclarationDescriptor? {
|
||||
return this.extensionReceiverParameter?.descriptor
|
||||
fun IrFunction.getExtensionReceiver(): IrSymbol? {
|
||||
return this.extensionReceiverParameter?.symbol
|
||||
}
|
||||
|
||||
fun IrFunction.getReceiver(): DeclarationDescriptor? {
|
||||
fun IrFunction.getReceiver(): IrSymbol? {
|
||||
return this.getDispatchReceiver() ?: this.getExtensionReceiver()
|
||||
}
|
||||
|
||||
@@ -40,39 +38,6 @@ fun IrFunctionAccessExpression.getBody(): IrBody? {
|
||||
return this.symbol.owner.body
|
||||
}
|
||||
|
||||
fun DeclarationDescriptor.equalTo(other: DeclarationDescriptor): Boolean {
|
||||
return this.isEqualByReceiverTo(other) || this.hasSameNameAs(other) || this == other
|
||||
}
|
||||
|
||||
private fun WrappedReceiverParameterDescriptor.isEqualTo(other: DeclarationDescriptor): Boolean {
|
||||
return when (val container = this.containingDeclaration) {
|
||||
is ClassDescriptor -> container == other.containingDeclaration
|
||||
is FunctionDescriptor -> container.dispatchReceiverParameter == other || container.extensionReceiverParameter == other
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
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 == other.value.type
|
||||
this.value is ExtensionReceiver && other.value is ExtensionReceiver -> this.value == other.value
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
private fun DeclarationDescriptor.hasSameNameAs(other: DeclarationDescriptor): Boolean {
|
||||
return (this is VariableDescriptor && other is VariableDescriptor && this.name == other.name) ||
|
||||
(this is TypeParameterDescriptor && other is TypeParameterDescriptor && this.name == other.name) ||
|
||||
(this is FunctionDescriptor && other is FunctionDescriptor && //this == other
|
||||
this.valueParameters.map { it.type.toString() } == other.valueParameters.map { it.type.toString() } &&
|
||||
this.name == other.name)
|
||||
}
|
||||
|
||||
fun State.toIrExpression(expression: IrExpression): IrExpression {
|
||||
val start = expression.startOffset
|
||||
val end = expression.endOffset
|
||||
@@ -130,14 +95,14 @@ fun <T> IrConst<T>.toPrimitive(): Primitive<T> {
|
||||
fun IrAnnotationContainer?.hasAnnotation(annotation: FqName): Boolean {
|
||||
this ?: return false
|
||||
if (this.annotations.isNotEmpty()) {
|
||||
return this.annotations.any { it.symbol.descriptor.containingDeclaration.fqNameSafe == annotation }
|
||||
return this.annotations.any { it.symbol.owner.parentAsClass.fqNameWhenAvailable == annotation }
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun IrAnnotationContainer.getAnnotation(annotation: FqName): IrConstructorCall {
|
||||
return this.annotations.firstOrNull { it.symbol.descriptor.containingDeclaration.fqNameSafe == annotation }
|
||||
?: ((this as IrFunction).parent as IrClass).annotations.first { it.symbol.descriptor.containingDeclaration.fqNameSafe == annotation }
|
||||
return this.annotations.firstOrNull { it.symbol.owner.parentAsClass.fqNameWhenAvailable == annotation }
|
||||
?: ((this as IrFunction).parent as IrClass).annotations.first { it.symbol.owner.parentAsClass.fqNameWhenAvailable == annotation }
|
||||
}
|
||||
|
||||
fun IrAnnotationContainer.getEvaluateIntrinsicValue(): String? {
|
||||
@@ -214,20 +179,20 @@ fun IrFunctionAccessExpression.getVarargType(index: Int): IrType? {
|
||||
}
|
||||
|
||||
fun getTypeArguments(
|
||||
container: IrTypeParametersContainer, expression: IrFunctionAccessExpression, mapper: (TypeParameterDescriptor) -> State
|
||||
container: IrTypeParametersContainer, expression: IrFunctionAccessExpression, mapper: (IrTypeParameterSymbol) -> State
|
||||
): List<Variable> {
|
||||
fun IrType.getState(): State {
|
||||
return this.classOrNull?.owner?.let { Common(it) } ?: mapper(this.classifierOrFail.descriptor as TypeParameterDescriptor)
|
||||
return this.classOrNull?.owner?.let { Common(it) } ?: mapper(this.classifierOrFail as IrTypeParameterSymbol)
|
||||
}
|
||||
|
||||
val typeArguments = container.typeParameters.mapIndexed { index, typeParameter ->
|
||||
val typeArgument = expression.getTypeArgument(index)!!
|
||||
Variable(typeParameter.descriptor, typeArgument.getState())
|
||||
Variable(typeParameter.symbol, typeArgument.getState())
|
||||
}.toMutableList()
|
||||
|
||||
if (container is IrSimpleFunction) {
|
||||
container.returnType.classifierOrFail.owner.safeAs<IrTypeParameter>()
|
||||
?.let { typeArguments.add(Variable(it.descriptor, expression.type.getState())) }
|
||||
?.let { typeArguments.add(Variable(it.symbol, expression.type.getState())) }
|
||||
}
|
||||
|
||||
return typeArguments
|
||||
@@ -236,13 +201,13 @@ fun getTypeArguments(
|
||||
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 }
|
||||
return state.fields.filter { it.symbol !is IrFieldSymbol }
|
||||
}
|
||||
|
||||
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
|
||||
val other = irFunction.parentClassOrNull?.thisReceiver ?: return this
|
||||
return generateSequence(original) { it.superClass }.firstOrNull { it.irClass.thisReceiver == other } ?: this
|
||||
}
|
||||
+16
-14
@@ -60,7 +60,7 @@ object ArrayOfNulls : IntrinsicBase() {
|
||||
override suspend fun evaluate(
|
||||
irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult
|
||||
): ExecutionResult {
|
||||
val size = stack.getVariable(irFunction.valueParameters.first().descriptor).state.asInt()
|
||||
val size = stack.getVariable(irFunction.valueParameters.first().symbol).state.asInt()
|
||||
val array = arrayOfNulls<Any?>(size)
|
||||
stack.pushReturnValue(array.toState(irFunction.returnType))
|
||||
return Next
|
||||
@@ -77,7 +77,7 @@ object EnumValues : IntrinsicBase() {
|
||||
irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult
|
||||
): ExecutionResult {
|
||||
val enumClass = when (irFunction.fqNameWhenAvailable.toString()) {
|
||||
"kotlin.enumValues" -> stack.getVariable(irFunction.typeParameters.first().descriptor).state.irClass
|
||||
"kotlin.enumValues" -> stack.getVariable(irFunction.typeParameters.first().symbol).state.irClass
|
||||
else -> irFunction.parent as IrClass
|
||||
}
|
||||
|
||||
@@ -98,10 +98,10 @@ object EnumValueOf : IntrinsicBase() {
|
||||
irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult
|
||||
): ExecutionResult {
|
||||
val enumClass = when (irFunction.fqNameWhenAvailable.toString()) {
|
||||
"kotlin.enumValueOf" -> stack.getVariable(irFunction.typeParameters.first().descriptor).state.irClass
|
||||
"kotlin.enumValueOf" -> stack.getVariable(irFunction.typeParameters.first().symbol).state.irClass
|
||||
else -> irFunction.parent as IrClass
|
||||
}
|
||||
val enumEntryName = stack.getVariable(irFunction.valueParameters.first().descriptor).state.asString()
|
||||
val enumEntryName = stack.getVariable(irFunction.valueParameters.first().symbol).state.asString()
|
||||
val enumEntry = enumClass.declarations.filterIsInstance<IrEnumEntry>().singleOrNull { it.name.asString() == enumEntryName }
|
||||
enumEntry?.interpret()?.check { return it }
|
||||
?: throw IllegalArgumentException("No enum constant ${enumClass.fqNameWhenAvailable}.$enumEntryName")
|
||||
@@ -125,7 +125,7 @@ object RegexReplace : IntrinsicBase() {
|
||||
val transform = states.filterIsInstance<Lambda>().single().irFunction
|
||||
val matchResultParameter = transform.valueParameters.single()
|
||||
val result = regex.replace(input) {
|
||||
val itAsState = Variable(matchResultParameter.descriptor, Wrapper(it, matchResultParameter.type.classOrNull!!.owner))
|
||||
val itAsState = Variable(matchResultParameter.symbol, Wrapper(it, matchResultParameter.type.classOrNull!!.owner))
|
||||
runBlocking { stack.newFrame(initPool = listOf(itAsState)) { transform.interpret() } }//.check { return it }
|
||||
stack.popReturnValue().asString()
|
||||
}
|
||||
@@ -160,12 +160,12 @@ object JsPrimitives : IntrinsicBase() {
|
||||
): ExecutionResult {
|
||||
when (irFunction.fqNameWhenAvailable.toString()) {
|
||||
"kotlin.Long.<init>" -> {
|
||||
val low = stack.getVariable(irFunction.valueParameters[0].descriptor).state.asInt()
|
||||
val high = stack.getVariable(irFunction.valueParameters[1].descriptor).state.asInt()
|
||||
val low = stack.getVariable(irFunction.valueParameters[0].symbol).state.asInt()
|
||||
val high = stack.getVariable(irFunction.valueParameters[1].symbol).state.asInt()
|
||||
stack.pushReturnValue((high.toLong().shl(32) + low).toState(irFunction.returnType))
|
||||
}
|
||||
"kotlin.Char.<init>" -> {
|
||||
val value = stack.getVariable(irFunction.valueParameters[0].descriptor).state.asInt()
|
||||
val value = stack.getVariable(irFunction.valueParameters[0].symbol).state.asInt()
|
||||
stack.pushReturnValue(value.toChar().toState(irFunction.returnType))
|
||||
}
|
||||
}
|
||||
@@ -182,20 +182,22 @@ object ArrayConstructor : IntrinsicBase() {
|
||||
override suspend fun evaluate(
|
||||
irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult
|
||||
): ExecutionResult {
|
||||
val sizeDescriptor = irFunction.valueParameters[0].descriptor
|
||||
val sizeDescriptor = irFunction.valueParameters[0].symbol
|
||||
val size = stack.getVariable(sizeDescriptor).state.asInt()
|
||||
val arrayValue = MutableList<Any>(size) { 0 }
|
||||
|
||||
if (irFunction.valueParameters.size == 2) {
|
||||
val initDescriptor = irFunction.valueParameters[1].descriptor
|
||||
val initDescriptor = irFunction.valueParameters[1].symbol
|
||||
val initLambda = stack.getVariable(initDescriptor).state as Lambda
|
||||
val index = initLambda.irFunction.valueParameters.single()
|
||||
val nonLocalDeclarations = initLambda.extractNonLocalDeclarations()
|
||||
for (i in 0 until size) {
|
||||
val indexVar = listOf(Variable(index.descriptor, i.toState(index.type)))
|
||||
val indexVar = listOf(Variable(index.symbol, i.toState(index.type)))
|
||||
// TODO throw exception if label != RETURN
|
||||
stack.newFrame(asSubFrame = initLambda.irFunction.isLocal || initLambda.irFunction.isInline, initPool = indexVar) {
|
||||
initLambda.irFunction.body!!.interpret()
|
||||
}.check(ReturnLabel.RETURN) { return it }
|
||||
stack.newFrame(
|
||||
asSubFrame = initLambda.irFunction.isLocal || initLambda.irFunction.isInline,
|
||||
initPool = nonLocalDeclarations + indexVar
|
||||
) { initLambda.irFunction.body!!.interpret() }.check(ReturnLabel.RETURN) { return it }
|
||||
arrayValue[i] = stack.popReturnValue().let { (it as? Wrapper)?.value ?: (it as? Primitive<*>)?.value ?: it }
|
||||
}
|
||||
}
|
||||
|
||||
+8
-11
@@ -5,18 +5,16 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.common.interpreter.stack
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.equalTo
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.state.State
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import kotlin.NoSuchElementException
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
|
||||
interface Frame {
|
||||
fun addVar(variable: Variable)
|
||||
fun addAll(variables: List<Variable>)
|
||||
fun getVariable(variableDescriptor: DeclarationDescriptor): Variable?
|
||||
fun getVariable(symbol: IrSymbol): Variable?
|
||||
fun getAll(): List<Variable>
|
||||
fun contains(descriptor: DeclarationDescriptor): Boolean
|
||||
fun contains(symbol: IrSymbol): Boolean
|
||||
fun pushReturnValue(state: State)
|
||||
fun pushReturnValue(frame: Frame) // TODO rename to getReturnValueFrom
|
||||
fun peekReturnValue(): State
|
||||
@@ -39,17 +37,16 @@ class InterpreterFrame(
|
||||
pool.addAll(variables)
|
||||
}
|
||||
|
||||
override fun getVariable(variableDescriptor: DeclarationDescriptor): Variable? {
|
||||
return (if (variableDescriptor is TypeParameterDescriptor) typeArguments else pool)
|
||||
.firstOrNull { it.descriptor.equalTo(variableDescriptor) }
|
||||
override fun getVariable(symbol: IrSymbol): Variable? {
|
||||
return (if (symbol is IrTypeParameterSymbol) typeArguments else pool).firstOrNull { it.symbol == symbol }
|
||||
}
|
||||
|
||||
override fun getAll(): List<Variable> {
|
||||
return pool
|
||||
}
|
||||
|
||||
override fun contains(descriptor: DeclarationDescriptor): Boolean {
|
||||
return (typeArguments + pool).any { it.descriptor == descriptor }
|
||||
override fun contains(symbol: IrSymbol): Boolean {
|
||||
return (typeArguments + pool).any { it.symbol == symbol }
|
||||
}
|
||||
|
||||
override fun pushReturnValue(state: State) {
|
||||
|
||||
+14
-14
@@ -8,10 +8,10 @@ package org.jetbrains.kotlin.backend.common.interpreter.stack
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.ExecutionResult
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.exceptions.InterpreterException
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.state.State
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.name
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.util.file
|
||||
import org.jetbrains.kotlin.ir.util.fileEntry
|
||||
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
||||
@@ -28,10 +28,10 @@ interface Stack {
|
||||
fun clean()
|
||||
fun addVar(variable: Variable)
|
||||
fun addAll(variables: List<Variable>)
|
||||
fun getVariable(variableDescriptor: DeclarationDescriptor): Variable
|
||||
fun getVariable(symbol: IrSymbol): Variable
|
||||
fun getAll(): List<Variable>
|
||||
|
||||
fun contains(descriptor: DeclarationDescriptor): Boolean
|
||||
fun contains(symbol: IrSymbol): Boolean
|
||||
fun hasReturnValue(): Boolean
|
||||
fun pushReturnValue(state: State)
|
||||
fun popReturnValue(): State
|
||||
@@ -43,8 +43,8 @@ class StackImpl : Stack {
|
||||
private fun getCurrentFrame() = frameList.last()
|
||||
|
||||
override suspend fun newFrame(asSubFrame: Boolean, initPool: List<Variable>, block: suspend () -> ExecutionResult): ExecutionResult {
|
||||
val typeArgumentsPool = initPool.filter { it.descriptor is TypeParameterDescriptor }
|
||||
val valueArguments = initPool.filter { it.descriptor !is TypeParameterDescriptor }
|
||||
val typeArgumentsPool = initPool.filter { it.symbol is IrTypeParameterSymbol }
|
||||
val valueArguments = initPool.filter { it.symbol !is IrTypeParameterSymbol }
|
||||
val newFrame = InterpreterFrame(valueArguments.toMutableList(), typeArgumentsPool)
|
||||
if (asSubFrame) getCurrentFrame().addSubFrame(newFrame) else frameList.add(FrameContainer(newFrame))
|
||||
|
||||
@@ -86,16 +86,16 @@ class StackImpl : Stack {
|
||||
getCurrentFrame().addAll(variables)
|
||||
}
|
||||
|
||||
override fun getVariable(variableDescriptor: DeclarationDescriptor): Variable {
|
||||
return getCurrentFrame().getVariable(variableDescriptor)
|
||||
override fun getVariable(symbol: IrSymbol): Variable {
|
||||
return getCurrentFrame().getVariable(symbol)
|
||||
}
|
||||
|
||||
override fun getAll(): List<Variable> {
|
||||
return getCurrentFrame().getAll()
|
||||
}
|
||||
|
||||
override fun contains(descriptor: DeclarationDescriptor): Boolean {
|
||||
return getCurrentFrame().contains(descriptor)
|
||||
override fun contains(symbol: IrSymbol): Boolean {
|
||||
return getCurrentFrame().contains(symbol)
|
||||
}
|
||||
|
||||
override fun hasReturnValue(): Boolean {
|
||||
@@ -132,12 +132,12 @@ private class FrameContainer(current: Frame = InterpreterFrame()) {
|
||||
fun addVar(variable: Variable) = getTopFrame().addVar(variable)
|
||||
fun addAll(variables: List<Variable>) = getTopFrame().addAll(variables)
|
||||
fun getAll() = innerStack.flatMap { it.getAll() }
|
||||
fun getVariable(variableDescriptor: DeclarationDescriptor): Variable {
|
||||
return innerStack.firstNotNullResult { it.getVariable(variableDescriptor) }
|
||||
?: throw InterpreterException("$variableDescriptor not found") // TODO better message
|
||||
fun getVariable(symbol: IrSymbol): Variable {
|
||||
return innerStack.firstNotNullResult { it.getVariable(symbol) }
|
||||
?: throw InterpreterException("$symbol not found") // TODO better message
|
||||
}
|
||||
|
||||
fun contains(descriptor: DeclarationDescriptor) = innerStack.any { it.contains(descriptor) }
|
||||
fun contains(symbol: IrSymbol) = innerStack.any { it.contains(symbol) }
|
||||
fun hasReturnValue() = getTopFrame().hasReturnValue()
|
||||
fun pushReturnValue(container: FrameContainer) = getTopFrame().pushReturnValue(container.getTopFrame())
|
||||
fun pushReturnValue(state: State) = getTopFrame().pushReturnValue(state)
|
||||
|
||||
+2
-11
@@ -6,15 +6,6 @@
|
||||
package org.jetbrains.kotlin.backend.common.interpreter.stack
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.state.State
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
|
||||
data class Variable(val descriptor: DeclarationDescriptor, var state: State) {
|
||||
override fun toString(): String {
|
||||
val descriptorName = when (descriptor) {
|
||||
is ReceiverParameterDescriptor -> descriptor.containingDeclaration.name.toString() + "::this"
|
||||
else -> descriptor.name
|
||||
}
|
||||
return "Variable(descriptor=$descriptorName, state=$state)"
|
||||
}
|
||||
}
|
||||
data class Variable(val symbol: IrSymbol, var state: State)
|
||||
+9
-7
@@ -5,18 +5,18 @@
|
||||
|
||||
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.getLastOverridden
|
||||
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.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization
|
||||
import org.jetbrains.kotlin.ir.util.isInterface
|
||||
import org.jetbrains.kotlin.ir.util.overrides
|
||||
|
||||
abstract class Complex(override val irClass: IrClass, override val fields: MutableList<Variable>) : State {
|
||||
var superClass: Complex? = null
|
||||
@@ -45,12 +45,14 @@ abstract class Complex(override val irClass: IrClass, override val fields: Mutab
|
||||
return irClass.fqNameForIrSerialization.toString()
|
||||
}
|
||||
|
||||
private fun contains(variable: Variable) = fields.any { it.descriptor == variable.descriptor }
|
||||
private fun contains(variable: Variable) = fields.any { it.symbol == variable.symbol }
|
||||
|
||||
private fun getIrFunction(descriptor: FunctionDescriptor): IrFunction? {
|
||||
private fun getIrFunction(symbol: IrFunctionSymbol): IrFunction? {
|
||||
val propertyGetters = irClass.declarations.filterIsInstance<IrProperty>().mapNotNull { it.getter }
|
||||
val functions = irClass.declarations.filterIsInstance<IrFunction>()
|
||||
return (propertyGetters + functions).singleOrNull { it.descriptor.equalTo(descriptor) }
|
||||
return (propertyGetters + functions).firstOrNull {
|
||||
if (it is IrSimpleFunction) it.overrides(symbol.owner as IrSimpleFunction) else it == symbol.owner
|
||||
}
|
||||
}
|
||||
|
||||
private fun getThisOrSuperReceiver(superIrClass: IrClass?): Complex? {
|
||||
@@ -80,7 +82,7 @@ abstract class Complex(override val irClass: IrClass, override val fields: Mutab
|
||||
override fun getIrFunctionByIrCall(expression: IrCall): IrFunction? {
|
||||
val receiver = getThisOrSuperReceiver(expression.superQualifierSymbol?.owner) ?: return null
|
||||
|
||||
val irFunction = receiver.getIrFunction(expression.symbol.descriptor) ?: return null
|
||||
val irFunction = receiver.getIrFunction(expression.symbol) ?: return null
|
||||
|
||||
return when (irFunction.body) {
|
||||
null -> getOverridden(irFunction as IrSimpleFunction, this.getCorrectReceiverByFunction(irFunction))
|
||||
|
||||
+22
-22
@@ -5,12 +5,13 @@
|
||||
|
||||
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.stack.Variable
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.toState
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrField
|
||||
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.util.isSubclassOf
|
||||
import org.jetbrains.kotlin.ir.util.nameForIrSerialization
|
||||
import kotlin.math.min
|
||||
@@ -21,15 +22,15 @@ class ExceptionState private constructor(
|
||||
|
||||
private lateinit var exceptionFqName: String
|
||||
private val exceptionHierarchy = mutableListOf<String>()
|
||||
private val messageProperty = irClass.getPropertyByName("message")
|
||||
private val causeProperty = irClass.getPropertyByName("cause")
|
||||
private val messageField = irClass.getFieldByName("message")
|
||||
private val causeField = irClass.getFieldByName("cause")
|
||||
|
||||
private val stackTrace: List<String> = stackTrace.reversed()
|
||||
|
||||
init {
|
||||
if (!this::exceptionFqName.isInitialized) this.exceptionFqName = irClassFqName()
|
||||
|
||||
if (fields.none { it.descriptor.equalTo(messageProperty.descriptor) }) {
|
||||
if (fields.none { it.symbol == messageField.symbol }) {
|
||||
setMessage()
|
||||
}
|
||||
}
|
||||
@@ -57,7 +58,7 @@ class ExceptionState private constructor(
|
||||
}
|
||||
|
||||
data class ExceptionData(val state: ExceptionState) : Throwable() {
|
||||
override val message: String? = state.getMessage().value
|
||||
override val message: String? = state.getMessage()
|
||||
override fun fillInStackTrace() = this
|
||||
|
||||
override fun toString(): String = state.getMessageWithName()
|
||||
@@ -66,8 +67,8 @@ class ExceptionState private constructor(
|
||||
private fun setUpCauseIfNeeded(wrapper: Wrapper?) {
|
||||
val cause = (wrapper?.value as? Throwable)?.cause as? ExceptionData
|
||||
setCause(cause?.state)
|
||||
if (getMessage().value == null && cause != null) {
|
||||
val causeMessage = cause.state.exceptionFqName + (cause.state.getMessage().value?.let { ": $it" } ?: "")
|
||||
if (getMessage() == null && cause != null) {
|
||||
val causeMessage = cause.state.exceptionFqName + (cause.state.getMessage()?.let { ": $it" } ?: "")
|
||||
setMessage(causeMessage)
|
||||
}
|
||||
}
|
||||
@@ -80,21 +81,21 @@ class ExceptionState private constructor(
|
||||
}
|
||||
|
||||
private fun setMessage(messageValue: String? = null) {
|
||||
setField(Variable(messageProperty.descriptor, Primitive(messageValue, messageProperty.getter!!.returnType)))
|
||||
setField(Variable(messageField.symbol, Primitive(messageValue, messageField.type)))
|
||||
}
|
||||
|
||||
private fun setCause(causeValue: State?) {
|
||||
setField(Variable(causeProperty.descriptor, causeValue ?: Primitive<Throwable?>(null, causeProperty.getter!!.returnType)))
|
||||
setField(Variable(causeField.symbol, causeValue ?: Primitive<Throwable?>(null, causeField.type)))
|
||||
}
|
||||
|
||||
fun getMessage(): Primitive<String?> = getState(messageProperty.descriptor) as Primitive<String?>
|
||||
private fun getMessageWithName(): String = getMessage().value?.let { "$exceptionFqName: $it" } ?: exceptionFqName
|
||||
fun getMessage(): String? = (getState(messageField.symbol) as Primitive<*>).value as String?
|
||||
private fun getMessageWithName(): String = getMessage()?.let { "$exceptionFqName: $it" } ?: exceptionFqName
|
||||
|
||||
fun getCause(): ExceptionState? = getState(causeProperty.descriptor)?.let { if (it is ExceptionState) it else null }
|
||||
fun getCause(): ExceptionState? = getState(causeField.symbol)?.let { if (it is ExceptionState) it else null }
|
||||
|
||||
fun getFullDescription(): String {
|
||||
// TODO remainder of the stack trace with "..."
|
||||
val message = getMessage().value.let { if (it?.isNotEmpty() == true) ": $it" else "" }
|
||||
val message = getMessage().let { if (it?.isNotEmpty() == true) ": $it" else "" }
|
||||
val prefix = if (stackTrace.isNotEmpty()) "\n\t" else ""
|
||||
val postfix = if (stackTrace.size > 10) "\n\t..." else ""
|
||||
val causeMessage = getCause()?.getFullDescription()?.replaceFirst("Exception ", "\nCaused by: ") ?: ""
|
||||
@@ -106,19 +107,18 @@ class ExceptionState private constructor(
|
||||
fun getThisAsCauseForException() = ExceptionData(this)
|
||||
|
||||
companion object {
|
||||
private fun IrClass.getPropertyByName(name: String): IrProperty {
|
||||
val getPropertyFun = this.declarations.firstOrNull { it.nameForIrSerialization.asString().contains("get-$name") }
|
||||
return (getPropertyFun as? IrFunctionImpl)?.correspondingPropertySymbol?.owner
|
||||
?: this.declarations.single { it.nameForIrSerialization.asString() == name } as IrProperty
|
||||
private fun IrClass.getFieldByName(name: String): IrField {
|
||||
val property = this.declarations.single { it.nameForIrSerialization.asString() == name } as IrProperty
|
||||
return (property.getter!!.getLastOverridden() as IrSimpleFunction).correspondingPropertySymbol!!.owner.backingField!!
|
||||
}
|
||||
|
||||
private fun evaluateFields(exception: Throwable, irClass: IrClass, stackTrace: List<String>): MutableList<Variable> {
|
||||
val messageProperty = irClass.getPropertyByName("message")
|
||||
val causeProperty = irClass.getPropertyByName("cause")
|
||||
val messageField = irClass.getFieldByName("message")
|
||||
val causeField = irClass.getFieldByName("cause")
|
||||
|
||||
val messageVar = Variable(messageProperty.descriptor, exception.message.toState(messageProperty.getter!!.returnType))
|
||||
val messageVar = Variable(messageField.symbol, exception.message.toState(messageField.type))
|
||||
val causeVar = exception.cause?.let {
|
||||
Variable(causeProperty.descriptor, ExceptionState(it, irClass, stackTrace + it.stackTrace.reversed().map { "at $it" }))
|
||||
Variable(causeField.symbol, ExceptionState(it, irClass, stackTrace + it.stackTrace.reversed().map { "at $it" }))
|
||||
}
|
||||
return listOfNotNull(messageVar, causeVar).toMutableList()
|
||||
}
|
||||
|
||||
+8
-4
@@ -5,22 +5,26 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.common.interpreter.state
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.equalTo
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.getFqName
|
||||
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.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.util.nameForIrSerialization
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
|
||||
class Lambda(val irFunction: IrFunction, override val irClass: IrClass) : State {
|
||||
override val fields: MutableList<Variable> = mutableListOf()
|
||||
|
||||
// irFunction is anonymous declaration, but irCall will contain descriptor of invoke method from Function interface
|
||||
private val invokeDescriptor = irClass.declarations.single { it.nameForIrSerialization.asString() == "invoke" }.descriptor
|
||||
private val invokeSymbol = irClass.declarations
|
||||
.single { it.nameForIrSerialization.asString() == "invoke" }
|
||||
.cast<IrSimpleFunction>()
|
||||
.getLastOverridden().symbol
|
||||
|
||||
override fun getIrFunctionByIrCall(expression: IrCall): IrFunction? {
|
||||
return if (invokeDescriptor.equalTo(expression.symbol.descriptor)) irFunction else null
|
||||
return if (invokeSymbol == expression.symbol) irFunction else null
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
|
||||
+3
-2
@@ -12,6 +12,7 @@ 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.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||
import org.jetbrains.kotlin.ir.util.isFakeOverride
|
||||
@@ -20,8 +21,8 @@ class Primitive<T>(var value: T, val type: IrType) : State {
|
||||
override val fields: MutableList<Variable> = mutableListOf()
|
||||
override val irClass: IrClass = type.classOrNull!!.owner
|
||||
|
||||
override fun getState(descriptor: DeclarationDescriptor): State {
|
||||
return super.getState(descriptor) ?: this
|
||||
override fun getState(symbol: IrSymbol): State {
|
||||
return super.getState(symbol) ?: this
|
||||
}
|
||||
|
||||
override fun getIrFunctionByIrCall(expression: IrCall): IrFunction? {
|
||||
|
||||
+4
-5
@@ -5,23 +5,22 @@
|
||||
|
||||
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.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
|
||||
interface State {
|
||||
val fields: MutableList<Variable>
|
||||
val irClass: IrClass
|
||||
|
||||
fun getState(descriptor: DeclarationDescriptor): State? {
|
||||
return fields.firstOrNull { it.descriptor.equalTo(descriptor) }?.state
|
||||
fun getState(symbol: IrSymbol): State? {
|
||||
return fields.firstOrNull { it.symbol == symbol }?.state
|
||||
}
|
||||
|
||||
fun setField(newVar: Variable) {
|
||||
when (val oldState = fields.firstOrNull { it.descriptor == newVar.descriptor }) {
|
||||
when (val oldState = fields.firstOrNull { it.symbol == newVar.symbol }) {
|
||||
null -> fields.add(newVar) // newVar isn't present in value list
|
||||
else -> fields[fields.indexOf(oldState)].state = newVar.state // newVar already present
|
||||
}
|
||||
|
||||
-1
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.backend.common.interpreter.getEvaluateIntrinsicValue
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.getFqName
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.getPrimitiveClass
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.hasAnnotation
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.stack.Variable
|
||||
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
|
||||
Reference in New Issue
Block a user