Add utility to check if effect is ESReturns

Somewhat simplify related code in AbstractBinaryFunctor and
AbstractUnaryFunctor
This commit is contained in:
Alexander Udalov
2018-12-21 17:15:03 +01:00
parent de22c133c7
commit cf19fa832c
4 changed files with 23 additions and 34 deletions
@@ -125,7 +125,7 @@ class EffectsExtractingVisitor(
// null bypassing function's contract, so we have to filter them out // null bypassing function's contract, so we have to filter them out
fun ESEffect.containsReturnsNull(): Boolean = fun ESEffect.containsReturnsNull(): Boolean =
this == ESReturns(ESConstant.NULL) || this is ConditionalEffect && this.simpleEffect.containsReturnsNull() isReturns { value == ESConstant.NULL } || this is ConditionalEffect && this.simpleEffect.containsReturnsNull()
val effectsWithoutReturnsNull = computation.effects.filter { !it.containsReturnsNull() } val effectsWithoutReturnsNull = computation.effects.filter { !it.containsReturnsNull() }
return CallComputation(computation.type, effectsWithoutReturnsNull) return CallComputation(computation.type, effectsWithoutReturnsNull)
@@ -16,15 +16,15 @@
package org.jetbrains.kotlin.contracts.model.functors package org.jetbrains.kotlin.contracts.model.functors
import org.jetbrains.kotlin.contracts.model.structure.ESReturns import org.jetbrains.kotlin.contracts.model.Computation
import org.jetbrains.kotlin.contracts.model.structure.ESConstant
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
import org.jetbrains.kotlin.contracts.model.Computation import org.jetbrains.kotlin.contracts.model.structure.ESConstant
import org.jetbrains.kotlin.contracts.model.structure.isReturns
abstract class AbstractBinaryFunctor : AbstractReducingFunctor() { abstract class AbstractBinaryFunctor : AbstractReducingFunctor() {
override fun doInvocation(arguments: List<Computation>): List<ESEffect> { override fun doInvocation(arguments: List<Computation>): List<ESEffect> {
assert(arguments.size == 2, { "Wrong size of arguments list for Binary functor: expected 2, got ${arguments.size}" }) assert(arguments.size == 2) { "Wrong size of arguments list for Binary functor: expected 2, got ${arguments.size}" }
return invokeWithArguments(arguments[0], arguments[1]) return invokeWithArguments(arguments[0], arguments[1])
} }
@@ -32,23 +32,13 @@ abstract class AbstractBinaryFunctor : AbstractReducingFunctor() {
if (left is ESConstant) return invokeWithConstant(right, left) if (left is ESConstant) return invokeWithConstant(right, left)
if (right is ESConstant) return invokeWithConstant(left, right) if (right is ESConstant) return invokeWithConstant(left, right)
val nonInterestingEffects = mutableListOf<ESEffect>() val leftValueReturning =
val leftValueReturning = mutableListOf<ConditionalEffect>() left.effects.filterIsInstance<ConditionalEffect>().filter { it.simpleEffect.isReturns { value != ESConstant.WILDCARD } }
val rightValueReturning = mutableListOf<ConditionalEffect>() val rightValueReturning =
right.effects.filterIsInstance<ConditionalEffect>().filter { it.simpleEffect.isReturns { value != ESConstant.WILDCARD } }
left.effects.forEach { val nonInterestingEffects =
if (it !is ConditionalEffect || it.simpleEffect !is ESReturns || it.simpleEffect.value == ESConstant.WILDCARD) left.effects - leftValueReturning + right.effects - rightValueReturning
nonInterestingEffects += it
else
leftValueReturning += it
}
right.effects.forEach {
if (it !is ConditionalEffect || it.simpleEffect !is ESReturns || it.simpleEffect.value == ESConstant.WILDCARD)
nonInterestingEffects += it
else
rightValueReturning += it
}
val evaluatedByFunctor = invokeWithReturningEffects(leftValueReturning, rightValueReturning) val evaluatedByFunctor = invokeWithReturningEffects(leftValueReturning, rightValueReturning)
@@ -60,4 +50,4 @@ abstract class AbstractBinaryFunctor : AbstractReducingFunctor() {
left: List<ConditionalEffect>, left: List<ConditionalEffect>,
right: List<ConditionalEffect> right: List<ConditionalEffect>
): List<ConditionalEffect> ): List<ConditionalEffect>
} }
@@ -16,12 +16,11 @@
package org.jetbrains.kotlin.contracts.model.functors package org.jetbrains.kotlin.contracts.model.functors
import org.jetbrains.kotlin.contracts.model.structure.ESReturns import org.jetbrains.kotlin.contracts.model.Computation
import org.jetbrains.kotlin.contracts.model.structure.ESConstant
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
import org.jetbrains.kotlin.contracts.model.Computation import org.jetbrains.kotlin.contracts.model.structure.ESConstant
import org.jetbrains.kotlin.contracts.model.structure.isReturns
/** /**
* Unary functor that has sequential semantics, i.e. it won't apply to * Unary functor that has sequential semantics, i.e. it won't apply to
@@ -32,15 +31,14 @@ import org.jetbrains.kotlin.contracts.model.Computation
*/ */
abstract class AbstractUnaryFunctor : AbstractReducingFunctor() { abstract class AbstractUnaryFunctor : AbstractReducingFunctor() {
override fun doInvocation(arguments: List<Computation>): List<ESEffect> { override fun doInvocation(arguments: List<Computation>): List<ESEffect> {
assert(arguments.size == 1, { "Wrong size of arguments list for Unary operator: expected 1, got ${arguments.size}" }) assert(arguments.size == 1) { "Wrong size of arguments list for Unary operator: expected 1, got ${arguments.size}" }
return invokeWithArguments(arguments[0]) return invokeWithArguments(arguments[0])
} }
fun invokeWithArguments(arg: Computation): List<ESEffect> { fun invokeWithArguments(arg: Computation): List<ESEffect> {
val returning = mutableListOf<ConditionalEffect>() val returning =
val rest = mutableListOf<ESEffect>() arg.effects.filterIsInstance<ConditionalEffect>().filter { it.simpleEffect.isReturns { value != ESConstant.WILDCARD } }
val rest = arg.effects - returning
arg.effects.forEach { if (it !is ConditionalEffect || it.simpleEffect !is ESReturns || it.simpleEffect.value == ESConstant.WILDCARD) rest += it else returning += it }
val evaluatedByFunctor = invokeWithReturningEffects(returning) val evaluatedByFunctor = invokeWithReturningEffects(returning)
@@ -49,5 +47,3 @@ abstract class AbstractUnaryFunctor : AbstractReducingFunctor() {
protected abstract fun invokeWithReturningEffects(list: List<ConditionalEffect>): List<ConditionalEffect> protected abstract fun invokeWithReturningEffects(list: List<ConditionalEffect>): List<ConditionalEffect>
} }
@@ -44,4 +44,7 @@ data class ESReturns(val value: ESValue) : SimpleEffect() {
return value == other.value return value == other.value
} }
} }
inline fun ESEffect.isReturns(block: ESReturns.() -> Boolean): Boolean =
this is ESReturns && block()