Implement string concatenation interpretation

This commit is contained in:
Ivan Kylchik
2020-01-23 15:41:29 +03:00
parent 0839e7afdc
commit a25896bf6a
2 changed files with 32 additions and 1 deletions
@@ -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
}
}
@@ -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<IrFunction>()
.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