Allow to create object in interpreter only if it is compile time
This commit is contained in:
committed by
TeamCityServer
parent
6e12cee626
commit
25989b36c5
@@ -370,11 +370,10 @@ class IrInterpreter private constructor(
|
||||
callStack.addInstruction(CompoundInstruction(field.initializer?.expression))
|
||||
}
|
||||
expression.accessesTopLevelOrObjectField() -> {
|
||||
// receiver is null, for example, for top level fields
|
||||
val propertyOwner = field.correspondingPropertySymbol?.owner
|
||||
val isConst = propertyOwner?.isConst == true || propertyOwner?.backingField?.initializer?.expression is IrConst<*>
|
||||
assert(isConst) { "Cannot interpret get method on top level non const properties" }
|
||||
callStack.addInstruction(CompoundInstruction(expression.symbol.owner.initializer?.expression))
|
||||
callStack.addInstruction(CompoundInstruction(field.initializer?.expression))
|
||||
}
|
||||
else -> {
|
||||
val result = callStack.getState(receiver!!).getField(field.correspondingPropertySymbol!!)
|
||||
@@ -390,6 +389,9 @@ class IrInterpreter private constructor(
|
||||
environment.mapOfObjects[objectClass.symbol] = state // must set object's state here to avoid cyclic evaluation
|
||||
callStack.addVariable(Variable(objectClass.thisReceiver!!.symbol, state))
|
||||
|
||||
// non compile time objects can be used in interpreter, for example, to evaluate const properties
|
||||
if (!objectClass.hasAnnotation(compileTimeAnnotation)) return@interceptGetObjectValue callStack.pushState(state)
|
||||
|
||||
val constructor = objectClass.constructors.firstOrNull() ?: return@interceptGetObjectValue callStack.pushState(state)
|
||||
val constructorCall = IrConstructorCallImpl.fromSymbolOwner(constructor.returnType, constructor.symbol)
|
||||
callStack.newSubFrame(constructorCall)
|
||||
|
||||
+4
-3
@@ -119,9 +119,10 @@ class IrCompileTimeChecker(
|
||||
}
|
||||
|
||||
override fun visitGetValue(expression: IrGetValue, data: Nothing?): Boolean {
|
||||
val parent = expression.symbol.owner.parent as IrSymbolOwner
|
||||
val isObject = (parent as? IrClass)?.isObject == true //used to evaluate constants inside object
|
||||
return visitedStack.contains(parent) || isObject
|
||||
val owner = expression.symbol.owner
|
||||
val parent = owner.parent as IrSymbolOwner
|
||||
val isObjectReceiver = (parent as? IrClass)?.isObject == true && owner.origin == IrDeclarationOrigin.INSTANCE_RECEIVER
|
||||
return visitedStack.contains(parent) || isObjectReceiver
|
||||
}
|
||||
|
||||
override fun visitSetValue(expression: IrSetValue, data: Nothing?): Boolean {
|
||||
|
||||
+5
@@ -1,3 +1,4 @@
|
||||
@CompileTimeCalculation
|
||||
class A {
|
||||
const val a = <!EVALUATED: `10`!>{ 10 }()<!>
|
||||
|
||||
@@ -10,10 +11,13 @@ class A {
|
||||
}
|
||||
}
|
||||
|
||||
@CompileTimeCalculation
|
||||
object ObjectWithConst {
|
||||
const val a = 100
|
||||
const val b = <!EVALUATED: `Value in a: 100`!>concat("Value in a: ", a)<!>
|
||||
|
||||
val nonConst = "Not const field in compile time object"
|
||||
|
||||
fun concat(first: String, second: Any) = "$first$second"
|
||||
}
|
||||
|
||||
@@ -21,3 +25,4 @@ const val num = A().<!EVALUATED: `10`!>a<!>
|
||||
const val numStatic = A.<!EVALUATED: `-10`!>static<!>
|
||||
const val numStaticFromFun = A.<!EVALUATED: `2147483647`!>getStaticNumber()<!>
|
||||
const val valFromObject = ObjectWithConst.<!EVALUATED: `Value in a: 100`!>b<!>
|
||||
const val valFnonConstFromObject = ObjectWithConst.<!EVALUATED: `Not const field in compile time object`!>nonConst<!>
|
||||
|
||||
Reference in New Issue
Block a user