From 0f3997c6ca620b6acbb4cc565483b1aabf468076 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Fri, 25 Dec 2015 20:24:14 +0300 Subject: [PATCH] InitState / VariableUseState / VariableControlFlowState moved to a separate file --- .../jetbrains/kotlin/cfg/ControlFlowInfo.kt | 108 ++++++++++++++++++ .../cfg/ControlFlowInformationProvider.java | 6 +- .../kotlin/cfg/PseudocodeVariablesData.kt | 99 +--------------- .../kotlin/cfg/AbstractDataFlowTest.java | 3 - 4 files changed, 114 insertions(+), 102 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInfo.kt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInfo.kt b/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInfo.kt new file mode 100644 index 00000000000..24a8ef89eee --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInfo.kt @@ -0,0 +1,108 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.cfg + +enum class InitState(private val s: String) { + // Definitely initialized + INITIALIZED("I"), + // Fake initializer in else branch of "exhaustive when without else", see MagicKind.EXHAUSTIVE_WHEN_ELSE + INITIALIZED_EXHAUSTIVELY("IE"), + // Initialized in some branches, not initialized in other branches + UNKNOWN("I?"), + // Definitely not initialized + NOT_INITIALIZED(""); + + fun merge(other: InitState): InitState { + // X merge X = X + // X merge IE = IE merge X = X + // else X merge Y = I? + if (this == other || other == INITIALIZED_EXHAUSTIVELY) return this + if (this == INITIALIZED_EXHAUSTIVELY) return other + return UNKNOWN + } + + override fun toString() = s +} + +class VariableControlFlowState private constructor(val initState: InitState, val isDeclared: Boolean) { + + fun definitelyInitialized(): Boolean { + return initState == InitState.INITIALIZED + } + + fun mayBeInitialized(): Boolean { + return initState != InitState.NOT_INITIALIZED + } + + override fun toString(): String { + if (initState == InitState.NOT_INITIALIZED && !isDeclared) return "-" + return "$initState${if (isDeclared) "D" else ""}" + } + + companion object { + + private val VS_IT = VariableControlFlowState(InitState.INITIALIZED, true) + private val VS_IF = VariableControlFlowState(InitState.INITIALIZED, false) + private val VS_ET = VariableControlFlowState(InitState.INITIALIZED_EXHAUSTIVELY, true) + private val VS_EF = VariableControlFlowState(InitState.INITIALIZED_EXHAUSTIVELY, false) + private val VS_UT = VariableControlFlowState(InitState.UNKNOWN, true) + private val VS_UF = VariableControlFlowState(InitState.UNKNOWN, false) + private val VS_NT = VariableControlFlowState(InitState.NOT_INITIALIZED, true) + private val VS_NF = VariableControlFlowState(InitState.NOT_INITIALIZED, false) + + fun create(initState: InitState, isDeclared: Boolean): VariableControlFlowState = + when (initState) { + InitState.INITIALIZED -> if (isDeclared) VS_IT else VS_IF + InitState.INITIALIZED_EXHAUSTIVELY -> if (isDeclared) VS_ET else VS_EF + InitState.UNKNOWN -> if (isDeclared) VS_UT else VS_UF + InitState.NOT_INITIALIZED -> if (isDeclared) VS_NT else VS_NF + } + + fun createInitializedExhaustively(isDeclared: Boolean): VariableControlFlowState { + return create(InitState.INITIALIZED_EXHAUSTIVELY, isDeclared) + } + + fun create(isInitialized: Boolean, isDeclared: Boolean = false): VariableControlFlowState { + return create(if (isInitialized) InitState.INITIALIZED else InitState.NOT_INITIALIZED, isDeclared) + } + + fun create(isDeclaredHere: Boolean, mergedEdgesData: VariableControlFlowState?): VariableControlFlowState { + return create(true, isDeclaredHere || mergedEdgesData != null && mergedEdgesData.isDeclared) + } + } +} + +enum class VariableUseState(private val priority: Int) { + READ(3), + WRITTEN_AFTER_READ(2), + ONLY_WRITTEN_NEVER_READ(1), + UNUSED(0); + + fun merge(variableUseState: VariableUseState?): VariableUseState { + if (variableUseState == null || priority > variableUseState.priority) return this + return variableUseState + } + + companion object { + + @JvmStatic + fun isUsed(variableUseState: VariableUseState?): Boolean { + return variableUseState != null && variableUseState != UNUSED + } + } +} + diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.java b/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.java index ebc21f306f5..19419e83a51 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.java @@ -28,8 +28,6 @@ import kotlin.jvm.functions.Function3; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.builtins.KotlinBuiltIns; -import org.jetbrains.kotlin.cfg.PseudocodeVariablesData.VariableControlFlowState; -import org.jetbrains.kotlin.cfg.PseudocodeVariablesData.VariableUseState; import org.jetbrains.kotlin.cfg.pseudocode.PseudoValue; import org.jetbrains.kotlin.cfg.pseudocode.Pseudocode; import org.jetbrains.kotlin.cfg.pseudocode.PseudocodeUtil; @@ -65,7 +63,7 @@ import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils; import java.util.*; -import static org.jetbrains.kotlin.cfg.PseudocodeVariablesData.VariableUseState.*; +import static org.jetbrains.kotlin.cfg.VariableUseState.*; import static org.jetbrains.kotlin.cfg.TailRecursionKind.*; import static org.jetbrains.kotlin.diagnostics.Errors.*; import static org.jetbrains.kotlin.diagnostics.Errors.UNREACHABLE_CODE; @@ -560,7 +558,7 @@ public class ControlFlowInformationProvider { || !ExpressionTypingUtils.isLocal(variableDescriptor.getContainingDeclaration(), variableDescriptor)) { return; } - PseudocodeVariablesData.VariableUseState variableUseState = in.get(variableDescriptor); + VariableUseState variableUseState = in.get(variableDescriptor); if (instruction instanceof WriteValueInstruction) { if (trace.get(CAPTURED_IN_CLOSURE, variableDescriptor) != null) return; KtElement element = ((WriteValueInstruction) instruction).getElement(); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/PseudocodeVariablesData.kt b/compiler/frontend/src/org/jetbrains/kotlin/cfg/PseudocodeVariablesData.kt index 75685102f7d..b11eec20b57 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/PseudocodeVariablesData.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/PseudocodeVariablesData.kt @@ -191,107 +191,16 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon variableUseState = VariableUseState.UNUSED } when (variableUseState) { - PseudocodeVariablesData.VariableUseState.UNUSED, PseudocodeVariablesData.VariableUseState.ONLY_WRITTEN_NEVER_READ -> exitResult.put(variableDescriptor, VariableUseState.ONLY_WRITTEN_NEVER_READ) - PseudocodeVariablesData.VariableUseState.WRITTEN_AFTER_READ, PseudocodeVariablesData.VariableUseState.READ -> exitResult.put(variableDescriptor, VariableUseState.WRITTEN_AFTER_READ) + VariableUseState.UNUSED, VariableUseState.ONLY_WRITTEN_NEVER_READ -> + exitResult.put(variableDescriptor, VariableUseState.ONLY_WRITTEN_NEVER_READ) + VariableUseState.WRITTEN_AFTER_READ, VariableUseState.READ -> + exitResult.put(variableDescriptor, VariableUseState.WRITTEN_AFTER_READ) } } return Edges(enterResult, exitResult) } }) - private enum class InitState private constructor(private val s: String) { - // Definitely initialized - INITIALIZED("I"), - // Fake initializer in else branch of "exhaustive when without else", see MagicKind.EXHAUSTIVE_WHEN_ELSE - INITIALIZED_EXHAUSTIVELY("IE"), - // Initialized in some branches, not initialized in other branches - UNKNOWN("I?"), - // Definitely not initialized - NOT_INITIALIZED(""); - - fun merge(other: InitState): InitState { - // X merge X = X - // X merge IE = IE merge X = X - // else X merge Y = I? - if (this == other || other == INITIALIZED_EXHAUSTIVELY) return this - if (this == INITIALIZED_EXHAUSTIVELY) return other - return UNKNOWN - } - - override fun toString(): String { - return s - } - } - - class VariableControlFlowState private constructor(val initState: InitState, val isDeclared: Boolean) { - - fun definitelyInitialized(): Boolean { - return initState == InitState.INITIALIZED - } - - fun mayBeInitialized(): Boolean { - return initState != InitState.NOT_INITIALIZED - } - - override fun toString(): String { - if (initState == InitState.NOT_INITIALIZED && !isDeclared) return "-" - return "$initState${if (isDeclared) "D" else ""}" - } - - companion object { - - private val VS_IT = VariableControlFlowState(InitState.INITIALIZED, true) - private val VS_IF = VariableControlFlowState(InitState.INITIALIZED, false) - private val VS_ET = VariableControlFlowState(InitState.INITIALIZED_EXHAUSTIVELY, true) - private val VS_EF = VariableControlFlowState(InitState.INITIALIZED_EXHAUSTIVELY, false) - private val VS_UT = VariableControlFlowState(InitState.UNKNOWN, true) - private val VS_UF = VariableControlFlowState(InitState.UNKNOWN, false) - private val VS_NT = VariableControlFlowState(InitState.NOT_INITIALIZED, true) - private val VS_NF = VariableControlFlowState(InitState.NOT_INITIALIZED, false) - - fun create(initState: InitState, isDeclared: Boolean): VariableControlFlowState { - when (initState) { - PseudocodeVariablesData.InitState.INITIALIZED -> return if (isDeclared) VS_IT else VS_IF - PseudocodeVariablesData.InitState.INITIALIZED_EXHAUSTIVELY -> return if (isDeclared) VS_ET else VS_EF - PseudocodeVariablesData.InitState.UNKNOWN -> return if (isDeclared) VS_UT else VS_UF - else -> return if (isDeclared) VS_NT else VS_NF - } - } - - fun createInitializedExhaustively(isDeclared: Boolean): VariableControlFlowState { - return create(InitState.INITIALIZED_EXHAUSTIVELY, isDeclared) - } - - fun create(isInitialized: Boolean, isDeclared: Boolean = false): VariableControlFlowState { - return create(if (isInitialized) InitState.INITIALIZED else InitState.NOT_INITIALIZED, isDeclared) - } - - fun create(isDeclaredHere: Boolean, mergedEdgesData: VariableControlFlowState?): VariableControlFlowState { - return create(true, isDeclaredHere || mergedEdgesData != null && mergedEdgesData.isDeclared) - } - } - } - - enum class VariableUseState private constructor(private val priority: Int) { - READ(3), - WRITTEN_AFTER_READ(2), - ONLY_WRITTEN_NEVER_READ(1), - UNUSED(0); - - fun merge(variableUseState: VariableUseState?): VariableUseState { - if (variableUseState == null || priority > variableUseState.priority) return this - return variableUseState - } - - companion object { - - @JvmStatic - fun isUsed(variableUseState: VariableUseState?): Boolean { - return variableUseState != null && variableUseState != UNUSED - } - } - } - companion object { @JvmStatic diff --git a/compiler/tests/org/jetbrains/kotlin/cfg/AbstractDataFlowTest.java b/compiler/tests/org/jetbrains/kotlin/cfg/AbstractDataFlowTest.java index bce33d502b2..f3e561bb530 100644 --- a/compiler/tests/org/jetbrains/kotlin/cfg/AbstractDataFlowTest.java +++ b/compiler/tests/org/jetbrains/kotlin/cfg/AbstractDataFlowTest.java @@ -30,9 +30,6 @@ import java.util.Collections; import java.util.List; import java.util.Map; -import static org.jetbrains.kotlin.cfg.PseudocodeVariablesData.VariableControlFlowState; -import static org.jetbrains.kotlin.cfg.PseudocodeVariablesData.VariableUseState; - public abstract class AbstractDataFlowTest extends AbstractPseudocodeTest { @Override