Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.jetbrains.kotlin.fir.resolve.dfa.LogicSystem.kt Maven / Gradle / Ivy
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.resolve.dfa
import org.jetbrains.kotlin.fir.types.ConeInferenceContext
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.commonSuperTypeOrNull
abstract class Flow {
abstract fun getTypeStatement(variable: RealVariable): TypeStatement?
abstract fun getImplications(variable: DataFlowVariable): Collection
abstract fun getVariablesInTypeStatements(): Collection
abstract fun removeOperations(variable: DataFlowVariable): Collection
abstract val directAliasMap: Map
abstract val backwardsAliasMap: Map>
}
fun Flow.unwrapVariable(variable: RealVariable): RealVariable {
return directAliasMap[variable]?.variable ?: variable
}
abstract class LogicSystem(protected val context: ConeInferenceContext) {
// ------------------------------- Flow operations -------------------------------
abstract fun createEmptyFlow(): FLOW
abstract fun forkFlow(flow: FLOW): FLOW
abstract fun joinFlow(flows: Collection): FLOW
abstract fun unionFlow(flows: Collection): FLOW
abstract fun addTypeStatement(flow: FLOW, statement: TypeStatement)
abstract fun addImplication(flow: FLOW, implication: Implication)
abstract fun removeAllAboutVariable(flow: FLOW, variable: RealVariable)
abstract fun translateVariableFromConditionInStatements(
flow: FLOW,
originalVariable: DataFlowVariable,
newVariable: DataFlowVariable,
shouldRemoveOriginalStatements: Boolean,
filter: (Implication) -> Boolean = { true },
transform: (Implication) -> Implication = { it },
)
abstract fun approveStatementsInsideFlow(
flow: FLOW,
approvedStatement: OperationStatement,
shouldForkFlow: Boolean,
shouldRemoveSynthetics: Boolean,
): FLOW
abstract fun addLocalVariableAlias(flow: FLOW, alias: RealVariable, underlyingVariable: RealVariableAndType)
abstract fun removeLocalVariableAlias(flow: FLOW, alias: RealVariable)
protected abstract fun getImplicationsWithVariable(flow: FLOW, variable: DataFlowVariable): Collection
// ------------------------------- Callbacks for updating implicit receiver stack -------------------------------
abstract fun processUpdatedReceiverVariable(flow: FLOW, variable: RealVariable)
abstract fun updateAllReceivers(flow: FLOW)
// ------------------------------- Public TypeStatement util functions -------------------------------
data class InfoForBooleanOperator(
val conditionalFromLeft: Collection,
val conditionalFromRight: Collection,
val knownFromRight: TypeStatements,
)
abstract fun collectInfoForBooleanOperator(
leftFlow: FLOW,
leftVariable: DataFlowVariable,
rightFlow: FLOW,
rightVariable: DataFlowVariable,
): InfoForBooleanOperator
abstract fun approveStatementsTo(
destination: MutableTypeStatements,
flow: FLOW,
approvedStatement: OperationStatement,
statements: Collection,
)
/**
* Recursively collects all TypeStatements approved by [approvedStatement] and all predicates
* that has been implied by it
* TODO: or not recursively?
*/
fun approveOperationStatement(flow: FLOW, approvedStatement: OperationStatement): Collection {
val statements = getImplicationsWithVariable(flow, approvedStatement.variable)
return approveOperationStatement(flow, approvedStatement, statements).values
}
fun orForTypeStatements(
left: TypeStatements,
right: TypeStatements,
): MutableTypeStatements {
if (left.isNullOrEmpty() || right.isNullOrEmpty()) return mutableMapOf()
val map = mutableMapOf()
for (variable in left.keys.intersect(right.keys)) {
val leftStatement = left.getValue(variable)
val rightStatement = right.getValue(variable)
map[variable] = or(listOf(leftStatement, rightStatement))
}
return map
}
// ------------------------------- Util functions -------------------------------
// TODO
protected fun Collection>.intersectSets(): Set {
if (isEmpty()) return emptySet()
val iterator = iterator()
val result = LinkedHashSet(iterator.next())
while (iterator.hasNext()) {
result.retainAll(iterator.next())
}
return result
}
protected fun or(statements: Collection): MutableTypeStatement {
require(statements.isNotEmpty())
statements.singleOrNull()?.let { return it as MutableTypeStatement }
val variable = statements.first().variable
assert(statements.all { it.variable == variable })
val exactType = orForTypes(statements.map { it.exactType })
val exactNotType = orForTypes(statements.map { it.exactNotType })
return MutableTypeStatement(variable, exactType, exactNotType)
}
private fun orForTypes(types: Collection>): MutableSet {
if (types.any { it.isEmpty() }) return mutableSetOf()
val allTypes = types.flatMapTo(mutableSetOf()) { it }
val commonTypes = allTypes.toMutableSet()
types.forEach { commonTypes.retainAll(it) }
val differentTypes = types.mapNotNull { typeSet -> (typeSet - commonTypes).takeIf { it.isNotEmpty() } }
if (differentTypes.size == types.size) {
context.commonSuperTypeOrNull(differentTypes.flatten())?.let { commonTypes += it }
}
return commonTypes
}
protected fun and(statements: Collection): MutableTypeStatement {
require(statements.isNotEmpty())
statements.singleOrNull()?.let { return it as MutableTypeStatement }
val variable = statements.first().variable
assert(statements.all { it.variable == variable })
val exactType = andForTypes(statements.map { it.exactType })
val exactNotType = andForTypes(statements.map { it.exactNotType })
return MutableTypeStatement(variable, exactType, exactNotType)
}
private fun andForTypes(types: Collection>): MutableSet {
return types.flatMapTo(mutableSetOf()) { it }
}
}
fun LogicSystem.approveOperationStatement(
flow: FLOW,
approvedStatement: OperationStatement,
statements: Collection,
): MutableTypeStatements {
return mutableMapOf().apply {
approveStatementsTo(this, flow, approvedStatement, statements)
}
}
/*
* used for:
* 1. val b = x is String
* 2. b = x is String
* 3. !b | b.not() for Booleans
*/
fun LogicSystem.replaceVariableFromConditionInStatements(
flow: F,
originalVariable: DataFlowVariable,
newVariable: DataFlowVariable,
filter: (Implication) -> Boolean = { true },
transform: (Implication) -> Implication = { it },
) {
translateVariableFromConditionInStatements(
flow,
originalVariable,
newVariable,
shouldRemoveOriginalStatements = true,
filter,
transform,
)
}