FIR DFA: remove approved and impossible statements from flows
This commit is contained in:
@@ -26,16 +26,16 @@ abstract class LogicSystem<FLOW : Flow>(protected val context: ConeInferenceCont
|
||||
flow: FLOW,
|
||||
originalVariable: DataFlowVariable,
|
||||
newVariable: DataFlowVariable,
|
||||
shouldRemoveOriginalStatements: Boolean,
|
||||
shouldRemoveOriginalStatements: Boolean = originalVariable.isSynthetic(),
|
||||
filter: (Implication) -> Boolean = { true },
|
||||
transform: (Implication) -> Implication? = { it },
|
||||
)
|
||||
|
||||
// This does *not* commit the results to the flow (but it does mutate the flow if shouldRemoveSynthetics=true)
|
||||
// This does *not* commit the results to the flow (but it does mutate the flow if removeApprovedOrImpossible=true)
|
||||
abstract fun approveOperationStatement(
|
||||
flow: FLOW,
|
||||
approvedStatement: OperationStatement,
|
||||
shouldRemoveSynthetics: Boolean = false
|
||||
removeApprovedOrImpossible: Boolean = false
|
||||
): TypeStatements
|
||||
|
||||
protected abstract fun ConeKotlinType.isAcceptableForSmartcast(): Boolean
|
||||
@@ -90,26 +90,3 @@ abstract class LogicSystem<FLOW : Flow>(protected val context: ConeInferenceCont
|
||||
protected fun or(statements: Collection<TypeStatement>): TypeStatement =
|
||||
statements.singleOrNew { unifyTypes(statements.map { it.exactType })?.let { mutableSetOf(it) } ?: mutableSetOf() }
|
||||
}
|
||||
|
||||
/*
|
||||
* used for:
|
||||
* 1. val b = x is String
|
||||
* 2. b = x is String
|
||||
* 3. !b | b.not() for Booleans
|
||||
*/
|
||||
fun <F : Flow> LogicSystem<F>.replaceVariableFromConditionInStatements(
|
||||
flow: F,
|
||||
originalVariable: DataFlowVariable,
|
||||
newVariable: DataFlowVariable,
|
||||
filter: (Implication) -> Boolean = { true },
|
||||
transform: (Implication) -> Implication = { it },
|
||||
) {
|
||||
translateVariableFromConditionInStatements(
|
||||
flow,
|
||||
originalVariable,
|
||||
newVariable,
|
||||
shouldRemoveOriginalStatements = true,
|
||||
filter,
|
||||
transform,
|
||||
)
|
||||
}
|
||||
|
||||
+12
-8
@@ -256,7 +256,7 @@ abstract class PersistentLogicSystem(context: ConeInferenceContext) : LogicSyste
|
||||
override fun approveOperationStatement(
|
||||
flow: PersistentFlow,
|
||||
approvedStatement: OperationStatement,
|
||||
shouldRemoveSynthetics: Boolean,
|
||||
removeApprovedOrImpossible: Boolean,
|
||||
): TypeStatements {
|
||||
val approvedTypeStatements: ArrayListMultimap<RealVariable, TypeStatement> = ArrayListMultimap.create()
|
||||
val queue = LinkedList<OperationStatement>().apply { this += approvedStatement }
|
||||
@@ -266,17 +266,21 @@ abstract class PersistentLogicSystem(context: ConeInferenceContext) : LogicSyste
|
||||
// Defense from cycles in facts
|
||||
if (!approved.add(next)) continue
|
||||
val variable = next.variable
|
||||
val statements = flow.logicStatements[variable]?.takeIf { it.isNotEmpty() } ?: continue
|
||||
if (shouldRemoveSynthetics && variable.isSynthetic()) {
|
||||
flow.logicStatements -= variable
|
||||
}
|
||||
for (statement in statements) {
|
||||
if (statement.condition == next) {
|
||||
when (val effect = statement.effect) {
|
||||
val statements = flow.logicStatements[variable] ?: continue
|
||||
val stillUnknown = statements.removeAll {
|
||||
val knownValue = it.condition.operation.valueIfKnown(next.operation)
|
||||
if (knownValue == true) {
|
||||
when (val effect = it.effect) {
|
||||
is OperationStatement -> queue += effect
|
||||
is TypeStatement -> approvedTypeStatements.put(effect.variable, effect)
|
||||
}
|
||||
}
|
||||
removeApprovedOrImpossible && knownValue != null
|
||||
}
|
||||
if (stillUnknown.isEmpty()) {
|
||||
flow.logicStatements -= variable
|
||||
} else if (stillUnknown != statements) {
|
||||
flow.logicStatements = flow.logicStatements.put(variable, stillUnknown)
|
||||
}
|
||||
}
|
||||
return approvedTypeStatements.asMap().mapValues { and(it.value) }
|
||||
|
||||
@@ -62,6 +62,12 @@ enum class Operation {
|
||||
NotEqNull -> EqNull
|
||||
}
|
||||
|
||||
fun valueIfKnown(given: Operation): Boolean? = when (this) {
|
||||
EqTrue, EqFalse -> if (given == NotEqNull) null else given == this
|
||||
EqNull -> given == EqNull
|
||||
NotEqNull -> given == NotEqNull
|
||||
}
|
||||
|
||||
override fun toString(): String = when (this) {
|
||||
EqTrue -> "== True"
|
||||
EqFalse -> "== False"
|
||||
|
||||
Reference in New Issue
Block a user