FIR DFA: remove exactNotType
Literally not used for anything anymore. What a waste of CPU time. ...and safeCallBreakInsideDoWhile is broken again. Oh well.
This commit is contained in:
@@ -91,31 +91,18 @@ abstract class LogicSystem<FLOW : Flow>(protected val context: ConeInferenceCont
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------- Util functions -------------------------------
|
||||
|
||||
private fun foldStatements(statements: Collection<TypeStatement>, all: Boolean): TypeStatement {
|
||||
require(statements.isNotEmpty())
|
||||
statements.singleOrNull()?.let { return it }
|
||||
val variable = statements.first().variable
|
||||
assert(statements.all { it.variable == variable })
|
||||
// TypeStatement(variable, exactType, exactNotType) =
|
||||
// variable is intersect(exactType) && variable !is intersect(exactNotType)
|
||||
// So `and` of two type statements computes `and` of exactType and `or` of `exactNotType`,
|
||||
// while `or` is the opposite.
|
||||
return if (all) {
|
||||
val exactType = statements.flatMapTo(mutableSetOf()) { it.exactType }
|
||||
// variable !is a && variable !is b =/=> variable !is commonSuperType(a, b)
|
||||
// So in this case we can only take the union if either type is a subtype of the other.
|
||||
val exactNotType = unifyTypes(statements.map { it.exactNotType }, onlyInputTypes = true)
|
||||
MutableTypeStatement(variable, exactType, exactNotType?.let { mutableSetOf(it) } ?: mutableSetOf())
|
||||
} else {
|
||||
val exactType = unifyTypes(statements.map { it.exactType }, onlyInputTypes = false)
|
||||
val exactNotType = statements.flatMapTo(mutableSetOf()) { it.exactNotType }
|
||||
MutableTypeStatement(variable, exactType?.let { mutableSetOf(it) } ?: mutableSetOf(), exactNotType)
|
||||
private inline fun Collection<TypeStatement>.singleOrNew(exactType: () -> MutableSet<ConeKotlinType>): TypeStatement =
|
||||
when (size) {
|
||||
0 -> throw AssertionError("need at least one statement")
|
||||
1 -> first()
|
||||
else -> {
|
||||
val variable = first().variable
|
||||
assert(all { it.variable == variable }) { "folding statements for different variables" }
|
||||
MutableTypeStatement(variable, exactType())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun unifyTypes(types: Collection<Set<ConeKotlinType>>, onlyInputTypes: Boolean): ConeKotlinType? {
|
||||
private fun unifyTypes(types: Collection<Set<ConeKotlinType>>): ConeKotlinType? {
|
||||
if (types.any { it.isEmpty() }) return null
|
||||
val intersected = types.map { ConeTypeIntersector.intersectTypes(context, it.toList()) }
|
||||
val unified = context.commonSuperTypeOrNull(intersected) ?: return null
|
||||
@@ -123,14 +110,14 @@ abstract class LogicSystem<FLOW : Flow>(protected val context: ConeInferenceCont
|
||||
unified.isAcceptableForSmartcast() -> unified
|
||||
unified.canBeNull -> null
|
||||
else -> context.anyType()
|
||||
}.takeIf { !onlyInputTypes || it in intersected }
|
||||
}
|
||||
}
|
||||
|
||||
protected fun and(statements: Collection<TypeStatement>): TypeStatement =
|
||||
foldStatements(statements, all = true)
|
||||
statements.singleOrNew { statements.flatMapTo(mutableSetOf()) { it.exactType } }
|
||||
|
||||
protected fun or(statements: Collection<TypeStatement>): TypeStatement =
|
||||
foldStatements(statements, all = false)
|
||||
statements.singleOrNew { unifyTypes(statements.map { it.exactType })?.let { mutableSetOf(it) } ?: mutableSetOf() }
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+2
-3
@@ -16,7 +16,6 @@ import kotlin.math.max
|
||||
data class PersistentTypeStatement(
|
||||
override val variable: RealVariable,
|
||||
override val exactType: PersistentSet<ConeKotlinType>,
|
||||
override val exactNotType: PersistentSet<ConeKotlinType>
|
||||
) : TypeStatement()
|
||||
|
||||
typealias PersistentApprovedTypeStatements = PersistentMap<RealVariable, PersistentTypeStatement>
|
||||
@@ -391,7 +390,7 @@ private fun lowestCommonFlow(left: PersistentFlow, right: PersistentFlow): Persi
|
||||
|
||||
private fun TypeStatement.toPersistent(): PersistentTypeStatement = when (this) {
|
||||
is PersistentTypeStatement -> this
|
||||
else -> PersistentTypeStatement(variable, exactType.toPersistentSet(), exactNotType.toPersistentSet())
|
||||
else -> PersistentTypeStatement(variable, exactType.toPersistentSet())
|
||||
}
|
||||
|
||||
@JvmName("replaceVariableInStatements")
|
||||
@@ -436,5 +435,5 @@ private fun Statement.replaceVariable(from: RealVariable, to: RealVariable): Sta
|
||||
if (variable != from) this else when (this) {
|
||||
is OperationStatement -> copy(variable = to)
|
||||
is PersistentTypeStatement -> copy(variable = to)
|
||||
is MutableTypeStatement -> MutableTypeStatement(to, exactType, exactNotType)
|
||||
is MutableTypeStatement -> MutableTypeStatement(to, exactType)
|
||||
}
|
||||
|
||||
@@ -15,9 +15,8 @@ import kotlin.contracts.contract
|
||||
class MutableTypeStatement(
|
||||
override val variable: RealVariable,
|
||||
override val exactType: MutableSet<ConeKotlinType> = linkedSetOf(),
|
||||
override val exactNotType: MutableSet<ConeKotlinType> = linkedSetOf()
|
||||
) : TypeStatement() {
|
||||
fun copy(): MutableTypeStatement = MutableTypeStatement(variable, LinkedHashSet(exactType), LinkedHashSet(exactNotType))
|
||||
fun copy(): MutableTypeStatement = MutableTypeStatement(variable, LinkedHashSet(exactType))
|
||||
}
|
||||
|
||||
fun Implication.invertCondition(): Implication = Implication(condition.invert(), effect)
|
||||
@@ -49,25 +48,7 @@ infix fun DataFlowVariable.notEq(constant: Boolean?): OperationStatement {
|
||||
infix fun OperationStatement.implies(effect: Statement): Implication = Implication(this, effect)
|
||||
|
||||
infix fun RealVariable.typeEq(type: ConeKotlinType): MutableTypeStatement =
|
||||
MutableTypeStatement(this) andTypeEq type
|
||||
|
||||
infix fun RealVariable.typeNotEq(type: ConeKotlinType): MutableTypeStatement =
|
||||
MutableTypeStatement(this) andTypeNotEq type
|
||||
|
||||
infix fun MutableTypeStatement.andTypeEq(type: ConeKotlinType): MutableTypeStatement =
|
||||
this.apply {
|
||||
if (type !is ConeErrorType) {
|
||||
exactType += type
|
||||
}
|
||||
}
|
||||
|
||||
infix fun MutableTypeStatement.andTypeNotEq(type: ConeKotlinType): MutableTypeStatement =
|
||||
this.apply {
|
||||
require(exactNotType.isEmpty()) { "statement $this already has a negation; use `logicSystem.and`" }
|
||||
if (type !is ConeErrorType) {
|
||||
exactNotType += type
|
||||
}
|
||||
}
|
||||
MutableTypeStatement(this, if (type is ConeErrorType) linkedSetOf() else linkedSetOf(type))
|
||||
|
||||
// --------------------------------------- Utils ---------------------------------------
|
||||
|
||||
|
||||
@@ -31,16 +31,15 @@ data class OperationStatement(override val variable: DataFlowVariable, val opera
|
||||
sealed class TypeStatement : Statement() {
|
||||
abstract override val variable: RealVariable
|
||||
abstract val exactType: Set<ConeKotlinType>
|
||||
abstract val exactNotType: Set<ConeKotlinType>
|
||||
|
||||
val isEmpty: Boolean
|
||||
get() = exactType.isEmpty() && exactNotType.isEmpty()
|
||||
get() = exactType.isEmpty()
|
||||
|
||||
val isNotEmpty: Boolean
|
||||
get() = !isEmpty
|
||||
|
||||
override fun toString(): String {
|
||||
return "$variable: $exactType, $exactNotType"
|
||||
return "$variable: $exactType"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user