Do not use DefaultBuiltIns in contracts
Default built-ins represent built-ins loaded from the compiler jar via class loader, and they may not be equivalent to the built-ins present in the standard library that is used in compilation dependencies, in case the compiler and stdlib versions do not match. Use built-ins from the given module instead. This commit deals with more-or-less obvious usages of DefaultBuiltIns; next commits refactor the ESConstant values and related code to support injected built-ins
This commit is contained in:
@@ -16,8 +16,9 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.contracts
|
package org.jetbrains.kotlin.contracts
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
|
import org.jetbrains.kotlin.contracts.description.expressions.ConstantReference
|
||||||
import org.jetbrains.kotlin.contracts.model.ESValue
|
import org.jetbrains.kotlin.contracts.model.ESValue
|
||||||
import org.jetbrains.kotlin.contracts.model.MutableContextInfo
|
import org.jetbrains.kotlin.contracts.model.MutableContextInfo
|
||||||
import org.jetbrains.kotlin.contracts.model.structure.ESConstant
|
import org.jetbrains.kotlin.contracts.model.structure.ESConstant
|
||||||
@@ -26,41 +27,47 @@ import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfoFactory
|
|||||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue
|
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue
|
||||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.IdentifierInfo
|
import org.jetbrains.kotlin.resolve.calls.smartcasts.IdentifierInfo
|
||||||
|
|
||||||
fun MutableContextInfo.toDataFlowInfo(languageVersionSettings: LanguageVersionSettings): DataFlowInfo {
|
fun MutableContextInfo.toDataFlowInfo(languageVersionSettings: LanguageVersionSettings, builtIns: KotlinBuiltIns): DataFlowInfo {
|
||||||
var resultingDataFlowInfo = DataFlowInfoFactory.EMPTY
|
var resultingDataFlowInfo = DataFlowInfoFactory.EMPTY
|
||||||
|
|
||||||
extractDataFlowStatements(equalValues) { leftDfv, rightValue ->
|
extractDataFlowStatements(equalValues, builtIns) { leftDfv, rightValue ->
|
||||||
val rightDfv = rightValue.toDataFlowValue()
|
val rightDfv = rightValue.toDataFlowValue(builtIns)
|
||||||
if (rightDfv != null) {
|
if (rightDfv != null) {
|
||||||
resultingDataFlowInfo = resultingDataFlowInfo.equate(leftDfv, rightDfv, false, languageVersionSettings)
|
resultingDataFlowInfo = resultingDataFlowInfo.equate(leftDfv, rightDfv, false, languageVersionSettings)
|
||||||
}
|
}
|
||||||
IntArray(42) { it }
|
IntArray(42) { it }
|
||||||
}
|
}
|
||||||
|
|
||||||
extractDataFlowStatements(notEqualValues) { leftDfv, rightValue ->
|
extractDataFlowStatements(notEqualValues, builtIns) { leftDfv, rightValue ->
|
||||||
val rightDfv = rightValue.toDataFlowValue()
|
val rightDfv = rightValue.toDataFlowValue(builtIns)
|
||||||
if (rightDfv != null) {
|
if (rightDfv != null) {
|
||||||
resultingDataFlowInfo = resultingDataFlowInfo.disequate(leftDfv, rightDfv, languageVersionSettings)
|
resultingDataFlowInfo = resultingDataFlowInfo.disequate(leftDfv, rightDfv, languageVersionSettings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extractDataFlowStatements(subtypes) { leftDfv, type ->
|
extractDataFlowStatements(subtypes, builtIns) { leftDfv, type ->
|
||||||
resultingDataFlowInfo = resultingDataFlowInfo.establishSubtyping(leftDfv, type, languageVersionSettings)
|
resultingDataFlowInfo = resultingDataFlowInfo.establishSubtyping(leftDfv, type, languageVersionSettings)
|
||||||
}
|
}
|
||||||
|
|
||||||
return resultingDataFlowInfo
|
return resultingDataFlowInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
inline private fun <D> extractDataFlowStatements(dictionary: Map<ESValue, Set<D>>, callback: (DataFlowValue, D) -> Unit) {
|
private inline fun <D> extractDataFlowStatements(
|
||||||
|
dictionary: Map<ESValue, Set<D>>,
|
||||||
|
builtIns: KotlinBuiltIns,
|
||||||
|
callback: (DataFlowValue, D) -> Unit
|
||||||
|
) {
|
||||||
for ((key, setOfValues) in dictionary) {
|
for ((key, setOfValues) in dictionary) {
|
||||||
val leftDfv = key.toDataFlowValue() ?: continue
|
val leftDfv = key.toDataFlowValue(builtIns) ?: continue
|
||||||
setOfValues.forEach { callback(leftDfv, it) }
|
setOfValues.forEach { callback(leftDfv, it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ESValue.toDataFlowValue(): DataFlowValue? = when (this) {
|
private fun ESValue.toDataFlowValue(builtIns: KotlinBuiltIns): DataFlowValue? = when (this) {
|
||||||
is ESDataFlowValue -> dataFlowValue
|
is ESDataFlowValue -> dataFlowValue
|
||||||
ESConstant.NULL -> DataFlowValue.nullValue(DefaultBuiltIns.Instance)
|
is ESConstant -> when (constantReference) {
|
||||||
is ESConstant -> DataFlowValue(IdentifierInfo.NO, type)
|
ConstantReference.NULL -> DataFlowValue.nullValue(builtIns)
|
||||||
|
else -> DataFlowValue(IdentifierInfo.NO, type)
|
||||||
|
}
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
@@ -18,15 +18,11 @@ package org.jetbrains.kotlin.contracts
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
import org.jetbrains.kotlin.contracts.model.structure.ESCalls
|
|
||||||
import org.jetbrains.kotlin.contracts.model.structure.ESReturns
|
|
||||||
import org.jetbrains.kotlin.contracts.model.functors.EqualsFunctor
|
|
||||||
import org.jetbrains.kotlin.contracts.model.structure.ESConstant
|
|
||||||
import org.jetbrains.kotlin.contracts.model.structure.UNKNOWN_COMPUTATION
|
|
||||||
import org.jetbrains.kotlin.contracts.model.structure.lift
|
|
||||||
import org.jetbrains.kotlin.contracts.model.ESEffect
|
|
||||||
import org.jetbrains.kotlin.contracts.model.Computation
|
import org.jetbrains.kotlin.contracts.model.Computation
|
||||||
|
import org.jetbrains.kotlin.contracts.model.ESEffect
|
||||||
import org.jetbrains.kotlin.contracts.model.MutableContextInfo
|
import org.jetbrains.kotlin.contracts.model.MutableContextInfo
|
||||||
|
import org.jetbrains.kotlin.contracts.model.functors.EqualsFunctor
|
||||||
|
import org.jetbrains.kotlin.contracts.model.structure.*
|
||||||
import org.jetbrains.kotlin.contracts.model.visitors.InfoCollector
|
import org.jetbrains.kotlin.contracts.model.visitors.InfoCollector
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
import org.jetbrains.kotlin.psi.KtCallExpression
|
import org.jetbrains.kotlin.psi.KtCallExpression
|
||||||
@@ -54,7 +50,7 @@ class EffectSystem(val languageVersionSettings: LanguageVersionSettings, val dat
|
|||||||
|
|
||||||
val resultContextInfo = getContextInfoWhen(ESReturns(ESConstant.WILDCARD), callExpression, bindingTrace, moduleDescriptor)
|
val resultContextInfo = getContextInfoWhen(ESReturns(ESConstant.WILDCARD), callExpression, bindingTrace, moduleDescriptor)
|
||||||
|
|
||||||
return resultContextInfo.toDataFlowInfo(languageVersionSettings)
|
return resultContextInfo.toDataFlowInfo(languageVersionSettings, moduleDescriptor.builtIns)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getDataFlowInfoWhenEquals(
|
fun getDataFlowInfoWhenEquals(
|
||||||
@@ -73,12 +69,13 @@ class EffectSystem(val languageVersionSettings: LanguageVersionSettings, val dat
|
|||||||
|
|
||||||
val effects = EqualsFunctor(false).invokeWithArguments(leftComputation, rightComputation)
|
val effects = EqualsFunctor(false).invokeWithArguments(leftComputation, rightComputation)
|
||||||
|
|
||||||
|
val builtIns = moduleDescriptor.builtIns
|
||||||
val equalsContextInfo = InfoCollector(ESReturns(true.lift())).collectFromSchema(effects)
|
val equalsContextInfo = InfoCollector(ESReturns(true.lift())).collectFromSchema(effects)
|
||||||
val notEqualsContextInfo = InfoCollector(ESReturns(false.lift())).collectFromSchema(effects)
|
val notEqualsContextInfo = InfoCollector(ESReturns(false.lift())).collectFromSchema(effects)
|
||||||
|
|
||||||
return ConditionalDataFlowInfo(
|
return ConditionalDataFlowInfo(
|
||||||
equalsContextInfo.toDataFlowInfo(languageVersionSettings),
|
equalsContextInfo.toDataFlowInfo(languageVersionSettings, builtIns),
|
||||||
notEqualsContextInfo.toDataFlowInfo(languageVersionSettings)
|
notEqualsContextInfo.toDataFlowInfo(languageVersionSettings, builtIns)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,7 +104,7 @@ class EffectSystem(val languageVersionSettings: LanguageVersionSettings, val dat
|
|||||||
if (condition == null) return DataFlowInfo.EMPTY
|
if (condition == null) return DataFlowInfo.EMPTY
|
||||||
|
|
||||||
return getContextInfoWhen(ESReturns(value.lift()), condition, bindingTrace, moduleDescriptor)
|
return getContextInfoWhen(ESReturns(value.lift()), condition, bindingTrace, moduleDescriptor)
|
||||||
.toDataFlowInfo(languageVersionSettings)
|
.toDataFlowInfo(languageVersionSettings, moduleDescriptor.builtIns)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getContextInfoWhen(
|
private fun getContextInfoWhen(
|
||||||
|
|||||||
@@ -16,9 +16,8 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.contracts
|
package org.jetbrains.kotlin.contracts
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.contracts.description.ContractProviderKey
|
import org.jetbrains.kotlin.contracts.description.ContractProviderKey
|
||||||
import org.jetbrains.kotlin.contracts.interpretation.ContractInterpretationDispatcher
|
|
||||||
import org.jetbrains.kotlin.contracts.model.Computation
|
import org.jetbrains.kotlin.contracts.model.Computation
|
||||||
import org.jetbrains.kotlin.contracts.model.ConditionalEffect
|
import org.jetbrains.kotlin.contracts.model.ConditionalEffect
|
||||||
import org.jetbrains.kotlin.contracts.model.ESEffect
|
import org.jetbrains.kotlin.contracts.model.ESEffect
|
||||||
@@ -54,6 +53,8 @@ class EffectsExtractingVisitor(
|
|||||||
private val moduleDescriptor: ModuleDescriptor,
|
private val moduleDescriptor: ModuleDescriptor,
|
||||||
private val dataFlowValueFactory: DataFlowValueFactory
|
private val dataFlowValueFactory: DataFlowValueFactory
|
||||||
) : KtVisitor<Computation, Unit>() {
|
) : KtVisitor<Computation, Unit>() {
|
||||||
|
private val builtIns: KotlinBuiltIns = moduleDescriptor.builtIns
|
||||||
|
|
||||||
fun extractOrGetCached(element: KtElement): Computation {
|
fun extractOrGetCached(element: KtElement): Computation {
|
||||||
trace[BindingContext.EXPRESSION_EFFECTS, element]?.let { return it }
|
trace[BindingContext.EXPRESSION_EFFECTS, element]?.let { return it }
|
||||||
return element.accept(this, Unit).also { trace.record(BindingContext.EXPRESSION_EFFECTS, element, it) }
|
return element.accept(this, Unit).also { trace.record(BindingContext.EXPRESSION_EFFECTS, element, it) }
|
||||||
@@ -68,7 +69,7 @@ class EffectsExtractingVisitor(
|
|||||||
val descriptor = resolvedCall.resultingDescriptor
|
val descriptor = resolvedCall.resultingDescriptor
|
||||||
return when {
|
return when {
|
||||||
descriptor.isEqualsDescriptor() -> CallComputation(
|
descriptor.isEqualsDescriptor() -> CallComputation(
|
||||||
DefaultBuiltIns.Instance.booleanType,
|
builtIns.booleanType,
|
||||||
EqualsFunctor(false).invokeWithArguments(arguments)
|
EqualsFunctor(false).invokeWithArguments(arguments)
|
||||||
)
|
)
|
||||||
descriptor is ValueDescriptor -> ESDataFlowValue(
|
descriptor is ValueDescriptor -> ESDataFlowValue(
|
||||||
@@ -112,7 +113,7 @@ class EffectsExtractingVisitor(
|
|||||||
val rightType: KotlinType = trace[BindingContext.TYPE, expression.typeReference] ?: return UNKNOWN_COMPUTATION
|
val rightType: KotlinType = trace[BindingContext.TYPE, expression.typeReference] ?: return UNKNOWN_COMPUTATION
|
||||||
val arg = extractOrGetCached(expression.leftHandSide)
|
val arg = extractOrGetCached(expression.leftHandSide)
|
||||||
return CallComputation(
|
return CallComputation(
|
||||||
DefaultBuiltIns.Instance.booleanType,
|
builtIns.booleanType,
|
||||||
IsFunctor(rightType, expression.isNegated).invokeWithArguments(listOf(arg))
|
IsFunctor(rightType, expression.isNegated).invokeWithArguments(listOf(arg))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -138,10 +139,10 @@ class EffectsExtractingVisitor(
|
|||||||
val args = listOf(left, right)
|
val args = listOf(left, right)
|
||||||
|
|
||||||
return when (expression.operationToken) {
|
return when (expression.operationToken) {
|
||||||
KtTokens.EXCLEQ -> CallComputation(DefaultBuiltIns.Instance.booleanType, EqualsFunctor(true).invokeWithArguments(args))
|
KtTokens.EXCLEQ -> CallComputation(builtIns.booleanType, EqualsFunctor(true).invokeWithArguments(args))
|
||||||
KtTokens.EQEQ -> CallComputation(DefaultBuiltIns.Instance.booleanType, EqualsFunctor(false).invokeWithArguments(args))
|
KtTokens.EQEQ -> CallComputation(builtIns.booleanType, EqualsFunctor(false).invokeWithArguments(args))
|
||||||
KtTokens.ANDAND -> CallComputation(DefaultBuiltIns.Instance.booleanType, AndFunctor().invokeWithArguments(args))
|
KtTokens.ANDAND -> CallComputation(builtIns.booleanType, AndFunctor().invokeWithArguments(args))
|
||||||
KtTokens.OROR -> CallComputation(DefaultBuiltIns.Instance.booleanType, OrFunctor().invokeWithArguments(args))
|
KtTokens.OROR -> CallComputation(builtIns.booleanType, OrFunctor().invokeWithArguments(args))
|
||||||
else -> UNKNOWN_COMPUTATION
|
else -> UNKNOWN_COMPUTATION
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -149,7 +150,7 @@ class EffectsExtractingVisitor(
|
|||||||
override fun visitUnaryExpression(expression: KtUnaryExpression, data: Unit): Computation {
|
override fun visitUnaryExpression(expression: KtUnaryExpression, data: Unit): Computation {
|
||||||
val arg = extractOrGetCached(expression.baseExpression ?: return UNKNOWN_COMPUTATION)
|
val arg = extractOrGetCached(expression.baseExpression ?: return UNKNOWN_COMPUTATION)
|
||||||
return when (expression.operationToken) {
|
return when (expression.operationToken) {
|
||||||
KtTokens.EXCL -> CallComputation(DefaultBuiltIns.Instance.booleanType, NotFunctor().invokeWithArguments(arg))
|
KtTokens.EXCL -> CallComputation(builtIns.booleanType, NotFunctor().invokeWithArguments(arg))
|
||||||
else -> UNKNOWN_COMPUTATION
|
else -> UNKNOWN_COMPUTATION
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -170,7 +171,7 @@ class EffectsExtractingVisitor(
|
|||||||
|
|
||||||
private fun FunctionDescriptor.getFunctor(): Functor? {
|
private fun FunctionDescriptor.getFunctor(): Functor? {
|
||||||
val contractDescription = getUserData(ContractProviderKey)?.getContractDescription() ?: return null
|
val contractDescription = getUserData(ContractProviderKey)?.getContractDescription() ?: return null
|
||||||
return contractDescription.functor
|
return contractDescription.getFunctor(moduleDescriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ResolvedCall<*>.isCallWithUnsupportedReceiver(): Boolean =
|
private fun ResolvedCall<*>.isCallWithUnsupportedReceiver(): Boolean =
|
||||||
|
|||||||
+4
-4
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.contracts.description
|
|||||||
import org.jetbrains.kotlin.contracts.interpretation.ContractInterpretationDispatcher
|
import org.jetbrains.kotlin.contracts.interpretation.ContractInterpretationDispatcher
|
||||||
import org.jetbrains.kotlin.contracts.model.Functor
|
import org.jetbrains.kotlin.contracts.model.Functor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
import org.jetbrains.kotlin.storage.StorageManager
|
import org.jetbrains.kotlin.storage.StorageManager
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -38,12 +39,11 @@ open class ContractDescription(
|
|||||||
val ownerFunction: FunctionDescriptor,
|
val ownerFunction: FunctionDescriptor,
|
||||||
storageManager: StorageManager
|
storageManager: StorageManager
|
||||||
) {
|
) {
|
||||||
private val functorLazyValue = storageManager.createNullableLazyValue {
|
private val computeFunctor = storageManager.createMemoizedFunctionWithNullableValues<ModuleDescriptor, Functor> { module ->
|
||||||
ContractInterpretationDispatcher().convertContractDescriptorToFunctor(this)
|
ContractInterpretationDispatcher(module).convertContractDescriptorToFunctor(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
val functor: Functor?
|
fun getFunctor(usageModule: ModuleDescriptor): Functor? = computeFunctor(usageModule)
|
||||||
get() = functorLazyValue()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ContractDescriptionElement {
|
interface ContractDescriptionElement {
|
||||||
|
|||||||
+10
-7
@@ -16,21 +16,24 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.contracts.interpretation
|
package org.jetbrains.kotlin.contracts.interpretation
|
||||||
|
|
||||||
import org.jetbrains.kotlin.contracts.description.*
|
import org.jetbrains.kotlin.contracts.description.BooleanExpression
|
||||||
|
import org.jetbrains.kotlin.contracts.description.ConditionalEffectDeclaration
|
||||||
|
import org.jetbrains.kotlin.contracts.description.ContractDescription
|
||||||
|
import org.jetbrains.kotlin.contracts.description.EffectDeclaration
|
||||||
import org.jetbrains.kotlin.contracts.description.expressions.ConstantReference
|
import org.jetbrains.kotlin.contracts.description.expressions.ConstantReference
|
||||||
import org.jetbrains.kotlin.contracts.description.expressions.VariableReference
|
import org.jetbrains.kotlin.contracts.description.expressions.VariableReference
|
||||||
import org.jetbrains.kotlin.contracts.model.functors.SubstitutingFunctor
|
|
||||||
import org.jetbrains.kotlin.contracts.model.structure.ESConstant
|
|
||||||
import org.jetbrains.kotlin.contracts.model.structure.ESVariable
|
|
||||||
import org.jetbrains.kotlin.contracts.model.ESEffect
|
import org.jetbrains.kotlin.contracts.model.ESEffect
|
||||||
import org.jetbrains.kotlin.contracts.model.ESExpression
|
import org.jetbrains.kotlin.contracts.model.ESExpression
|
||||||
import org.jetbrains.kotlin.contracts.model.Functor
|
import org.jetbrains.kotlin.contracts.model.Functor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.contracts.model.functors.SubstitutingFunctor
|
||||||
|
import org.jetbrains.kotlin.contracts.model.structure.ESConstant
|
||||||
|
import org.jetbrains.kotlin.contracts.model.structure.ESVariable
|
||||||
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class manages conversion of [ContractDescription] to [Functor]
|
* This class manages conversion of [ContractDescription] to [Functor]
|
||||||
*/
|
*/
|
||||||
class ContractInterpretationDispatcher {
|
class ContractInterpretationDispatcher(internal val module: ModuleDescriptor) {
|
||||||
private val constantsInterpreter = ConstantValuesInterpreter()
|
private val constantsInterpreter = ConstantValuesInterpreter()
|
||||||
private val conditionInterpreter = ConditionInterpreter(this)
|
private val conditionInterpreter = ConditionInterpreter(this)
|
||||||
private val conditionalEffectInterpreter = ConditionalEffectInterpreter(this)
|
private val conditionalEffectInterpreter = ConditionalEffectInterpreter(this)
|
||||||
@@ -48,7 +51,7 @@ class ContractInterpretationDispatcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return SubstitutingFunctor(resultingClauses, contractDescription.ownerFunction)
|
return SubstitutingFunctor(resultingClauses, contractDescription.ownerFunction, module.builtIns)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun interpretEffect(effectDeclaration: EffectDeclaration): ESEffect? {
|
internal fun interpretEffect(effectDeclaration: EffectDeclaration): ESEffect? {
|
||||||
|
|||||||
+7
-3
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.contracts.model.functors
|
package org.jetbrains.kotlin.contracts.model.functors
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.contracts.model.*
|
import org.jetbrains.kotlin.contracts.model.*
|
||||||
import org.jetbrains.kotlin.contracts.model.structure.*
|
import org.jetbrains.kotlin.contracts.model.structure.*
|
||||||
import org.jetbrains.kotlin.contracts.model.visitors.Substitutor
|
import org.jetbrains.kotlin.contracts.model.visitors.Substitutor
|
||||||
@@ -23,8 +24,11 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.ValueDescriptor
|
import org.jetbrains.kotlin.descriptors.ValueDescriptor
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
|
|
||||||
class SubstitutingFunctor(private val basicEffects: List<ESEffect>, private val ownerFunction: FunctionDescriptor) :
|
class SubstitutingFunctor(
|
||||||
AbstractReducingFunctor() {
|
private val basicEffects: List<ESEffect>,
|
||||||
|
private val ownerFunction: FunctionDescriptor,
|
||||||
|
private val builtIns: KotlinBuiltIns
|
||||||
|
) : AbstractReducingFunctor() {
|
||||||
override fun doInvocation(arguments: List<Computation>): List<ESEffect> {
|
override fun doInvocation(arguments: List<Computation>): List<ESEffect> {
|
||||||
if (basicEffects.isEmpty()) return emptyList()
|
if (basicEffects.isEmpty()) return emptyList()
|
||||||
|
|
||||||
@@ -37,7 +41,7 @@ class SubstitutingFunctor(private val basicEffects: List<ESEffect>, private val
|
|||||||
}
|
}
|
||||||
|
|
||||||
val substitutions = parameters.zip(arguments).toMap()
|
val substitutions = parameters.zip(arguments).toMap()
|
||||||
val substitutor = Substitutor(substitutions)
|
val substitutor = Substitutor(substitutions, builtIns)
|
||||||
val substitutedClauses = mutableListOf<ESEffect>()
|
val substitutedClauses = mutableListOf<ESEffect>()
|
||||||
|
|
||||||
effectsLoop@ for (effect in basicEffects) {
|
effectsLoop@ for (effect in basicEffects) {
|
||||||
|
|||||||
+13
-8
@@ -16,8 +16,10 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.contracts.model.visitors
|
package org.jetbrains.kotlin.contracts.model.visitors
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.contracts.model.*
|
import org.jetbrains.kotlin.contracts.model.Computation
|
||||||
|
import org.jetbrains.kotlin.contracts.model.ESExpression
|
||||||
|
import org.jetbrains.kotlin.contracts.model.ESExpressionVisitor
|
||||||
import org.jetbrains.kotlin.contracts.model.structure.*
|
import org.jetbrains.kotlin.contracts.model.structure.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -25,33 +27,36 @@ import org.jetbrains.kotlin.contracts.model.structure.*
|
|||||||
* and then flattens resulting tree, producing an [EffectSchema], which describes effects
|
* and then flattens resulting tree, producing an [EffectSchema], which describes effects
|
||||||
* of this [ESExpression] with effects of arguments taken into consideration.
|
* of this [ESExpression] with effects of arguments taken into consideration.
|
||||||
*/
|
*/
|
||||||
class Substitutor(private val substitutions: Map<ESVariable, Computation>) : ESExpressionVisitor<Computation?> {
|
class Substitutor(
|
||||||
|
private val substitutions: Map<ESVariable, Computation>,
|
||||||
|
private val builtIns: KotlinBuiltIns
|
||||||
|
) : ESExpressionVisitor<Computation?> {
|
||||||
override fun visitIs(isOperator: ESIs): Computation? {
|
override fun visitIs(isOperator: ESIs): Computation? {
|
||||||
val arg = isOperator.left.accept(this) ?: return null
|
val arg = isOperator.left.accept(this) ?: return null
|
||||||
return CallComputation(DefaultBuiltIns.Instance.booleanType, isOperator.functor.invokeWithArguments(arg))
|
return CallComputation(builtIns.booleanType, isOperator.functor.invokeWithArguments(arg))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitNot(not: ESNot): Computation? {
|
override fun visitNot(not: ESNot): Computation? {
|
||||||
val arg = not.arg.accept(this) ?: return null
|
val arg = not.arg.accept(this) ?: return null
|
||||||
return CallComputation(DefaultBuiltIns.Instance.booleanType, not.functor.invokeWithArguments(arg))
|
return CallComputation(builtIns.booleanType, not.functor.invokeWithArguments(arg))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitEqual(equal: ESEqual): Computation? {
|
override fun visitEqual(equal: ESEqual): Computation? {
|
||||||
val left = equal.left.accept(this) ?: return null
|
val left = equal.left.accept(this) ?: return null
|
||||||
val right = equal.right.accept(this) ?: return null
|
val right = equal.right.accept(this) ?: return null
|
||||||
return CallComputation(DefaultBuiltIns.Instance.booleanType, equal.functor.invokeWithArguments(listOf(left, right)))
|
return CallComputation(builtIns.booleanType, equal.functor.invokeWithArguments(listOf(left, right)))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitAnd(and: ESAnd): Computation? {
|
override fun visitAnd(and: ESAnd): Computation? {
|
||||||
val left = and.left.accept(this) ?: return null
|
val left = and.left.accept(this) ?: return null
|
||||||
val right = and.right.accept(this) ?: return null
|
val right = and.right.accept(this) ?: return null
|
||||||
return CallComputation(DefaultBuiltIns.Instance.booleanType, and.functor.invokeWithArguments(left, right))
|
return CallComputation(builtIns.booleanType, and.functor.invokeWithArguments(left, right))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitOr(or: ESOr): Computation? {
|
override fun visitOr(or: ESOr): Computation? {
|
||||||
val left = or.left.accept(this) ?: return null
|
val left = or.left.accept(this) ?: return null
|
||||||
val right = or.right.accept(this) ?: return null
|
val right = or.right.accept(this) ?: return null
|
||||||
return CallComputation(DefaultBuiltIns.Instance.booleanType, or.functor.invokeWithArguments(left, right))
|
return CallComputation(builtIns.booleanType, or.functor.invokeWithArguments(left, right))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitVariable(esVariable: ESVariable): Computation? = substitutions[esVariable] ?: esVariable
|
override fun visitVariable(esVariable: ESVariable): Computation? = substitutions[esVariable] ?: esVariable
|
||||||
|
|||||||
Reference in New Issue
Block a user