From 04b36ff19ea6164535c4c28adb3919474badd078 Mon Sep 17 00:00:00 2001 From: Ivan Kylchik Date: Fri, 2 Apr 2021 17:05:39 +0300 Subject: [PATCH] Make interpreted functions implicitly return Unit as result --- .../kotlin/ir/interpreter/InstructionsUnfolder.kt | 9 ++++++++- .../kotlin/ir/interpreter/IrInterpreter.kt | 13 +++++-------- .../ir/interpreter/IrInterpreterEnvironment.kt | 5 +++++ .../jetbrains/kotlin/ir/interpreter/stack/Frame.kt | 2 +- .../jetbrains/kotlin/ir/interpreter/state/State.kt | 1 + 5 files changed, 20 insertions(+), 10 deletions(-) diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/InstructionsUnfolder.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/InstructionsUnfolder.kt index ad934e26e7b..716436ee6b5 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/InstructionsUnfolder.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/InstructionsUnfolder.kt @@ -192,11 +192,18 @@ private fun unfoldBlock(block: IrBlock, callStack: CallStack) { } private fun unfoldStatements(statements: List, callStack: CallStack) { + fun dropUnitResult() { + if (callStack.peekState().isUnit()) callStack.popState() + } + for (i in statements.indices.reversed()) { when (val statement = statements[i]) { is IrClass -> if (!statement.isLocal) TODO("Only local classes are supported") is IrFunction -> if (!statement.isLocal) TODO("Only local functions are supported") - else -> callStack.addInstruction(CompoundInstruction(statement)) + else -> { + callStack.addInstruction(CustomInstruction(::dropUnitResult)) + callStack.addInstruction(CompoundInstruction(statement)) + } } } } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt index 22e22865285..daee54f18f6 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt @@ -57,9 +57,7 @@ class IrInterpreter private constructor( if (commandCount >= IrInterpreterEnvironment.MAX_COMMANDS) InterpreterTimeOutError().handleUserException(environment) } - private fun getUnitState(): State { - return environment.mapOfObjects.getOrPut(irBuiltIns.unitClass) { Common(irBuiltIns.unitClass.owner) } - } + private fun getUnitState(): State = environment.mapOfObjects[irBuiltIns.unitClass]!! private fun Instruction.handle() { when (this) { @@ -91,7 +89,7 @@ class IrInterpreter private constructor( incrementAndCheckCommands() } - if (callStack.peekState() == null) callStack.pushState(getUnitState()) // TODO maybe move this logic to body/block + if (callStack.peekState() == null) callStack.pushState(getUnitState()) callStack.popState().apply { callStack.dropFrame() } } } @@ -141,9 +139,8 @@ class IrInterpreter private constructor( private fun interpretFunction(function: IrSimpleFunction) { function.tryResetFunctionBody() - if (function.checkCast(environment)) { - callStack.dropFrameAndCopyResult() - } + if (callStack.peekState() == null) callStack.pushState(getUnitState()) // implicit Unit return + if (function.checkCast(environment)) callStack.dropFrameAndCopyResult() } private fun interpretValueParameter(valueParameter: IrValueParameter) { @@ -251,7 +248,7 @@ class IrInterpreter private constructor( if (irClass.isLocal) callStack.storeUpValues(objectVar.state as StateWithClosure) val outerClass = if (irClass.isInner) callStack.popState() else null - callStack.dropSubFrame() // TODO check that data stack is empty + callStack.dropSubFrame() callStack.newFrame(constructor, listOf(SimpleInstruction(constructor))) callStack.addVariable(objectVar) constructor.valueParameters.forEachIndexed { i, param -> callStack.addVariable(Variable(param.symbol, valueArguments[i])) } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreterEnvironment.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreterEnvironment.kt index cd5579c40fd..e3accbb7b6b 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreterEnvironment.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreterEnvironment.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.interpreter.stack.CallStack +import org.jetbrains.kotlin.ir.interpreter.state.Common import org.jetbrains.kotlin.ir.interpreter.state.Complex import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.util.isSubclassOf @@ -18,6 +19,10 @@ internal class IrInterpreterEnvironment(val irBuiltIns: IrBuiltIns, val callStac var mapOfEnums = mutableMapOf() var mapOfObjects = mutableMapOf() + init { + mapOfObjects[irBuiltIns.unitClass] = Common(irBuiltIns.unitClass.owner) + } + private constructor(environment: IrInterpreterEnvironment) : this(environment.irBuiltIns, CallStack()) { irExceptions.addAll(environment.irExceptions) mapOfEnums = environment.mapOfEnums diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/stack/Frame.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/stack/Frame.kt index 74cea11691d..cc8067f53c6 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/stack/Frame.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/stack/Frame.kt @@ -66,7 +66,7 @@ internal class Frame(subFrame: SubFrame, val irFile: IrFile? = null) { } fun getVariable(symbol: IrSymbol): Variable { - return innerStack.firstNotNullResult { it.getVariable(symbol) } + return innerStack.reversed().firstNotNullResult { it.getVariable(symbol) } ?: throw InterpreterError("$symbol not found") // TODO better message } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/State.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/State.kt index a44882801ed..e1e64ee893c 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/State.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/State.kt @@ -34,6 +34,7 @@ internal interface State { } internal fun State.isNull() = this is Primitive<*> && this.value == null +internal fun State?.isUnit() = this is Common && this.irClassFqName() == "kotlin.Unit" internal fun State.asInt() = (this as Primitive<*>).value as Int internal fun State.asBoolean() = (this as Primitive<*>).value as Boolean