[IR] Add special preprocessors for ir interpreter
These preprocessors allow us to modify IR at first and only after that try to evaluate. With this we can drop `KCallableNamePropertyLowering`.
This commit is contained in:
-85
@@ -1,85 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.backend.common.lower
|
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.BackendContext
|
|
||||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
|
||||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
|
||||||
import org.jetbrains.kotlin.ir.util.isSubclassOf
|
|
||||||
import org.jetbrains.kotlin.ir.util.render
|
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
|
||||||
|
|
||||||
val kCallableNamePropertyPhase = makeIrFilePhase(
|
|
||||||
::KCallableNamePropertyLowering,
|
|
||||||
name = "KCallableNameProperty",
|
|
||||||
description = "Replace name references for callables with constants"
|
|
||||||
)
|
|
||||||
|
|
||||||
private class KCallableNamePropertyLowering(val context: BackendContext) : FileLoweringPass {
|
|
||||||
override fun lower(irFile: IrFile) {
|
|
||||||
irFile.transformChildrenVoid(KCallableNamePropertyTransformer(this))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class KCallableNamePropertyTransformer(val lower: KCallableNamePropertyLowering) : IrElementTransformerVoid() {
|
|
||||||
private fun nameForCallableMember(reference: IrCallableReference<*>): Name {
|
|
||||||
return when (reference) {
|
|
||||||
is IrFunctionReference -> reference.symbol.owner.name
|
|
||||||
is IrPropertyReference -> reference.symbol.owner.name
|
|
||||||
is IrLocalDelegatedPropertyReference -> reference.symbol.owner.name
|
|
||||||
else -> error("Unexpected callable reference type ${reference.render()}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitCall(expression: IrCall): IrExpression {
|
|
||||||
val callableReference = expression.dispatchReceiver as? IrCallableReference<*>
|
|
||||||
?: return super.visitCall(expression)
|
|
||||||
|
|
||||||
val directMember = expression.symbol.owner.let {
|
|
||||||
(it as? IrSimpleFunction)?.correspondingPropertySymbol?.owner ?: it
|
|
||||||
}
|
|
||||||
|
|
||||||
val irClass = directMember.parent as? IrClass
|
|
||||||
?: return super.visitCall(expression)
|
|
||||||
if (!irClass.isSubclassOf(lower.context.irBuiltIns.kCallableClass.owner)) {
|
|
||||||
return super.visitCall(expression)
|
|
||||||
}
|
|
||||||
|
|
||||||
val name = when (directMember) {
|
|
||||||
is IrSimpleFunction -> directMember.name
|
|
||||||
is IrProperty -> directMember.name
|
|
||||||
else -> throw AssertionError("Should be IrSimpleFunction or IrProperty, got $directMember")
|
|
||||||
}
|
|
||||||
if (name.asString() != "name") return expression
|
|
||||||
|
|
||||||
val receiver = callableReference.dispatchReceiver ?: callableReference.extensionReceiver
|
|
||||||
|
|
||||||
return IrCompositeImpl(expression.startOffset, expression.endOffset, lower.context.irBuiltIns.stringType).apply {
|
|
||||||
receiver?.let {
|
|
||||||
//put receiver for bound callable reference
|
|
||||||
statements.add(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
statements.add(
|
|
||||||
IrConstImpl.string(
|
|
||||||
expression.startOffset,
|
|
||||||
expression.endOffset,
|
|
||||||
lower.context.irBuiltIns.stringType,
|
|
||||||
nameForCallableMember(callableReference).asString()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -9,7 +9,8 @@ import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
|||||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||||
import org.jetbrains.kotlin.backend.common.checkDeclarationParents
|
import org.jetbrains.kotlin.backend.common.checkDeclarationParents
|
||||||
import org.jetbrains.kotlin.backend.common.lower.*
|
import org.jetbrains.kotlin.backend.common.lower.*
|
||||||
import org.jetbrains.kotlin.backend.common.lower.inline.*
|
import org.jetbrains.kotlin.backend.common.lower.inline.FunctionInlining
|
||||||
|
import org.jetbrains.kotlin.backend.common.lower.inline.InlineFunctionResolver
|
||||||
import org.jetbrains.kotlin.backend.common.lower.loops.forLoopsPhase
|
import org.jetbrains.kotlin.backend.common.lower.loops.forLoopsPhase
|
||||||
import org.jetbrains.kotlin.backend.common.phaser.*
|
import org.jetbrains.kotlin.backend.common.phaser.*
|
||||||
import org.jetbrains.kotlin.backend.jvm.ir.constantValue
|
import org.jetbrains.kotlin.backend.jvm.ir.constantValue
|
||||||
@@ -341,7 +342,6 @@ private val jvmFilePhases = listOf(
|
|||||||
jvmOverloadsAnnotationPhase,
|
jvmOverloadsAnnotationPhase,
|
||||||
mainMethodGenerationPhase,
|
mainMethodGenerationPhase,
|
||||||
|
|
||||||
kCallableNamePropertyPhase,
|
|
||||||
annotationPhase,
|
annotationPhase,
|
||||||
annotationImplementationPhase,
|
annotationImplementationPhase,
|
||||||
polymorphicSignaturePhase,
|
polymorphicSignaturePhase,
|
||||||
|
|||||||
-1
@@ -125,7 +125,6 @@ private fun unfoldValueParameters(expression: IrFunctionAccessExpression, enviro
|
|||||||
callStack.pushState(enumEntry.toState(environment.irBuiltIns))
|
callStack.pushState(enumEntry.toState(environment.irBuiltIns))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// TODO do the same thing but for "KCallable.name" with "this" as receiver
|
|
||||||
|
|
||||||
val hasDefaults = (0 until expression.valueArgumentsCount).any { expression.getValueArgument(it) == null }
|
val hasDefaults = (0 until expression.valueArgumentsCount).any { expression.getValueArgument(it) == null }
|
||||||
if (hasDefaults) {
|
if (hasDefaults) {
|
||||||
|
|||||||
+2
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.ir.interpreter.checker
|
package org.jetbrains.kotlin.ir.interpreter.checker
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.ir.IrBuiltIns
|
||||||
import org.jetbrains.kotlin.ir.interpreter.IrInterpreterConfiguration
|
import org.jetbrains.kotlin.ir.interpreter.IrInterpreterConfiguration
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||||
|
|
||||||
@@ -13,5 +14,6 @@ interface IrInterpreterChecker : IrElementVisitor<Boolean, IrInterpreterCheckerD
|
|||||||
}
|
}
|
||||||
|
|
||||||
class IrInterpreterCheckerData(
|
class IrInterpreterCheckerData(
|
||||||
|
val irBuiltIns: IrBuiltIns,
|
||||||
val interpreterConfiguration: IrInterpreterConfiguration
|
val interpreterConfiguration: IrInterpreterConfiguration
|
||||||
)
|
)
|
||||||
+40
-15
@@ -5,33 +5,58 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.ir.interpreter.checker
|
package org.jetbrains.kotlin.ir.interpreter.checker
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.ir.IrBuiltIns
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrCallableReference
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrGetEnumValue
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrStringConcatenation
|
||||||
|
import org.jetbrains.kotlin.ir.util.isSubclassOf
|
||||||
|
|
||||||
class IrInterpreterNameChecker(
|
class IrInterpreterNameChecker(
|
||||||
override val mode: EvaluationMode
|
override val mode: EvaluationMode,
|
||||||
) : IrInterpreterChecker {
|
) : IrInterpreterChecker {
|
||||||
private fun IrCall.isIntrinsicConstEvaluationNameProperty(): Boolean {
|
|
||||||
val owner = this.symbol.owner
|
|
||||||
if (owner.extensionReceiverParameter != null || owner.valueParameters.isNotEmpty()) return false
|
|
||||||
val property = (owner as? IrSimpleFunction)?.correspondingPropertySymbol?.owner ?: return false
|
|
||||||
return mode.canEvaluateFunction(owner) && property.name.asString() == "name"
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitElement(element: IrElement, data: IrInterpreterCheckerData) = false
|
override fun visitElement(element: IrElement, data: IrInterpreterCheckerData) = false
|
||||||
|
|
||||||
override fun visitCall(expression: IrCall, data: IrInterpreterCheckerData): Boolean {
|
override fun visitCall(expression: IrCall, data: IrInterpreterCheckerData): Boolean {
|
||||||
if (!expression.isIntrinsicConstEvaluationNameProperty()) return false
|
val owner = expression.symbol.owner
|
||||||
return when (val receiver = expression.dispatchReceiver) {
|
if (!mode.canEvaluateFunction(owner)) return false
|
||||||
is IrCallableReference<*> -> (receiver.dispatchReceiver == null || receiver.dispatchReceiver is IrGetObjectValue) && receiver.extensionReceiver == null
|
|
||||||
is IrGetEnumValue -> true
|
return expression.isKCallableNameCall(data.irBuiltIns) || expression.isEnumName()
|
||||||
else -> false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitStringConcatenation(expression: IrStringConcatenation, data: IrInterpreterCheckerData): Boolean {
|
override fun visitStringConcatenation(expression: IrStringConcatenation, data: IrInterpreterCheckerData): Boolean {
|
||||||
val possibleNameCall = expression.arguments.singleOrNull() as? IrCall ?: return false
|
val possibleNameCall = expression.arguments.singleOrNull() as? IrCall ?: return false
|
||||||
return possibleNameCall.accept(this, data)
|
return possibleNameCall.accept(this, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun IrCall.isKCallableNameCall(irBuiltIns: IrBuiltIns): Boolean {
|
||||||
|
if (this.dispatchReceiver !is IrCallableReference<*>) return false
|
||||||
|
|
||||||
|
val directMember = this.symbol.owner.let {
|
||||||
|
(it as? IrSimpleFunction)?.correspondingPropertySymbol?.owner ?: it
|
||||||
|
}
|
||||||
|
|
||||||
|
val irClass = directMember.parent as? IrClass ?: return false
|
||||||
|
if (!irClass.isSubclassOf(irBuiltIns.kCallableClass.owner)) return false
|
||||||
|
|
||||||
|
val name = when (directMember) {
|
||||||
|
is IrSimpleFunction -> directMember.name
|
||||||
|
is IrProperty -> directMember.name
|
||||||
|
else -> throw AssertionError("Should be IrSimpleFunction or IrProperty, got $directMember")
|
||||||
|
}
|
||||||
|
return name.asString() == "name"
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrCall.isEnumName(): Boolean {
|
||||||
|
val owner = this.symbol.owner
|
||||||
|
if (owner.extensionReceiverParameter != null || owner.valueParameters.isNotEmpty()) return false
|
||||||
|
val property = (owner as? IrSimpleFunction)?.correspondingPropertySymbol?.owner ?: return false
|
||||||
|
return this.dispatchReceiver is IrGetEnumValue && property.name.asString() == "name"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.ir.interpreter.preprocessor
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrCallableReference
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
|
||||||
|
import org.jetbrains.kotlin.ir.interpreter.checker.IrInterpreterNameChecker.Companion.isKCallableNameCall
|
||||||
|
|
||||||
|
// Note: this class still will not allow us to evaluate things like `A()::a.name + `A()::b.name`.
|
||||||
|
// This code will be optimized but not completely turned into "ab" result.
|
||||||
|
class IrInterpreterKCallableNamePreprocessor : IrInterpreterPreprocessor {
|
||||||
|
override fun visitCall(expression: IrCall, data: IrInterpreterPreprocessorData): IrElement {
|
||||||
|
if (!data.mode.canEvaluateFunction(expression.symbol.owner)) return super.visitCall(expression, data)
|
||||||
|
if (!expression.isKCallableNameCall(data.irBuiltIns)) return super.visitCall(expression, data)
|
||||||
|
|
||||||
|
val callableReference = expression.dispatchReceiver as? IrCallableReference<*> ?: return super.visitCall(expression, data)
|
||||||
|
|
||||||
|
// receiver is needed for bound callable reference
|
||||||
|
val receiver = callableReference.dispatchReceiver ?: callableReference.extensionReceiver ?: return expression
|
||||||
|
callableReference.dispatchReceiver = null
|
||||||
|
callableReference.extensionReceiver = null
|
||||||
|
|
||||||
|
return IrCompositeImpl(
|
||||||
|
expression.startOffset, expression.endOffset, expression.type, origin = null, statements = listOf(receiver, expression)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.ir.interpreter.preprocessor
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.ir.IrBuiltIns
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
|
import org.jetbrains.kotlin.ir.interpreter.checker.EvaluationMode
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||||
|
|
||||||
|
interface IrInterpreterPreprocessor: IrElementTransformer<IrInterpreterPreprocessorData> {
|
||||||
|
fun preprocess(file: IrFile, data: IrInterpreterPreprocessorData): IrFile {
|
||||||
|
return file.transform(this, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class IrInterpreterPreprocessorData(
|
||||||
|
val mode: EvaluationMode,
|
||||||
|
val irBuiltIns: IrBuiltIns
|
||||||
|
)
|
||||||
+19
-8
@@ -16,11 +16,18 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
|
|||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||||
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
|
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
|
||||||
import org.jetbrains.kotlin.ir.interpreter.IrInterpreterConfiguration
|
import org.jetbrains.kotlin.ir.interpreter.IrInterpreterConfiguration
|
||||||
import org.jetbrains.kotlin.ir.interpreter.checker.*
|
import org.jetbrains.kotlin.ir.interpreter.checker.EvaluationMode
|
||||||
|
import org.jetbrains.kotlin.ir.interpreter.checker.IrInterpreterCheckerData
|
||||||
|
import org.jetbrains.kotlin.ir.interpreter.checker.IrInterpreterCommonChecker
|
||||||
|
import org.jetbrains.kotlin.ir.interpreter.checker.IrInterpreterNameChecker
|
||||||
|
import org.jetbrains.kotlin.ir.interpreter.preprocessor.IrInterpreterKCallableNamePreprocessor
|
||||||
|
import org.jetbrains.kotlin.ir.interpreter.preprocessor.IrInterpreterPreprocessorData
|
||||||
import org.jetbrains.kotlin.ir.interpreter.toConstantValue
|
import org.jetbrains.kotlin.ir.interpreter.toConstantValue
|
||||||
import org.jetbrains.kotlin.ir.util.dump
|
import org.jetbrains.kotlin.ir.util.dump
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||||
|
|
||||||
|
private val preprocessors = setOf(IrInterpreterKCallableNamePreprocessor())
|
||||||
|
|
||||||
fun IrFile.transformConst(
|
fun IrFile.transformConst(
|
||||||
interpreter: IrInterpreter,
|
interpreter: IrInterpreter,
|
||||||
mode: EvaluationMode,
|
mode: EvaluationMode,
|
||||||
@@ -29,18 +36,22 @@ fun IrFile.transformConst(
|
|||||||
onError: (IrFile, IrElement, IrErrorExpression) -> Unit = { _, _, _ -> },
|
onError: (IrFile, IrElement, IrErrorExpression) -> Unit = { _, _, _ -> },
|
||||||
suppressExceptions: Boolean = false,
|
suppressExceptions: Boolean = false,
|
||||||
) {
|
) {
|
||||||
|
val preprocessedFile = preprocessors.fold(this) { acc, preprocessor ->
|
||||||
|
preprocessor.preprocess(acc, IrInterpreterPreprocessorData(mode, interpreter.irBuiltIns))
|
||||||
|
}
|
||||||
|
|
||||||
val irConstExpressionTransformer = IrConstExpressionTransformer(
|
val irConstExpressionTransformer = IrConstExpressionTransformer(
|
||||||
interpreter, this, mode, evaluatedConstTracker, onWarning, onError, suppressExceptions
|
interpreter, preprocessedFile, mode, evaluatedConstTracker, onWarning, onError, suppressExceptions
|
||||||
)
|
)
|
||||||
val irConstDeclarationAnnotationTransformer = IrConstDeclarationAnnotationTransformer(
|
val irConstDeclarationAnnotationTransformer = IrConstDeclarationAnnotationTransformer(
|
||||||
interpreter, this, mode, evaluatedConstTracker, onWarning, onError, suppressExceptions
|
interpreter, preprocessedFile, mode, evaluatedConstTracker, onWarning, onError, suppressExceptions
|
||||||
)
|
)
|
||||||
val irConstTypeAnnotationTransformer = IrConstTypeAnnotationTransformer(
|
val irConstTypeAnnotationTransformer = IrConstTypeAnnotationTransformer(
|
||||||
interpreter, this, mode, evaluatedConstTracker, onWarning, onError, suppressExceptions
|
interpreter, preprocessedFile, mode, evaluatedConstTracker, onWarning, onError, suppressExceptions
|
||||||
)
|
)
|
||||||
this.transform(irConstExpressionTransformer, null)
|
preprocessedFile.transform(irConstExpressionTransformer, null)
|
||||||
this.transform(irConstDeclarationAnnotationTransformer, null)
|
preprocessedFile.transform(irConstDeclarationAnnotationTransformer, null)
|
||||||
this.transform(irConstTypeAnnotationTransformer, null)
|
preprocessedFile.transform(irConstTypeAnnotationTransformer, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: We are using `IrElementTransformer` here instead of `IrElementTransformerVoid` to avoid conflicts with `IrTypeVisitorVoid`
|
// Note: We are using `IrElementTransformer` here instead of `IrElementTransformerVoid` to avoid conflicts with `IrTypeVisitorVoid`
|
||||||
@@ -83,7 +94,7 @@ internal abstract class IrConstTransformer(
|
|||||||
configuration: IrInterpreterConfiguration = interpreter.environment.configuration
|
configuration: IrInterpreterConfiguration = interpreter.environment.configuration
|
||||||
): Boolean {
|
): Boolean {
|
||||||
return try {
|
return try {
|
||||||
checkers.any { this.accept(it, IrInterpreterCheckerData(configuration)) }
|
checkers.any { this.accept(it, IrInterpreterCheckerData(interpreter.irBuiltIns, configuration)) }
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
if (suppressExceptions) {
|
if (suppressExceptions) {
|
||||||
return false
|
return false
|
||||||
|
|||||||
+2
@@ -15,6 +15,7 @@ const val methodName = A::foo.<!EVALUATED("foo")!>name<!>
|
|||||||
const val suspendMethodName = A::bar.<!EVALUATED("bar")!>name<!>
|
const val suspendMethodName = A::bar.<!EVALUATED("bar")!>name<!>
|
||||||
const val className = ::A.<!EVALUATED("<init>")!>name<!>
|
const val className = ::A.<!EVALUATED("<init>")!>name<!>
|
||||||
const val topLevelPropName = ::topLevelProp.<!EVALUATED("topLevelProp")!>name<!>
|
const val topLevelPropName = ::topLevelProp.<!EVALUATED("topLevelProp")!>name<!>
|
||||||
|
const val nameInComplexExpression = A::OK.<!EVALUATED("OK")!>name<!> <!EVALUATED("OK!")!>+ "!"<!>
|
||||||
|
|
||||||
// STOP_EVALUATION_CHECKS
|
// STOP_EVALUATION_CHECKS
|
||||||
fun box(): String {
|
fun box(): String {
|
||||||
@@ -24,5 +25,6 @@ fun box(): String {
|
|||||||
if (suspendMethodName.id() != "bar") return "Fail 3.2"
|
if (suspendMethodName.id() != "bar") return "Fail 3.2"
|
||||||
if (className.id() != "<init>") return "Fail 4"
|
if (className.id() != "<init>") return "Fail 4"
|
||||||
if (topLevelPropName.id() != "topLevelProp") return "Fail 5"
|
if (topLevelPropName.id() != "topLevelProp") return "Fail 5"
|
||||||
|
if (nameInComplexExpression.id() != "OK!") return "Fail 5"
|
||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+7
-4
@@ -17,13 +17,16 @@ class A {
|
|||||||
val b = A::b.<!EVALUATED("b")!>name<!>
|
val b = A::b.<!EVALUATED("b")!>name<!>
|
||||||
|
|
||||||
val c = ::A.<!EVALUATED("<init>")!>name<!>
|
val c = ::A.<!EVALUATED("<init>")!>name<!>
|
||||||
val d = this::a.name
|
val d = this::a.<!EVALUATED("a")!>name<!>
|
||||||
|
|
||||||
val e = A()::b.name
|
val e = A()::b.<!EVALUATED("b")!>name<!>
|
||||||
val f = getA()::b.name
|
val f = getA()::b.<!EVALUATED("b")!>name<!>
|
||||||
|
|
||||||
val temp = A()
|
val temp = A()
|
||||||
val g = temp::b.name
|
val g = temp::b.<!EVALUATED("b")!>name<!>
|
||||||
|
|
||||||
|
val complexExpression1 = A()::a.<!EVALUATED("a")!>name<!> + A()::b.<!EVALUATED("b")!>name<!>
|
||||||
|
val complexExpression2 = A::a.<!EVALUATED("a")!>name<!> <!EVALUATED("ab")!>+ A::b.<!EVALUATED("b")!>name<!><!>
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getA(): A = A()
|
fun getA(): A = A()
|
||||||
|
|||||||
Reference in New Issue
Block a user