Refactor AndFunctor/OrFunction: do not use strictPartition

Instead use a filter with a simple check. This seems to be slightly
better both for readability (`strictPartition` gave an impression that
two its parameters were related in some way, but they were totally
independent) and for performance (do not create unnecessary objects,
instead decompose the existing objects and check their structure)
This commit is contained in:
Alexander Udalov
2018-12-21 17:11:41 +01:00
parent 07931451b1
commit 7561502956
3 changed files with 16 additions and 38 deletions
@@ -16,14 +16,10 @@
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.ESAnd
import org.jetbrains.kotlin.contracts.model.structure.ESConstant
import org.jetbrains.kotlin.contracts.model.structure.ESOr
import org.jetbrains.kotlin.contracts.model.structure.lift
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.*
class AndFunctor : AbstractBinaryFunctor() { class AndFunctor : AbstractBinaryFunctor() {
override fun invokeWithConstant(computation: Computation, constant: ESConstant): List<ESEffect> = when (constant) { override fun invokeWithConstant(computation: Computation, constant: ESConstant): List<ESEffect> = when (constant) {
@@ -40,8 +36,10 @@ class AndFunctor : AbstractBinaryFunctor() {
with Returns(1) (note that they still *return* as guaranteed by AbstractSequentialBinaryFunctor). with Returns(1) (note that they still *return* as guaranteed by AbstractSequentialBinaryFunctor).
We will just ignore such clauses in order to make smartcasting robust while typing */ We will just ignore such clauses in order to make smartcasting robust while typing */
val (leftTrue, leftFalse) = left.strictPartition(ESReturns(true.lift()), ESReturns(false.lift())) val leftTrue = left.filter { it.simpleEffect.isReturns { value.isTrue } }
val (rightTrue, rightFalse) = right.strictPartition(ESReturns(true.lift()), ESReturns(false.lift())) val leftFalse = left.filter { it.simpleEffect.isReturns { value.isFalse } }
val rightTrue = right.filter { it.simpleEffect.isReturns { value.isTrue } }
val rightFalse = right.filter { it.simpleEffect.isReturns { value.isFalse } }
val whenLeftReturnsTrue = foldConditionsWithOr(leftTrue) val whenLeftReturnsTrue = foldConditionsWithOr(leftTrue)
val whenRightReturnsTrue = foldConditionsWithOr(rightTrue) val whenRightReturnsTrue = foldConditionsWithOr(rightTrue)
@@ -68,4 +66,4 @@ class AndFunctor : AbstractBinaryFunctor() {
return result return result
} }
} }
@@ -16,10 +16,9 @@
package org.jetbrains.kotlin.contracts.model.functors package org.jetbrains.kotlin.contracts.model.functors
import org.jetbrains.kotlin.contracts.model.structure.ESOr
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.ESExpression import org.jetbrains.kotlin.contracts.model.ESExpression
import org.jetbrains.kotlin.contracts.model.structure.ESOr
/** /**
* Applies [operation] to [first] and [second] if both not-null, otherwise returns null * Applies [operation] to [first] and [second] if both not-null, otherwise returns null
@@ -44,21 +43,3 @@ internal fun foldConditionsWithOr(list: List<ConditionalEffect>): ESExpression?
null null
else else
list.map { it.condition }.reduce { acc, condition -> ESOr(acc, condition) } list.map { it.condition }.reduce { acc, condition -> ESOr(acc, condition) }
/**
* Places all clauses that equal to `firstModel` into first list, and all clauses that equal to `secondModel` into second list
*/
internal fun List<ConditionalEffect>.strictPartition(
firstModel: ESEffect,
secondModel: ESEffect
): Pair<List<ConditionalEffect>, List<ConditionalEffect>> {
val first = mutableListOf<ConditionalEffect>()
val second = mutableListOf<ConditionalEffect>()
forEach {
if (it.simpleEffect == firstModel) first += it
if (it.simpleEffect == secondModel) second += it
}
return first to second
}
@@ -16,14 +16,10 @@
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.ESAnd
import org.jetbrains.kotlin.contracts.model.structure.ESConstant
import org.jetbrains.kotlin.contracts.model.structure.ESOr
import org.jetbrains.kotlin.contracts.model.structure.lift
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.*
class OrFunctor : AbstractBinaryFunctor() { class OrFunctor : AbstractBinaryFunctor() {
override fun invokeWithConstant(computation: Computation, constant: ESConstant): List<ESEffect> = when (constant) { override fun invokeWithConstant(computation: Computation, constant: ESConstant): List<ESEffect> = when (constant) {
@@ -39,8 +35,11 @@ class OrFunctor : AbstractBinaryFunctor() {
expression wasn't properly typechecked, we could get some senseless clauses here, e.g. expression wasn't properly typechecked, we could get some senseless clauses here, e.g.
with Returns(1) (note that they still *return* as guaranteed by AbstractSequentialBinaryFunctor). with Returns(1) (note that they still *return* as guaranteed by AbstractSequentialBinaryFunctor).
We will just ignore such clauses in order to make smartcasting robust while typing */ We will just ignore such clauses in order to make smartcasting robust while typing */
val (leftTrue, leftFalse) = left.strictPartition(ESReturns(true.lift()), ESReturns(false.lift()))
val (rightTrue, rightFalse) = right.strictPartition(ESReturns(true.lift()), ESReturns(false.lift())) val leftTrue = left.filter { it.simpleEffect.isReturns { value.isTrue } }
val leftFalse = left.filter { it.simpleEffect.isReturns { value.isFalse } }
val rightTrue = right.filter { it.simpleEffect.isReturns { value.isTrue } }
val rightFalse = right.filter { it.simpleEffect.isReturns { value.isFalse } }
val whenLeftReturnsTrue = foldConditionsWithOr(leftTrue) val whenLeftReturnsTrue = foldConditionsWithOr(leftTrue)
val whenRightReturnsTrue = foldConditionsWithOr(rightTrue) val whenRightReturnsTrue = foldConditionsWithOr(rightTrue)
@@ -67,4 +66,4 @@ class OrFunctor : AbstractBinaryFunctor() {
return result return result
} }
} }