Add methods for combine InvocationKind's

There is two methods added -- `or` and `and`

`or` is used by CFA for combining two kinds that came from different
edges of control flow graph

`and` is analog of `+` operator for invocation kinds
This commit is contained in:
Dmitriy Novozhilov
2020-06-17 10:21:34 +03:00
parent 4078b4b6f9
commit 25621d699b
3 changed files with 29 additions and 8 deletions
@@ -197,7 +197,7 @@ class FirContractSerializer {
InvocationKind.AT_MOST_ONCE -> ProtoBuf.Effect.InvocationKind.AT_MOST_ONCE
InvocationKind.EXACTLY_ONCE -> ProtoBuf.Effect.InvocationKind.EXACTLY_ONCE
InvocationKind.AT_LEAST_ONCE -> ProtoBuf.Effect.InvocationKind.AT_LEAST_ONCE
InvocationKind.UNKNOWN -> null
else -> null
}
private fun constantValueProtobufEnum(constantReference: ConeConstantReference): ProtoBuf.Expression.ConstantValue? =
@@ -5,13 +5,34 @@
package org.jetbrains.kotlin.contracts.description
enum class InvocationKind {
AT_MOST_ONCE,
EXACTLY_ONCE,
AT_LEAST_ONCE,
UNKNOWN
import kotlin.math.max
import kotlin.math.min
enum class InvocationKind(private val left: Int, private val right: Int) {
ZERO(0, 0), // 0..0
AT_MOST_ONCE(0, 1), // 0..1
EXACTLY_ONCE(1, 1), // 1..1
AT_LEAST_ONCE(1, 2), // 1..*
UNKNOWN(0, 2); // 0..*
companion object {
private fun fromRange(left: Int, right: Int): InvocationKind = when (min(left, 1) to min(right, 2)) {
0 to 0 -> ZERO
0 to 1 -> AT_MOST_ONCE
1 to 1 -> EXACTLY_ONCE
1 to 2 -> AT_LEAST_ONCE
0 to 2 -> UNKNOWN
else -> throw IllegalArgumentException()
}
fun or(x: InvocationKind, y: InvocationKind): InvocationKind = fromRange(min(x.left, y.left), max(x.right, y.right))
fun and(x: InvocationKind, y: InvocationKind): InvocationKind = fromRange(x.left + y.left, x.right + y.right)
}
infix fun or(other: InvocationKind): InvocationKind = Companion.or(this, other)
infix fun and(other: InvocationKind): InvocationKind = Companion.and(this, other)
}
fun InvocationKind.isDefinitelyVisited(): Boolean = this == InvocationKind.EXACTLY_ONCE || this == InvocationKind.AT_LEAST_ONCE
fun InvocationKind.canBeRevisited(): Boolean = this == InvocationKind.UNKNOWN || this == InvocationKind.AT_LEAST_ONCE
@@ -192,7 +192,7 @@ class ContractSerializer {
InvocationKind.AT_MOST_ONCE -> ProtoBuf.Effect.InvocationKind.AT_MOST_ONCE
InvocationKind.EXACTLY_ONCE -> ProtoBuf.Effect.InvocationKind.EXACTLY_ONCE
InvocationKind.AT_LEAST_ONCE -> ProtoBuf.Effect.InvocationKind.AT_LEAST_ONCE
InvocationKind.UNKNOWN -> null
else -> null
}
private fun constantValueProtobufEnum(constantReference: ConstantReference): ProtoBuf.Expression.ConstantValue? =