Remove coroutines from ir interpreter

This commit is contained in:
Ivan Kylchik
2020-06-22 03:23:12 +03:00
parent f028d6c898
commit 6f4f7dd090
6 changed files with 64 additions and 91 deletions
@@ -5,7 +5,6 @@ plugins {
dependencies {
compile(project(":compiler:ir.tree"))
compileOnly(commonDep("org.jetbrains.kotlinx", "kotlinx-coroutines-core")) { isTransitive = false }
}
sourceSets {
@@ -5,9 +5,6 @@
package org.jetbrains.kotlin.ir.interpreter
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import kotlinx.coroutines.yield
import org.jetbrains.kotlin.ir.interpreter.builtins.*
import org.jetbrains.kotlin.ir.interpreter.exceptions.InterpreterException
import org.jetbrains.kotlin.ir.interpreter.exceptions.InterpreterMethodNotFoundException
@@ -31,8 +28,8 @@ import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import java.lang.invoke.MethodHandle
import kotlin.concurrent.thread
private const val MAX_STACK_SIZE = 10_000
private const val MAX_COMMANDS = 500_000
class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSignature, IrBody> = emptyMap()) {
@@ -72,9 +69,10 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
fun interpret(expression: IrExpression): IrExpression {
stack.clean()
return try {
runBlocking {
return@runBlocking when (val returnLabel = withContext(this.coroutineContext) { expression.interpret().returnLabel }) {
lateinit var result: IrExpression
thread(start = true) {
result = try {
when (val returnLabel = expression.interpret().returnLabel) {
ReturnLabel.REGULAR -> stack.popReturnValue().toIrExpression(expression)
ReturnLabel.EXCEPTION -> {
val message = (stack.popReturnValue() as ExceptionState).getFullDescription()
@@ -82,14 +80,15 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
}
else -> TODO("$returnLabel not supported as result of interpretation")
}
} catch (e: InterpreterException) {
// TODO don't handle, throw to lowering
IrErrorExpressionImpl(expression.startOffset, expression.endOffset, expression.type, "\n" + e.message)
}
} catch (e: InterpreterException) {
// TODO don't handle, throw to lowering
IrErrorExpressionImpl(expression.startOffset, expression.endOffset, expression.type, "\n" + e.message)
}
}.join()
return result
}
private suspend fun IrElement.interpret(): ExecutionResult {
private fun IrElement.interpret(): ExecutionResult {
try {
incrementAndCheckCommands()
val executionResult = when (this) {
@@ -145,18 +144,14 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
}
// this method is used to get stack trace after exception
private suspend fun interpretFunction(irFunction: IrSimpleFunction): ExecutionResult {
yield()
private fun interpretFunction(irFunction: IrSimpleFunction): ExecutionResult {
if (irFunction.fileOrNull != null) stack.setCurrentFrameName(irFunction)
if (stack.getStackTrace().size == MAX_STACK_SIZE) throw StackOverflowError("")
if (irFunction.body is IrSyntheticBody) return handleIntrinsicMethods(irFunction)
return irFunction.body?.interpret() ?: throw InterpreterException("Ir function must be with body")
}
private suspend fun MethodHandle?.invokeMethod(irFunction: IrFunction): ExecutionResult {
private fun MethodHandle?.invokeMethod(irFunction: IrFunction): ExecutionResult {
this ?: return handleIntrinsicMethods(irFunction)
val result = this.invokeWithArguments(irFunction.getArgsForMethodInvocation(stack.getAll()))
stack.pushReturnValue(result.toState(result.getType(irFunction.returnType)))
@@ -164,11 +159,11 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
return Next
}
private suspend fun handleIntrinsicMethods(irFunction: IrFunction): ExecutionResult {
private fun handleIntrinsicMethods(irFunction: IrFunction): ExecutionResult {
return IntrinsicEvaluator().evaluate(irFunction, stack) { this.interpret() }
}
private suspend fun calculateBuiltIns(irFunction: IrFunction): ExecutionResult {
private fun calculateBuiltIns(irFunction: IrFunction): ExecutionResult {
val methodName = when (val property = (irFunction as? IrSimpleFunction)?.correspondingPropertySymbol) {
null -> irFunction.name.asString()
else -> property.owner.name.asString()
@@ -227,7 +222,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
return Next
}
private suspend fun calculateRangeTo(type: IrType): ExecutionResult {
private fun calculateRangeTo(type: IrType): ExecutionResult {
val constructor = type.classOrNull!!.owner.constructors.first()
val constructorCall = IrConstructorCallImpl.fromSymbolOwner(constructor.returnType, constructor.symbol)
@@ -242,7 +237,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
}
}
private suspend fun interpretValueParameters(
private fun interpretValueParameters(
expression: IrFunctionAccessExpression, irFunction: IrFunction, pool: MutableList<Variable>
): ExecutionResult {
// if irFunction is lambda and it has receiver, then first descriptor must be taken from extension receiver
@@ -275,7 +270,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
}
}
private suspend fun interpretCall(expression: IrCall): ExecutionResult {
private fun interpretCall(expression: IrCall): ExecutionResult {
val valueArguments = mutableListOf<Variable>()
// dispatch receiver processing
val rawDispatchReceiver = expression.dispatchReceiver
@@ -322,7 +317,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
}.check { return it }.implicitCastIfNeeded(expression.type, irFunction.returnType, stack)
}
private suspend fun IrFunction.trySubstituteFunctionBody(): ExecutionResult? {
private fun IrFunction.trySubstituteFunctionBody(): ExecutionResult? {
if (!this.symbol.isPublicApi) return null
val body = bodyMap[this.symbol.signature]
@@ -337,12 +332,12 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
}
// TODO fix in FIR2IR; const val getter must have body with IrGetField node
private suspend fun IrFunction.tryCalculateLazyConst(): ExecutionResult? {
private fun IrFunction.tryCalculateLazyConst(): ExecutionResult? {
if (this !is IrSimpleFunction) return null
return this.correspondingPropertySymbol?.owner?.backingField?.initializer?.interpret()
}
private suspend fun interpretInstanceInitializerCall(call: IrInstanceInitializerCall): ExecutionResult {
private fun interpretInstanceInitializerCall(call: IrInstanceInitializerCall): ExecutionResult {
val irClass = call.classSymbol.owner
// properties processing
@@ -364,7 +359,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
return Next
}
private suspend fun interpretConstructor(constructorCall: IrFunctionAccessExpression): ExecutionResult {
private fun interpretConstructor(constructorCall: IrFunctionAccessExpression): ExecutionResult {
val owner = constructorCall.symbol.owner
val valueArguments = mutableListOf<Variable>()
@@ -403,15 +398,15 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
}
}
private suspend fun interpretConstructorCall(constructorCall: IrConstructorCall): ExecutionResult {
private fun interpretConstructorCall(constructorCall: IrConstructorCall): ExecutionResult {
return interpretConstructor(constructorCall)
}
private suspend fun interpretEnumConstructorCall(enumConstructorCall: IrEnumConstructorCall): ExecutionResult {
private fun interpretEnumConstructorCall(enumConstructorCall: IrEnumConstructorCall): ExecutionResult {
return interpretConstructor(enumConstructorCall)
}
private suspend fun interpretDelegatedConstructorCall(delegatingConstructorCall: IrDelegatingConstructorCall): ExecutionResult {
private fun interpretDelegatedConstructorCall(delegatingConstructorCall: IrDelegatingConstructorCall): ExecutionResult {
if (delegatingConstructorCall.symbol.owner.parent == irBuiltIns.anyClass.owner) {
val anyAsStateObject = Common(irBuiltIns.anyClass.owner)
stack.pushReturnValue(anyAsStateObject)
@@ -421,7 +416,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
return interpretConstructor(delegatingConstructorCall)
}
private suspend fun interpretConst(expression: IrConst<*>): ExecutionResult {
private fun interpretConst(expression: IrConst<*>): ExecutionResult {
fun getSignedType(unsignedType: IrType): IrType {
return when {
unsignedType.isUByte() -> irBuiltIns.byteType
@@ -445,7 +440,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
}
}
private suspend fun interpretStatements(statements: List<IrStatement>): ExecutionResult {
private fun interpretStatements(statements: List<IrStatement>): ExecutionResult {
var executionResult: ExecutionResult = Next
for (statement in statements) {
when (statement) {
@@ -457,20 +452,20 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
return executionResult
}
private suspend fun interpretBlock(block: IrBlock): ExecutionResult {
private fun interpretBlock(block: IrBlock): ExecutionResult {
return stack.newFrame(asSubFrame = true) { interpretStatements(block.statements) }
}
private suspend fun interpretBody(body: IrBody): ExecutionResult {
private fun interpretBody(body: IrBody): ExecutionResult {
return stack.newFrame(asSubFrame = true) { interpretStatements(body.statements) }
}
private suspend fun interpretReturn(expression: IrReturn): ExecutionResult {
private fun interpretReturn(expression: IrReturn): ExecutionResult {
expression.value.interpret().check { return it }
return Return.addOwnerInfo(expression.returnTargetSymbol.owner)
}
private suspend fun interpretWhile(expression: IrWhileLoop): ExecutionResult {
private fun interpretWhile(expression: IrWhileLoop): ExecutionResult {
while (true) {
expression.condition.interpret().check { return it }
if (stack.popReturnValue().asBooleanOrNull() != true) break
@@ -479,7 +474,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
return Next
}
private suspend fun interpretDoWhile(expression: IrDoWhileLoop): ExecutionResult {
private fun interpretDoWhile(expression: IrDoWhileLoop): ExecutionResult {
do {
// pool from body must be seen to condition expression, so must create temp frame here
stack.newFrame(asSubFrame = true) {
@@ -493,7 +488,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
return Next
}
private suspend fun interpretWhen(expression: IrWhen): ExecutionResult {
private fun interpretWhen(expression: IrWhen): ExecutionResult {
var executionResult: ExecutionResult = Next
for (branch in expression.branches) {
executionResult = branch.interpret().check { return it }
@@ -501,7 +496,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
return executionResult
}
private suspend fun interpretBranch(expression: IrBranch): ExecutionResult {
private fun interpretBranch(expression: IrBranch): ExecutionResult {
val executionResult = expression.condition.interpret().check { return it }
if (stack.popReturnValue().asBooleanOrNull() == true) {
expression.result.interpret().check { return it }
@@ -518,7 +513,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
return Continue.addOwnerInfo(continueStatement.loop)
}
private suspend fun interpretSetField(expression: IrSetField): ExecutionResult {
private fun interpretSetField(expression: IrSetField): ExecutionResult {
expression.value.interpret().check { return it }
// receiver is null only for top level var, but it cannot be used in constexpr; corresponding check is on frontend
@@ -528,7 +523,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
return Next
}
private suspend fun interpretGetField(expression: IrGetField): ExecutionResult {
private fun interpretGetField(expression: IrGetField): ExecutionResult {
val receiver = (expression.receiver as? IrDeclarationReference)?.symbol
val field = expression.symbol.owner
// for java static variables
@@ -551,13 +546,13 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
return Next
}
private suspend fun interpretVariable(expression: IrVariable): ExecutionResult {
private fun interpretVariable(expression: IrVariable): ExecutionResult {
expression.initializer?.interpret()?.check { return it } ?: return Next
stack.addVar(Variable(expression.symbol, stack.popReturnValue()))
return Next
}
private suspend fun interpretSetVariable(expression: IrSetVariable): ExecutionResult {
private fun interpretSetVariable(expression: IrSetVariable): ExecutionResult {
expression.value.interpret().check { return it }
if (stack.contains(expression.symbol)) {
@@ -584,7 +579,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
return Next
}
private suspend fun interpretGetEnumValue(expression: IrGetEnumValue): ExecutionResult {
private fun interpretGetEnumValue(expression: IrGetEnumValue): ExecutionResult {
mapOfEnums[expression.symbol]?.let { return Next.apply { stack.pushReturnValue(it) } }
val enumEntry = expression.symbol.owner
@@ -607,7 +602,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
return Next
}
private suspend fun interpretEnumEntry(enumEntry: IrEnumEntry): ExecutionResult {
private fun interpretEnumEntry(enumEntry: IrEnumEntry): ExecutionResult {
val enumClass = enumEntry.symbol.owner.parentAsClass
val enumEntries = enumClass.declarations.filterIsInstance<IrEnumEntry>()
@@ -624,7 +619,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
return executionResult ?: throw InterpreterException("Initializer at enum entry ${enumEntry.fqNameWhenAvailable} is null")
}
private suspend fun interpretTypeOperatorCall(expression: IrTypeOperatorCall): ExecutionResult {
private fun interpretTypeOperatorCall(expression: IrTypeOperatorCall): ExecutionResult {
val executionResult = expression.argument.interpret().check { return it }
val typeClassifier = expression.typeOperand.classifierOrFail
val isReified = (typeClassifier.owner as? IrTypeParameter)?.isReified == true
@@ -662,7 +657,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
return executionResult
}
private suspend fun interpretVararg(expression: IrVararg): ExecutionResult {
private fun interpretVararg(expression: IrVararg): ExecutionResult {
val args = expression.elements.flatMap {
it.interpret().check { executionResult -> return executionResult }
return@flatMap when (val result = stack.popReturnValue()) {
@@ -701,11 +696,11 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
return Next
}
private suspend fun interpretSpreadElement(spreadElement: IrSpreadElement): ExecutionResult {
private fun interpretSpreadElement(spreadElement: IrSpreadElement): ExecutionResult {
return spreadElement.expression.interpret().check { return it }
}
private suspend fun interpretTry(expression: IrTry): ExecutionResult {
private fun interpretTry(expression: IrTry): ExecutionResult {
try {
expression.tryResult.interpret().check(ReturnLabel.EXCEPTION) { return it } // if not exception -> return
val exception = stack.peekReturnValue() as ExceptionState
@@ -722,14 +717,14 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
return Next
}
private suspend fun interpretCatch(expression: IrCatch): ExecutionResult {
private fun interpretCatch(expression: IrCatch): ExecutionResult {
val catchParameter = Variable(expression.catchParameter.symbol, stack.popReturnValue())
return stack.newFrame(asSubFrame = true, initPool = listOf(catchParameter)) {
expression.result.interpret()
}
}
private suspend fun interpretThrow(expression: IrThrow): ExecutionResult {
private fun interpretThrow(expression: IrThrow): ExecutionResult {
expression.value.interpret().check { return it }
when (val exception = stack.popReturnValue()) {
is Common -> stack.pushReturnValue(ExceptionState(exception, stack.getStackTrace()))
@@ -740,7 +735,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
return Exception
}
private suspend fun interpretStringConcatenation(expression: IrStringConcatenation): ExecutionResult {
private fun interpretStringConcatenation(expression: IrStringConcatenation): ExecutionResult {
val result = StringBuilder()
expression.arguments.forEach {
it.interpret().check { executionResult -> return executionResult }
@@ -752,7 +747,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
return Next
}
private suspend fun interpretToString(state: State): ExecutionResult {
private fun interpretToString(state: State): ExecutionResult {
val result = when (state) {
is Primitive<*> -> state.value.toString()
is Wrapper -> state.value.toString()
@@ -781,7 +776,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
return Next
}
private suspend fun interpretComposite(expression: IrComposite): ExecutionResult {
private fun interpretComposite(expression: IrComposite): ExecutionResult {
return when (expression.origin) {
IrStatementOrigin.DESTRUCTURING_DECLARATION -> interpretStatements(expression.statements)
null -> interpretStatements(expression.statements) // is null for body of do while loop
@@ -27,7 +27,7 @@ enum class ReturnLabel {
}
open class ExecutionResult(val returnLabel: ReturnLabel, private val owner: IrElement? = null) {
suspend fun getNextLabel(irElement: IrElement, interpret: suspend IrElement.() -> ExecutionResult): ExecutionResult {
fun getNextLabel(irElement: IrElement, interpret: IrElement.() -> ExecutionResult): ExecutionResult {
return when (returnLabel) {
ReturnLabel.RETURN -> when (irElement) {
is IrCall, is IrReturnableBlock, is IrFunctionImpl, is IrLazyFunction -> if (owner == irElement) Next else this
@@ -12,7 +12,7 @@ import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrFunction
internal class IntrinsicEvaluator {
suspend fun evaluate(irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult): ExecutionResult {
fun evaluate(irFunction: IrFunction, stack: Stack, interpret: IrElement.() -> ExecutionResult): ExecutionResult {
return when {
EmptyArray.equalTo(irFunction) -> EmptyArray.evaluate(irFunction, stack, interpret)
ArrayOf.equalTo(irFunction) -> ArrayOf.evaluate(irFunction, stack, interpret)
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.ir.interpreter.intrinsics
import kotlinx.coroutines.runBlocking
import org.jetbrains.kotlin.ir.interpreter.*
import org.jetbrains.kotlin.ir.interpreter.stack.Stack
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
@@ -19,7 +18,7 @@ import org.jetbrains.kotlin.ir.util.*
internal sealed class IntrinsicBase {
abstract fun equalTo(irFunction: IrFunction): Boolean
abstract suspend fun evaluate(irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult): ExecutionResult
abstract fun evaluate(irFunction: IrFunction, stack: Stack, interpret: IrElement.() -> ExecutionResult): ExecutionResult
}
internal object EmptyArray : IntrinsicBase() {
@@ -28,9 +27,7 @@ internal object EmptyArray : IntrinsicBase() {
return fqName in setOf("kotlin.emptyArray", "kotlin.ArrayIntrinsicsKt.emptyArray")
}
override suspend fun evaluate(
irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult
): ExecutionResult {
override fun evaluate(irFunction: IrFunction, stack: Stack, interpret: IrElement.() -> ExecutionResult): ExecutionResult {
val typeArguments = irFunction.typeParameters.map { stack.getVariable(it.symbol) }
stack.pushReturnValue(emptyArray<Any?>().toState(irFunction.returnType).apply { addTypeArguments(typeArguments) })
return Next
@@ -43,9 +40,7 @@ internal object ArrayOf : IntrinsicBase() {
return fqName == "kotlin.arrayOf"
}
override suspend fun evaluate(
irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult
): ExecutionResult {
override fun evaluate(irFunction: IrFunction, stack: Stack, interpret: IrElement.() -> ExecutionResult): ExecutionResult {
val array = irFunction.getArgsForMethodInvocation(stack.getAll()).toTypedArray()
val typeArguments = irFunction.typeParameters.map { stack.getVariable(it.symbol) }
stack.pushReturnValue(array.toState(irFunction.returnType).apply { addTypeArguments(typeArguments) })
@@ -59,9 +54,7 @@ internal object ArrayOfNulls : IntrinsicBase() {
return fqName == "kotlin.arrayOfNulls"
}
override suspend fun evaluate(
irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult
): ExecutionResult {
override fun evaluate(irFunction: IrFunction, stack: Stack, interpret: IrElement.() -> ExecutionResult): ExecutionResult {
val size = stack.getVariable(irFunction.valueParameters.first().symbol).state.asInt()
val array = arrayOfNulls<Any?>(size)
val typeArguments = irFunction.typeParameters.map { stack.getVariable(it.symbol) }
@@ -76,9 +69,7 @@ internal object EnumValues : IntrinsicBase() {
return (fqName == "kotlin.enumValues" || fqName.endsWith(".values")) && irFunction.valueParameters.isEmpty()
}
override suspend fun evaluate(
irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult
): ExecutionResult {
override fun evaluate(irFunction: IrFunction, stack: Stack, interpret: IrElement.() -> ExecutionResult): ExecutionResult {
val enumClass = when (irFunction.fqNameWhenAvailable.toString()) {
"kotlin.enumValues" -> stack.getVariable(irFunction.typeParameters.first().symbol).state.irClass
else -> irFunction.parent as IrClass
@@ -97,9 +88,7 @@ internal object EnumValueOf : IntrinsicBase() {
return (fqName == "kotlin.enumValueOf" || fqName.endsWith(".valueOf")) && irFunction.valueParameters.size == 1
}
override suspend fun evaluate(
irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult
): ExecutionResult {
override fun evaluate(irFunction: IrFunction, stack: Stack, interpret: IrElement.() -> ExecutionResult): ExecutionResult {
val enumClass = when (irFunction.fqNameWhenAvailable.toString()) {
"kotlin.enumValueOf" -> stack.getVariable(irFunction.typeParameters.first().symbol).state.irClass
else -> irFunction.parent as IrClass
@@ -119,9 +108,7 @@ internal object RegexReplace : IntrinsicBase() {
return fqName == "kotlin.text.Regex.replace" && irFunction.valueParameters.size == 2
}
override suspend fun evaluate(
irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult
): ExecutionResult {
override fun evaluate(irFunction: IrFunction, stack: Stack, interpret: IrElement.() -> ExecutionResult): ExecutionResult {
val states = stack.getAll().map { it.state }
val regex = states.filterIsInstance<Wrapper>().single().value as Regex
val input = states.filterIsInstance<Primitive<*>>().single().asString()
@@ -129,7 +116,7 @@ internal object RegexReplace : IntrinsicBase() {
val matchResultParameter = transform.valueParameters.single()
val result = regex.replace(input) {
val itAsState = Variable(matchResultParameter.symbol, Wrapper(it, matchResultParameter.type.classOrNull!!.owner))
runBlocking { stack.newFrame(initPool = listOf(itAsState)) { transform.interpret() } }//.check { return it }
stack.newFrame(initPool = listOf(itAsState)) { transform.interpret() }//.check { return it }
stack.popReturnValue().asString()
}
stack.pushReturnValue(result.toState(irFunction.returnType))
@@ -143,9 +130,7 @@ internal object EnumHashCode : IntrinsicBase() {
return fqName == "kotlin.Enum.hashCode"
}
override suspend fun evaluate(
irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult
): ExecutionResult {
override fun evaluate(irFunction: IrFunction, stack: Stack, interpret: IrElement.() -> ExecutionResult): ExecutionResult {
val hashCode = stack.getAll().single().state.hashCode()
stack.pushReturnValue(hashCode.toState(irFunction.returnType))
return Next
@@ -158,9 +143,7 @@ internal object JsPrimitives : IntrinsicBase() {
return fqName == "kotlin.Long.<init>" || fqName == "kotlin.Char.<init>"
}
override suspend fun evaluate(
irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult
): ExecutionResult {
override fun evaluate(irFunction: IrFunction, stack: Stack, interpret: IrElement.() -> ExecutionResult): ExecutionResult {
when (irFunction.fqNameWhenAvailable.toString()) {
"kotlin.Long.<init>" -> {
val low = stack.getVariable(irFunction.valueParameters[0].symbol).state.asInt()
@@ -182,9 +165,7 @@ internal object ArrayConstructor : IntrinsicBase() {
return fqName.matches("kotlin\\.(Byte|Char|Short|Int|Long|Float|Double|Boolean|)Array\\.<init>".toRegex())
}
override suspend fun evaluate(
irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult
): ExecutionResult {
override fun evaluate(irFunction: IrFunction, stack: Stack, interpret: IrElement.() -> ExecutionResult): ExecutionResult {
val sizeDescriptor = irFunction.valueParameters[0].symbol
val size = stack.getVariable(sizeDescriptor).state.asInt()
val arrayValue = MutableList<Any>(size) { 0 }
@@ -19,9 +19,7 @@ import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
internal interface Stack {
suspend fun newFrame(
asSubFrame: Boolean = false, initPool: List<Variable> = listOf(), block: suspend () -> ExecutionResult
): ExecutionResult
fun newFrame(asSubFrame: Boolean = false, initPool: List<Variable> = listOf(), block: () -> ExecutionResult): ExecutionResult
fun setCurrentFrameName(irFunction: IrFunction)
fun getStackTrace(): List<String>
@@ -43,7 +41,7 @@ internal class StackImpl : Stack {
private val frameList = mutableListOf(FrameContainer()) // first frame is default, it is easier to work when last() is not null
private fun getCurrentFrame() = frameList.last()
override suspend fun newFrame(asSubFrame: Boolean, initPool: List<Variable>, block: suspend () -> ExecutionResult): ExecutionResult {
override fun newFrame(asSubFrame: Boolean, initPool: List<Variable>, block: () -> ExecutionResult): ExecutionResult {
val typeArgumentsPool = initPool.filter { it.symbol is IrTypeParameterSymbol }
val valueArguments = initPool.filter { it.symbol !is IrTypeParameterSymbol }
val newFrame = InterpreterFrame(valueArguments.toMutableList(), typeArgumentsPool)