From dcd8a4a4c78ad44f42e4a6bc692f71c475ed5363 Mon Sep 17 00:00:00 2001 From: Ivan Kylchik Date: Wed, 13 Nov 2019 17:58:14 +0300 Subject: [PATCH] Add variables support in interpreter --- .../common/interpreter/IrInterpreter.kt | 24 ++++++++++++++--- .../backend/common/interpreter/Utils.kt | 26 ++++++++++++------- .../backend/common/interpreter/stack/Frame.kt | 5 ++++ 3 files changed, 42 insertions(+), 13 deletions(-) diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/IrInterpreter.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/IrInterpreter.kt index e9fa9a2f7c5..6bd19f74e2d 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/IrInterpreter.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/IrInterpreter.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.declarations.IrConstructor +import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.util.isFakeOverride import org.jetbrains.kotlin.ir.util.statements @@ -22,12 +23,12 @@ class IrInterpreter : IrElementVisitor { private val any = Complex(builtIns.any, mutableListOf()) fun interpret(expression: IrExpression): IrExpression { - return visitExpression(expression, InterpreterFrame()).toIrExpression() + return visitExpression(expression, InterpreterFrame()).convertToIrExpression(expression) } - private fun State.toIrExpression(): IrExpression { + private fun State.convertToIrExpression(expression: IrExpression): IrExpression { return when (this) { - is Primitive<*> -> this.getIrConst() + is Primitive<*> -> this.getIrConst().value.toIrConst(expression) // it is necessary to replace ir offsets else -> TODO("not supported") } } @@ -129,4 +130,21 @@ class IrInterpreter : IrElementVisitor { override fun visitGetValue(expression: IrGetValue, data: Frame): State { return data.getVar(expression.symbol.descriptor).copy() } + + override fun visitVariable(declaration: IrVariable, data: Frame): State { + val variable = declaration.initializer?.accept(this, data)?.setDescriptor(declaration.descriptor) + variable?.let { data.addVar(it) } + return unit + } + + override fun visitSetVariable(expression: IrSetVariable, data: Frame): State { + if (data.contains(expression.symbol.descriptor)) { + val variable = data.getVar(expression.symbol.descriptor) + variable.setState(expression.value.accept(this, data)) + } else { + val variable = expression.value.accept(this, data).setDescriptor(expression.symbol.descriptor) + data.addVar(variable) + } + return unit + } } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/Utils.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/Utils.kt index 63ccf86b97e..a0c840fd39b 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/Utils.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/Utils.kt @@ -76,21 +76,27 @@ fun IrFunctionAccessExpression.getBody(): IrBody? { return this.symbol.owner.body } -fun Any.toIrConst(expression: IrExpression): IrConst<*> { +fun Any?.toIrConst(expression: IrExpression): IrConst<*> { return when (this) { - is Boolean -> IrConstImpl(expression.startOffset, expression.endOffset, expression.type, IrConstKind.Boolean, this) - is Char -> IrConstImpl(expression.startOffset, expression.endOffset, expression.type, IrConstKind.Char, this) - is Byte -> IrConstImpl(expression.startOffset, expression.endOffset, expression.type, IrConstKind.Byte, this) - is Short -> IrConstImpl(expression.startOffset, expression.endOffset, expression.type, IrConstKind.Short, this) - is Int -> IrConstImpl(expression.startOffset, expression.endOffset, expression.type, IrConstKind.Int, this) - is Long -> IrConstImpl(expression.startOffset, expression.endOffset, expression.type, IrConstKind.Long, this) - is String -> IrConstImpl(expression.startOffset, expression.endOffset, expression.type, IrConstKind.String, this) - is Float -> IrConstImpl(expression.startOffset, expression.endOffset, expression.type, IrConstKind.Float, this) - is Double -> IrConstImpl(expression.startOffset, expression.endOffset, expression.type, IrConstKind.Double, this) + is Boolean -> expression.copyParametersTo(IrConstKind.Boolean, this) + is Char -> expression.copyParametersTo(IrConstKind.Char, this) + is Byte -> expression.copyParametersTo(IrConstKind.Byte, this) + is Short -> expression.copyParametersTo(IrConstKind.Short, this) + is Int -> expression.copyParametersTo(IrConstKind.Int, this) + is Long -> expression.copyParametersTo(IrConstKind.Long, this) + is String -> expression.copyParametersTo(IrConstKind.String, this) + is Float -> expression.copyParametersTo(IrConstKind.Float, this) + is Double -> expression.copyParametersTo(IrConstKind.Double, this) + null -> expression.copyParametersTo(IrConstKind.Null, this) else -> throw UnsupportedOperationException("Unsupported const element type $this") } } +@Suppress("UNCHECKED_CAST") +private fun IrExpression.copyParametersTo(kind: IrConstKind, value: Any?): IrConst { + return IrConstImpl(startOffset, endOffset, type, kind, value as T) +} + fun IrConst.toPrimitive(): Primitive { return Primitive(this) } \ No newline at end of file diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/stack/Frame.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/stack/Frame.kt index 2924c6a63cb..b57d3f2a733 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/stack/Frame.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/stack/Frame.kt @@ -12,6 +12,7 @@ interface Frame { fun addVar(state: State) fun getVar(descriptor: DeclarationDescriptor): State fun getAll(): List + fun contains(descriptor: DeclarationDescriptor): Boolean } class InterpreterFrame(val pool: MutableList = mutableListOf()) : Frame { @@ -27,4 +28,8 @@ class InterpreterFrame(val pool: MutableList = mutableListOf()) : Frame { override fun getAll(): List { return pool } + + override fun contains(descriptor: DeclarationDescriptor): Boolean { + return pool.any { it.isTypeOf(descriptor) } + } }