Implement regular expression interpretation
This commit is contained in:
+25
-6
@@ -5,9 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.common.interpreter
|
||||
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.coroutines.yield
|
||||
import kotlinx.coroutines.*
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.builtins.*
|
||||
import org.jetbrains.kotlin.backend.common.interpreter.stack.*
|
||||
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
||||
@@ -245,6 +243,20 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
||||
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}")
|
||||
}
|
||||
|
||||
@@ -353,8 +365,9 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
||||
}
|
||||
|
||||
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) {
|
||||
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
|
||||
}
|
||||
return Code.NEXT
|
||||
@@ -395,8 +408,9 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
||||
}
|
||||
|
||||
val isWrapper = dispatchReceiver is Wrapper && rawExtensionReceiver == null
|
||||
val isInterfaceDefaultMethod = irFunction.body != null && (irFunction.parent as? IrClass)?.isInterface == true
|
||||
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.isAbstract() -> calculateAbstract(irFunction, newFrame) //abstract check must be before fake overridden check
|
||||
irFunction.isFakeOverridden() -> calculateOverridden(irFunction as IrFunctionImpl, newFrame)
|
||||
@@ -615,7 +629,12 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
||||
}
|
||||
|
||||
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)
|
||||
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 receiverClass = irClass.defaultType.getClass(true)
|
||||
|
||||
init {
|
||||
instance = this
|
||||
}
|
||||
|
||||
fun getMethod(irFunction: IrFunction): MethodHandle? {
|
||||
// if function is actually a getter, then use property name as method name
|
||||
val property = (irFunction as? IrFunctionImpl)?.correspondingPropertySymbol?.owner
|
||||
// if function is actually a getter, then use "get${property.name.capitalize()}" as method name
|
||||
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
|
||||
// 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 = property?.getEvaluateIntrinsicValue() ?: irFunction.getEvaluateIntrinsicValue()
|
||||
val intrinsicName = irFunction.getEvaluateIntrinsicValue()
|
||||
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()
|
||||
return MethodHandles.lookup().findVirtual(receiverClass, methodName, methodType)
|
||||
@@ -173,6 +178,14 @@ class Wrapper(val value: Any, override val irClass: IrClass) : Complex(irClass,
|
||||
}
|
||||
|
||||
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 {
|
||||
val methodType = irConstructor.getMethodType()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user