From a25896bf6a77df2d5442d42d383b68cf1d532d34 Mon Sep 17 00:00:00 2001 From: Ivan Kylchik Date: Thu, 23 Jan 2020 15:41:29 +0300 Subject: [PATCH] Implement string concatenation interpretation --- .../common/interpreter/IrInterpreter.kt | 27 ++++++++++++++++++- .../backend/common/interpreter/stack/State.kt | 6 +++++ 2 files changed, 32 insertions(+), 1 deletion(-) 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 5b0692ead40..e57ed7a00d6 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 @@ -89,13 +89,14 @@ class IrInterpreter(irModule: IrModuleFragment) { is IrTry -> interpretTry(this, data) is IrCatch -> interpretCatch(this, data) is IrThrow -> interpretThrow(this, data) + is IrStringConcatenation -> interpretStringConcatenation(this, data) else -> TODO("${this.javaClass} not supported") } return when (code) { Code.RETURN -> when (this) { // TODO check label - is IrCall, is IrReturnableBlock -> Code.NEXT + is IrCall, is IrReturnableBlock, is IrFunctionImpl -> Code.NEXT else -> Code.RETURN } Code.BREAK_WHEN -> when (this) { @@ -510,4 +511,28 @@ class IrInterpreter(irModule: IrModuleFragment) { expression.value.interpret(data) return Code.EXCEPTION } + + private fun interpretStringConcatenation(expression: IrStringConcatenation, data: Frame): Code { + val result = StringBuilder() + expression.arguments.forEach { + it.interpret(data).also { code -> if (code != Code.NEXT) return code } + result.append( + when (val returnValue = data.popReturnValue()) { + is Primitive<*> -> returnValue.value.toString() + is Wrapper -> returnValue.value.toString() + is Complex -> { + val toStringFun = returnValue.getToStringFunction() + val newFrame = InterpreterFrame(mutableListOf(Variable(toStringFun.symbol.getReceiver()!!, returnValue))) + val code = toStringFun.body?.let { toStringFun.interpret(newFrame) } ?: calculateOverridden(toStringFun, newFrame) + if (code != Code.NEXT) return code + (newFrame.popReturnValue() as Primitive<*>).value.toString() + } + else -> throw AssertionError("$returnValue cannot be used in StringConcatenation expression") + } + ) + } + + data.pushReturnValue(result.toString().toState(expression.type)) + return Code.NEXT + } } \ No newline at end of file diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/stack/State.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/stack/State.kt index 53951dd418c..18933c825e5 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/stack/State.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/stack/State.kt @@ -122,6 +122,12 @@ open class Complex(override var irClass: IrClass, override val fields: MutableLi .firstOrNull { it.descriptor.valueParameters.map { it.type } == descriptor.valueParameters.map { it.type } } } + fun getToStringFunction(): IrFunctionImpl { + return irClass.declarations.filterIsInstance() + .filter { it.descriptor.name.asString() == "toString" } + .first { it.descriptor.valueParameters.isEmpty() } as IrFunctionImpl + } + override fun copy(): State { return Complex(irClass, fields).apply { this@apply.superType = this@Complex.superType