Implement regular expression interpretation
This commit is contained in:
+25
-6
@@ -5,9 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.common.interpreter
|
package org.jetbrains.kotlin.backend.common.interpreter
|
||||||
|
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import kotlinx.coroutines.yield
|
|
||||||
import org.jetbrains.kotlin.backend.common.interpreter.builtins.*
|
import org.jetbrains.kotlin.backend.common.interpreter.builtins.*
|
||||||
import org.jetbrains.kotlin.backend.common.interpreter.stack.*
|
import org.jetbrains.kotlin.backend.common.interpreter.stack.*
|
||||||
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
||||||
@@ -245,6 +243,20 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
enumEntry.interpret(data).also { if (it != Code.NEXT) return it }
|
enumEntry.interpret(data).also { if (it != Code.NEXT) return it }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
"replace" -> {
|
||||||
|
val states = data.getAll().map { it.state }
|
||||||
|
val regex = states.filterIsInstance<Wrapper>().single().value as Regex
|
||||||
|
val input = states.filterIsInstance<Primitive<*>>().single().value.toString()
|
||||||
|
val transform = states.filterIsInstance<Lambda>().single().irFunction
|
||||||
|
val matchResultParameter = transform.valueParameters.single()
|
||||||
|
val result = regex.replace(input) {
|
||||||
|
val itAsState = Variable(matchResultParameter.descriptor, Wrapper(it, matchResultParameter.type.classOrNull!!.owner))
|
||||||
|
val newFrame = InterpreterFrame(mutableListOf(itAsState))
|
||||||
|
runBlocking { transform.interpret(newFrame) }
|
||||||
|
(newFrame.popReturnValue() as Primitive<*>).value.toString()
|
||||||
|
}
|
||||||
|
data.pushReturnValue(result.toState(irBuiltIns.stringType))
|
||||||
|
}
|
||||||
else -> throw AssertionError("Unsupported intrinsic ${irFunction.name}")
|
else -> throw AssertionError("Unsupported intrinsic ${irFunction.name}")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,8 +365,9 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun interpretValueParameters(parametersContainer: IrMemberAccessExpression, data: Frame): Code {
|
private suspend fun interpretValueParameters(parametersContainer: IrMemberAccessExpression, data: Frame): Code {
|
||||||
|
val defaultValues = (parametersContainer.symbol.owner as IrFunction).valueParameters.map { it.defaultValue }
|
||||||
for (i in (parametersContainer.valueArgumentsCount - 1) downTo 0) {
|
for (i in (parametersContainer.valueArgumentsCount - 1) downTo 0) {
|
||||||
val code = parametersContainer.getValueArgument(i)?.interpret(data) ?: Code.NEXT
|
val code = parametersContainer.getValueArgument(i)?.interpret(data) ?: defaultValues[i]!!.expression.interpret(data)
|
||||||
if (code != Code.NEXT) return code
|
if (code != Code.NEXT) return code
|
||||||
}
|
}
|
||||||
return Code.NEXT
|
return Code.NEXT
|
||||||
@@ -395,8 +408,9 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val isWrapper = dispatchReceiver is Wrapper && rawExtensionReceiver == null
|
val isWrapper = dispatchReceiver is Wrapper && rawExtensionReceiver == null
|
||||||
|
val isInterfaceDefaultMethod = irFunction.body != null && (irFunction.parent as? IrClass)?.isInterface == true
|
||||||
val code = when {
|
val code = when {
|
||||||
isWrapper -> (dispatchReceiver as Wrapper).getMethod(irFunction).invokeMethod(irFunction, newFrame)
|
isWrapper && !isInterfaceDefaultMethod -> (dispatchReceiver as Wrapper).getMethod(irFunction).invokeMethod(irFunction, newFrame)
|
||||||
irFunction.hasAnnotation(evaluateIntrinsicAnnotation) -> Wrapper.getStaticMethod(irFunction).invokeMethod(irFunction, newFrame)
|
irFunction.hasAnnotation(evaluateIntrinsicAnnotation) -> Wrapper.getStaticMethod(irFunction).invokeMethod(irFunction, newFrame)
|
||||||
irFunction.isAbstract() -> calculateAbstract(irFunction, newFrame) //abstract check must be before fake overridden check
|
irFunction.isAbstract() -> calculateAbstract(irFunction, newFrame) //abstract check must be before fake overridden check
|
||||||
irFunction.isFakeOverridden() -> calculateOverridden(irFunction as IrFunctionImpl, newFrame)
|
irFunction.isFakeOverridden() -> calculateOverridden(irFunction as IrFunctionImpl, newFrame)
|
||||||
@@ -615,7 +629,12 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun interpretGetObjectValue(expression: IrGetObjectValue, data: Frame): Code {
|
private suspend fun interpretGetObjectValue(expression: IrGetObjectValue, data: Frame): Code {
|
||||||
val objectState = Common(expression.symbol.owner, mutableListOf()).apply { this.instance = this }
|
val owner = expression.symbol.owner
|
||||||
|
if (owner.hasAnnotation(evaluateIntrinsicAnnotation)) {
|
||||||
|
data.pushReturnValue(Wrapper.getCompanionObject(owner))
|
||||||
|
return Code.NEXT
|
||||||
|
}
|
||||||
|
val objectState = Common(owner, mutableListOf()).apply { this.instance = this }
|
||||||
data.pushReturnValue(objectState)
|
data.pushReturnValue(objectState)
|
||||||
return Code.NEXT
|
return Code.NEXT
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-5
@@ -153,16 +153,21 @@ class Wrapper(val value: Any, override val irClass: IrClass) : Complex(irClass,
|
|||||||
private val typeFqName = irClass.fqNameForIrSerialization.toUnsafe()
|
private val typeFqName = irClass.fqNameForIrSerialization.toUnsafe()
|
||||||
private val receiverClass = irClass.defaultType.getClass(true)
|
private val receiverClass = irClass.defaultType.getClass(true)
|
||||||
|
|
||||||
|
init {
|
||||||
|
instance = this
|
||||||
|
}
|
||||||
|
|
||||||
fun getMethod(irFunction: IrFunction): MethodHandle? {
|
fun getMethod(irFunction: IrFunction): MethodHandle? {
|
||||||
// if function is actually a getter, then use property name as method name
|
// if function is actually a getter, then use "get${property.name.capitalize()}" as method name
|
||||||
val property = (irFunction as? IrFunctionImpl)?.correspondingPropertySymbol?.owner
|
val propertyName = (irFunction as? IrFunctionImpl)?.correspondingPropertySymbol?.owner?.name?.asString()
|
||||||
|
val propertyExplicitCall = propertyName?.takeIf { receiverClass.methods.map { it.name }.contains(it) }
|
||||||
|
val propertyGetCall = "get${propertyName?.capitalize()}".takeIf { receiverClass.methods.map { it.name }.contains(it) }
|
||||||
|
|
||||||
// intrinsicName is used to get correct java method
|
// intrinsicName is used to get correct java method
|
||||||
// for example: - method 'get' in kotlin StringBuilder is actually 'charAt' in java StringBuilder
|
// for example: - method 'get' in kotlin StringBuilder is actually 'charAt' in java StringBuilder
|
||||||
// - use getter for private fields such as detailMessage in java.lang.Throwable
|
val intrinsicName = irFunction.getEvaluateIntrinsicValue()
|
||||||
val intrinsicName = property?.getEvaluateIntrinsicValue() ?: irFunction.getEvaluateIntrinsicValue()
|
|
||||||
if (intrinsicName?.isEmpty() == true) return null
|
if (intrinsicName?.isEmpty() == true) return null
|
||||||
val methodName = intrinsicName ?: (property ?: irFunction).name.toString()
|
val methodName = intrinsicName ?: propertyExplicitCall ?: propertyGetCall ?: irFunction.name.toString()
|
||||||
|
|
||||||
val methodType = irFunction.getMethodType()
|
val methodType = irFunction.getMethodType()
|
||||||
return MethodHandles.lookup().findVirtual(receiverClass, methodName, methodType)
|
return MethodHandles.lookup().findVirtual(receiverClass, methodName, methodType)
|
||||||
@@ -173,6 +178,14 @@ class Wrapper(val value: Any, override val irClass: IrClass) : Complex(irClass,
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
private val companionObjectValue = mapOf<String, Any>("kotlin.text.Regex\$Companion" to Regex.Companion)
|
||||||
|
|
||||||
|
fun getCompanionObject(irClass: IrClass): Wrapper {
|
||||||
|
val objectName = irClass.getEvaluateIntrinsicValue()!!
|
||||||
|
val objectValue = companionObjectValue[objectName] ?: throw AssertionError("Companion object $objectName cannot be interpreted")
|
||||||
|
return Wrapper(objectValue, irClass)
|
||||||
|
}
|
||||||
|
|
||||||
fun getConstructorMethod(irConstructor: IrFunction): MethodHandle {
|
fun getConstructorMethod(irConstructor: IrFunction): MethodHandle {
|
||||||
val methodType = irConstructor.getMethodType()
|
val methodType = irConstructor.getMethodType()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user