Move all interpreter methods inside IrInterpreter class

This commit is contained in:
Ivan Kylchik
2019-12-08 16:17:01 +03:00
parent f8cb637712
commit 178b2a07ae
@@ -5,10 +5,12 @@
package org.jetbrains.kotlin.backend.common.interpreter package org.jetbrains.kotlin.backend.common.interpreter
import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.interpreter.builtins.CompileTimeFunction import org.jetbrains.kotlin.backend.common.interpreter.builtins.CompileTimeFunction
import org.jetbrains.kotlin.backend.common.interpreter.builtins.binaryFunctions import org.jetbrains.kotlin.backend.common.interpreter.builtins.binaryFunctions
import org.jetbrains.kotlin.backend.common.interpreter.builtins.unaryFunctions import org.jetbrains.kotlin.backend.common.interpreter.builtins.unaryFunctions
import org.jetbrains.kotlin.backend.common.interpreter.stack.* import org.jetbrains.kotlin.backend.common.interpreter.stack.*
import org.jetbrains.kotlin.backend.common.ir.Symbols
import org.jetbrains.kotlin.builtins.DefaultBuiltIns import org.jetbrains.kotlin.builtins.DefaultBuiltIns
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
@@ -25,31 +27,33 @@ enum class Code(var info: String = "") {
NEXT, RETURN, BREAK_LOOP, BREAK_WHEN, CONTINUE, EXCEPTION NEXT, RETURN, BREAK_LOOP, BREAK_WHEN, CONTINUE, EXCEPTION
} }
fun interpret(expression: IrExpression): IrExpression { class IrInterpreter(private val irSymbols: Symbols<CommonBackendContext>) {
return InterpreterFrame().apply { expression.interpret(this) }.popReturnValue().toIrExpression(expression)
}
fun IrElement.interpret(data: Frame): Code { fun interpret(expression: IrExpression): IrExpression {
return InterpreterFrame().apply { expression.interpret(this) }.popReturnValue().toIrExpression(expression)
}
private fun IrElement.interpret(data: Frame): Code {
try { try {
val code = when (this) { val code = when (this) {
is IrCall -> this.interpretCall(data) is IrCall -> interpretCall(this, data)
is IrConstructorCall -> this.interpretConstructorCall(data) is IrConstructorCall -> interpretConstructorCall(this, data)
is IrDelegatingConstructorCall -> this.interpretDelegatedConstructorCall(data) is IrDelegatingConstructorCall -> interpretDelegatedConstructorCall(this, data)
is IrBody -> this.interpretBody(data) is IrBody -> interpretBody(this, data)
is IrBlock -> this.interpretBlock(data) is IrBlock -> interpretBlock(this, data)
is IrReturn -> this.interpretReturn(data) is IrReturn -> interpretReturn(this, data)
is IrSetField -> this.interpretSetField(data) is IrSetField -> interpretSetField(this, data)
is IrGetField -> this.interpretGetField(data) is IrGetField -> interpretGetField(this, data)
is IrGetValue -> this.interpretGetValue(data) is IrGetValue -> interpretGetValue(this, data)
is IrGetObjectValue -> this.interpretGetObjectValue(data) is IrGetObjectValue -> interpretGetObjectValue(this, data)
is IrConst<*> -> this.interpretConst(data) is IrConst<*> -> interpretConst(this, data)
is IrVariable -> this.interpretVariable(data) is IrVariable -> interpretVariable(this, data)
is IrSetVariable -> this.interpretSetVariable(data) is IrSetVariable -> interpretSetVariable(this, data)
is IrTypeOperatorCall -> this.interpretTypeOperatorCall(data) is IrTypeOperatorCall -> interpretTypeOperatorCall(this, data)
is IrBranch -> this.interpretBranch(data) is IrBranch -> interpretBranch(this, data)
is IrWhileLoop -> this.interpretWhile(data) is IrWhileLoop -> interpretWhile(this, data)
is IrWhen -> this.interpretWhen(data) is IrWhen -> interpretWhen(this, data)
is IrBreak -> this.interpretBreak(data) is IrBreak -> interpretBreak(this, data)
else -> TODO("${this.javaClass} not supported") else -> TODO("${this.javaClass} not supported")
} }
@@ -76,14 +80,14 @@ fun IrElement.interpret(data: Frame): Code {
assert(false) assert(false)
return Code.EXCEPTION return Code.EXCEPTION
} }
} }
private fun calculateAbstract(irFunction: IrFunction, data: Frame): Code { private fun calculateAbstract(irFunction: IrFunction, data: Frame): Code {
return irFunction.body?.interpret(data) return irFunction.body?.interpret(data)
?: throw NoSuchMethodException("Method \"${irFunction.name}\" wasn't implemented") ?: throw NoSuchMethodException("Method \"${irFunction.name}\" wasn't implemented")
} }
private fun calculateOverridden(owner: IrFunctionImpl, data: Frame): Code { private fun calculateOverridden(owner: IrFunctionImpl, data: Frame): Code {
val variableDescriptor = owner.symbol.getThisAsReceiver()!! val variableDescriptor = owner.symbol.getThisAsReceiver()!!
val superQualifier = (data.getVariableState(variableDescriptor) as Complex).getSuperQualifier()!! val superQualifier = (data.getVariableState(variableDescriptor) as Complex).getSuperQualifier()!!
val overridden = owner.overriddenSymbols.first { it.getThisAsReceiver()?.equalTo(superQualifier.getThisReceiver()) == true } val overridden = owner.overriddenSymbols.first { it.getThisAsReceiver()?.equalTo(superQualifier.getThisReceiver()) == true }
@@ -98,9 +102,9 @@ private fun calculateOverridden(owner: IrFunctionImpl, data: Frame): Code {
body != null -> body.interpret(newStates) body != null -> body.interpret(newStates)
else -> calculateOverridden(overriddenOwner, newStates) else -> calculateOverridden(overriddenOwner, newStates)
}.apply { data.pushReturnValue(newStates) } }.apply { data.pushReturnValue(newStates) }
} }
private fun isBuiltIn(irFunction: IrFunction): Boolean { private fun isBuiltIn(irFunction: IrFunction): Boolean {
val descriptor = irFunction.descriptor val descriptor = irFunction.descriptor
val methodName = descriptor.name.asString() val methodName = descriptor.name.asString()
val receiverType = descriptor.dispatchReceiverParameter?.type ?: descriptor.extensionReceiverParameter?.type val receiverType = descriptor.dispatchReceiverParameter?.type ?: descriptor.extensionReceiverParameter?.type
@@ -109,9 +113,9 @@ private fun isBuiltIn(irFunction: IrFunction): Boolean {
methodName, methodName,
argsType.map { it.toString() }) argsType.map { it.toString() })
return (unaryFunctions[signature] ?: binaryFunctions[signature]) != null return (unaryFunctions[signature] ?: binaryFunctions[signature]) != null
} }
private fun calculateBuiltIns(expression: IrCall, data: Frame): Code { private fun calculateBuiltIns(expression: IrCall, data: Frame): Code {
val descriptor = expression.symbol.descriptor val descriptor = expression.symbol.descriptor
val methodName = descriptor.name.asString() val methodName = descriptor.name.asString()
val receiverType = descriptor.dispatchReceiverParameter?.type ?: descriptor.extensionReceiverParameter?.type val receiverType = descriptor.dispatchReceiverParameter?.type ?: descriptor.extensionReceiverParameter?.type
@@ -140,9 +144,9 @@ private fun calculateBuiltIns(expression: IrCall, data: Frame): Code {
} }
data.pushReturnValue(result.toState(expression)) data.pushReturnValue(result.toState(expression))
return Code.NEXT return Code.NEXT
} }
private fun calculateRangeTo(expression: IrExpression, data: Frame): Code { private fun calculateRangeTo(expression: IrExpression, data: Frame): Code {
val constructor = expression.type.classOrNull!!.owner.constructors.first() val constructor = expression.type.classOrNull!!.owner.constructors.first()
val constructorCall = IrConstructorCallImpl.fromSymbolOwner(constructor.returnType, constructor.symbol) val constructorCall = IrConstructorCallImpl.fromSymbolOwner(constructor.returnType, constructor.symbol)
@@ -155,27 +159,27 @@ private fun calculateRangeTo(expression: IrExpression, data: Frame): Code {
val code = constructorCall.interpret(newFrame) val code = constructorCall.interpret(newFrame)
data.pushReturnValue(newFrame) data.pushReturnValue(newFrame)
return code return code
} }
fun IrMemberAccessExpression.interpretValueParameters(data: Frame): Code { private fun interpretValueParameters(parametersContainer: IrMemberAccessExpression, data: Frame): Code {
for (i in (this.valueArgumentsCount - 1) downTo 0) { for (i in (parametersContainer.valueArgumentsCount - 1) downTo 0) {
val code = this.getValueArgument(i)?.interpret(data) ?: Code.NEXT val code = parametersContainer.getValueArgument(i)?.interpret(data) ?: Code.NEXT
if (code != Code.NEXT) return code if (code != Code.NEXT) return code
} }
return Code.NEXT return Code.NEXT
} }
fun IrCall.interpretCall(data: Frame): Code { private fun interpretCall(expression: IrCall, data: Frame): Code {
val newFrame = InterpreterFrame() val newFrame = InterpreterFrame()
this.interpretValueParameters(data).also { if (it != Code.NEXT) return it } interpretValueParameters(expression, data).also { if (it != Code.NEXT) return it }
val valueParameters = this.symbol.descriptor.valueParameters.map { Variable(it, data.popReturnValue()) } val valueParameters = expression.symbol.descriptor.valueParameters.map { Variable(it, data.popReturnValue()) }
val rawReceiver = this.dispatchReceiver ?: this.extensionReceiver val rawReceiver = expression.dispatchReceiver ?: expression.extensionReceiver
rawReceiver?.interpret(data)?.also { if (it != Code.NEXT) return it } rawReceiver?.interpret(data)?.also { if (it != Code.NEXT) return it }
val receiver = rawReceiver?.let { data.popReturnValue() } val receiver = rawReceiver?.let { data.popReturnValue() }
val irFunction = receiver.getIrFunction(this) val irFunction = receiver.getIrFunction(expression)
val receiverParameter = irFunction.symbol.getThisAsReceiver() val receiverParameter = irFunction.symbol.getThisAsReceiver()
// it is important firstly to add receiver, then arguments // it is important firstly to add receiver, then arguments
receiver?.let { newFrame.addVar(Variable(receiverParameter!!, it)) } receiver?.let { newFrame.addVar(Variable(receiverParameter!!, it)) }
@@ -183,165 +187,170 @@ fun IrCall.interpretCall(data: Frame): Code {
val code = when { val code = when {
//irFunction.annotations.any { it.descriptor.containingDeclaration.fqNameSafe == evaluateIntrinsicAnnotation } -> empty //irFunction.annotations.any { it.descriptor.containingDeclaration.fqNameSafe == evaluateIntrinsicAnnotation } -> empty
isBuiltIn(irFunction) -> calculateBuiltIns(this, newFrame) isBuiltIn(irFunction) -> calculateBuiltIns(expression, newFrame)
this.isAbstract() -> calculateAbstract(irFunction, newFrame) //abstract check must be before fake overridden check expression.isAbstract() -> calculateAbstract(
this.isFakeOverridden() -> calculateOverridden(irFunction as IrFunctionImpl, newFrame) irFunction,
else -> (irFunction.body ?: this.getBody())!!.interpret(newFrame) newFrame
) //abstract check must be before fake overridden check
expression.isFakeOverridden() -> calculateOverridden(irFunction as IrFunctionImpl, newFrame)
else -> (irFunction.body ?: expression.getBody())!!.interpret(newFrame)
} }
data.pushReturnValue(newFrame) data.pushReturnValue(newFrame)
return code return code
} }
fun IrFunctionAccessExpression.interpretConstructor(data: Frame): Code { private fun interpretConstructor(constructorCall: IrFunctionAccessExpression, data: Frame): Code {
this.interpretValueParameters(data).also { if (it != Code.NEXT) return it } interpretValueParameters(constructorCall, data).also { if (it != Code.NEXT) return it }
val valueParameters = this.symbol.descriptor.valueParameters.map { Variable(it, data.popReturnValue()) }.toMutableList() val valueParameters = constructorCall.symbol.descriptor.valueParameters.map { Variable(it, data.popReturnValue()) }.toMutableList()
val newFrame = InterpreterFrame(valueParameters) val newFrame = InterpreterFrame(valueParameters)
val state = Complex(this.symbol.owner.parent as IrClass, mutableListOf()) val state = Complex(constructorCall.symbol.owner.parent as IrClass, mutableListOf())
newFrame.addVar(Variable(this.getThisAsReceiver(), state)) //used to set up fields in body newFrame.addVar(Variable(constructorCall.getThisAsReceiver(), state)) //used to set up fields in body
val code = this.getBody()?.interpret(newFrame) ?: Code.NEXT val code = constructorCall.getBody()?.interpret(newFrame) ?: Code.NEXT
if (newFrame.hasReturnValue()) { if (newFrame.hasReturnValue()) {
state.setSuperQualifier(newFrame.popReturnValue() as Complex) state.setSuperQualifier(newFrame.popReturnValue() as Complex)
} }
data.pushReturnValue(state) data.pushReturnValue(state)
return code return code
} }
fun IrConstructorCall.interpretConstructorCall(data: Frame): Code { private fun interpretConstructorCall(constructorCall: IrConstructorCall, data: Frame): Code {
return this.interpretConstructor(data) return interpretConstructor(constructorCall, data)
} }
fun IrDelegatingConstructorCall.interpretDelegatedConstructorCall(data: Frame): Code { private fun interpretDelegatedConstructorCall(delegatingConstructorCall: IrDelegatingConstructorCall, data: Frame): Code {
if (this.symbol.descriptor.containingDeclaration.defaultType == DefaultBuiltIns.Instance.anyType) { if (delegatingConstructorCall.symbol.descriptor.containingDeclaration.defaultType == DefaultBuiltIns.Instance.anyType) {
return Code.NEXT return Code.NEXT
} }
return this.interpretConstructor(data) return interpretConstructor(delegatingConstructorCall, data)
} }
fun IrConst<*>.interpretConst(data: Frame): Code { private fun interpretConst(expression: IrConst<*>, data: Frame): Code {
data.pushReturnValue(this.toPrimitive()) data.pushReturnValue(expression.toPrimitive())
return Code.NEXT return Code.NEXT
} }
fun List<IrStatement>.interpretStatements(data: Frame): Code { private fun interpretStatements(statements: List<IrStatement>, data: Frame): Code {
//create newFrame //create newFrame
val newFrame = data.copy() val newFrame = data.copy()
var code = Code.NEXT var code = Code.NEXT
val iterator = this.asSequence().iterator() val iterator = statements.asSequence().iterator()
while (code == Code.NEXT && iterator.hasNext()) { while (code == Code.NEXT && iterator.hasNext()) {
code = iterator.next().interpret(newFrame) code = iterator.next().interpret(newFrame)
} }
data.pushReturnValue(newFrame) data.pushReturnValue(newFrame)
return code return code
} }
fun IrBlock.interpretBlock(data: Frame): Code { private fun interpretBlock(block: IrBlock, data: Frame): Code {
return this.statements.interpretStatements(data) return interpretStatements(block.statements, data)
} }
fun IrBody.interpretBody(data: Frame): Code { private fun interpretBody(body: IrBody, data: Frame): Code {
return this.statements.interpretStatements(data) return interpretStatements(body.statements, data)
} }
fun IrReturn.interpretReturn(data: Frame): Code { private fun interpretReturn(expression: IrReturn, data: Frame): Code {
val code = this.value.interpret(data) val code = expression.value.interpret(data)
return if (code == Code.NEXT) Code.RETURN else code return if (code == Code.NEXT) Code.RETURN else code
} }
fun IrWhileLoop.interpretWhile(data: Frame): Code { private fun interpretWhile(expression: IrWhileLoop, data: Frame): Code {
var code = Code.NEXT var code = Code.NEXT
while (code == Code.NEXT) { while (code == Code.NEXT) {
code = this.condition.interpret(data) code = expression.condition.interpret(data)
if (code == Code.NEXT && (data.popReturnValue() as? Primitive<*>)?.getIrConst()?.value as? Boolean == true) { if (code == Code.NEXT && (data.popReturnValue() as? Primitive<*>)?.getIrConst()?.value as? Boolean == true) {
code = this.body?.interpret(data) ?: Code.NEXT code = expression.body?.interpret(data) ?: Code.NEXT
} else { } else {
break break
} }
} }
return code return code
} }
fun IrWhen.interpretWhen(data: Frame): Code { private fun interpretWhen(expression: IrWhen, data: Frame): Code {
var code = Code.NEXT var code = Code.NEXT
val iterator = this.branches.asSequence().iterator() val iterator = expression.branches.asSequence().iterator()
while (code == Code.NEXT && iterator.hasNext()) { while (code == Code.NEXT && iterator.hasNext()) {
code = iterator.next().interpret(data) code = iterator.next().interpret(data)
} }
return code return code
} }
fun IrBranch.interpretBranch(data: Frame): Code { private fun interpretBranch(expression: IrBranch, data: Frame): Code {
var code = this.condition.interpret(data) var code = expression.condition.interpret(data)
if (code == Code.NEXT && (data.popReturnValue() as? Primitive<*>)?.getIrConst()?.value as? Boolean == true) { if (code == Code.NEXT && (data.popReturnValue() as? Primitive<*>)?.getIrConst()?.value as? Boolean == true) {
code = this.result.interpret(data) code = expression.result.interpret(data)
if (code == Code.NEXT) return Code.BREAK_WHEN if (code == Code.NEXT) return Code.BREAK_WHEN
} }
return code return code
} }
fun IrBreak.interpretBreak(data: Frame): Code { private fun interpretBreak(breakStatement: IrBreak, data: Frame): Code {
return Code.BREAK_LOOP.apply { info = this@interpretBreak.label ?: "" } return Code.BREAK_LOOP.apply { info = breakStatement.label ?: "" }
} }
fun IrSetField.interpretSetField(data: Frame): Code { private fun interpretSetField(expression: IrSetField, data: Frame): Code {
val code = this.value.interpret(data) val code = expression.value.interpret(data)
if (code != Code.NEXT) return code if (code != Code.NEXT) return code
val receiver = (this.receiver as IrDeclarationReference).symbol.descriptor val receiver = (expression.receiver as IrDeclarationReference).symbol.descriptor
data.getVariableState(receiver).setState(Variable(this.symbol.owner.descriptor, data.popReturnValue())) data.getVariableState(receiver).setState(Variable(expression.symbol.owner.descriptor, data.popReturnValue()))
return Code.NEXT return Code.NEXT
} }
fun IrGetField.interpretGetField(data: Frame): Code { private fun interpretGetField(expression: IrGetField, data: Frame): Code {
val receiver = (this.receiver as? IrDeclarationReference)?.symbol?.descriptor // receiver is null, for example, for top level fields val receiver = (expression.receiver as? IrDeclarationReference)?.symbol?.descriptor // receiver is null, for example, for top level fields
val result = receiver?.let { data.getVariableState(receiver).getState(this.symbol.descriptor)?.copy() } val result = receiver?.let { data.getVariableState(receiver).getState(expression.symbol.descriptor)?.copy() }
if (result == null) { if (result == null) {
return this.symbol.owner.initializer?.expression?.interpret(data) ?: Code.NEXT return expression.symbol.owner.initializer?.expression?.interpret(data) ?: Code.NEXT
} }
data.pushReturnValue(result) data.pushReturnValue(result)
return Code.NEXT return Code.NEXT
} }
fun IrGetValue.interpretGetValue(data: Frame): Code { private fun interpretGetValue(expression: IrGetValue, data: Frame): Code {
data.pushReturnValue(data.getVariableState(this.symbol.descriptor).copy()) data.pushReturnValue(data.getVariableState(expression.symbol.descriptor).copy())
return Code.NEXT return Code.NEXT
} }
fun IrVariable.interpretVariable(data: Frame): Code { private fun interpretVariable(expression: IrVariable, data: Frame): Code {
val code = this.initializer?.interpret(data) val code = expression.initializer?.interpret(data)
if (code != Code.NEXT) return code ?: Code.NEXT if (code != Code.NEXT) return code ?: Code.NEXT
data.addVar(Variable(this.descriptor, data.popReturnValue())) data.addVar(Variable(expression.descriptor, data.popReturnValue()))
return Code.NEXT return Code.NEXT
} }
fun IrSetVariable.interpretSetVariable(data: Frame): Code { private fun interpretSetVariable(expression: IrSetVariable, data: Frame): Code {
val code = this.value.interpret(data) val code = expression.value.interpret(data)
if (code != Code.NEXT) return code if (code != Code.NEXT) return code
if (data.contains(this.symbol.descriptor)) { if (data.contains(expression.symbol.descriptor)) {
val variable = data.getVariableState(this.symbol.descriptor) val variable = data.getVariableState(expression.symbol.descriptor)
variable.setState(Variable(this.symbol.descriptor, data.popReturnValue())) variable.setState(Variable(expression.symbol.descriptor, data.popReturnValue()))
} else { } else {
data.addVar(Variable(this.symbol.descriptor, data.popReturnValue())) data.addVar(Variable(expression.symbol.descriptor, data.popReturnValue()))
} }
return Code.NEXT return Code.NEXT
} }
fun IrGetObjectValue.interpretGetObjectValue(data: Frame): Code { private fun interpretGetObjectValue(expression: IrGetObjectValue, data: Frame): Code {
data.pushReturnValue(Complex(this.symbol.owner, mutableListOf())) data.pushReturnValue(Complex(expression.symbol.owner, mutableListOf()))
return Code.NEXT return Code.NEXT
} }
fun IrTypeOperatorCall.interpretTypeOperatorCall(data: Frame): Code { private fun interpretTypeOperatorCall(expression: IrTypeOperatorCall, data: Frame): Code {
return when (this.operator) { return when (expression.operator) {
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT -> { IrTypeOperator.IMPLICIT_COERCION_TO_UNIT -> {
this.argument.interpret(data) expression.argument.interpret(data)
} }
IrTypeOperator.CAST -> { IrTypeOperator.CAST -> {
this.argument.interpret(data) //todo check cast correctness expression.argument.interpret(data) //todo check cast correctness
} }
else -> TODO("${this.operator} not implemented") else -> TODO("${expression.operator} not implemented")
} }
}
} }