Refactoring: CFG.LexicalScope --> CFG.BlockScope #KT-11965 Fixed

This commit is contained in:
Mikhail Glukhikh
2016-04-19 18:41:12 +03:00
parent cda4d2dcce
commit a5b428d9ce
29 changed files with 168 additions and 168 deletions
@@ -34,10 +34,10 @@ interface ControlFlowBuilder {
val currentSubroutine: KtElement
val returnSubroutine: KtElement
// Lexical scopes
fun enterLexicalScope(block: KtElement)
// Scopes
fun enterBlockScope(block: KtElement)
fun exitLexicalScope(block: KtElement)
fun exitBlockScope(block: KtElement)
fun getExitPoint(labelElement: KtElement): Label?
fun getConditionEntryPoint(labelElement: KtElement): Label
@@ -217,11 +217,11 @@ abstract class ControlFlowBuilderAdapter : ControlFlowBuilder {
return delegateBuilder.newValue(element)
}
override fun enterLexicalScope(block: KtElement) {
delegateBuilder.enterLexicalScope(block)
override fun enterBlockScope(block: KtElement) {
delegateBuilder.enterBlockScope(block)
}
override fun exitLexicalScope(block: KtElement) {
delegateBuilder.exitLexicalScope(block)
override fun exitBlockScope(block: KtElement) {
delegateBuilder.exitBlockScope(block)
}
}
@@ -303,7 +303,7 @@ public class ControlFlowInformationProvider {
Map<Instruction, Edges<InitControlFlowInfo>> initializers =
pseudocodeVariablesData.getVariableInitializers();
final Set<VariableDescriptor> declaredVariables = pseudocodeVariablesData.getDeclaredVariables(pseudocode, true);
final LexicalScopeVariableInfo lexicalScopeVariableInfo = pseudocodeVariablesData.getLexicalScopeVariableInfo();
final BlockScopeVariableInfo blockScopeVariableInfo = pseudocodeVariablesData.getBlockScopeVariableInfo();
final Map<Instruction, DiagnosticFactory<?>> reportedDiagnosticMap = Maps.newHashMap();
@@ -318,7 +318,7 @@ public class ControlFlowInformationProvider {
) {
assert in != null && out != null;
VariableInitContext ctxt =
new VariableInitContext(instruction, reportedDiagnosticMap, in, out, lexicalScopeVariableInfo);
new VariableInitContext(instruction, reportedDiagnosticMap, in, out, blockScopeVariableInfo);
if (ctxt.variableDescriptor == null) return;
if (instruction instanceof ReadValueInstruction) {
ReadValueInstruction readValueInstruction = (ReadValueInstruction) instruction;
@@ -1123,22 +1123,22 @@ public class ControlFlowInformationProvider {
@NotNull Map<Instruction, DiagnosticFactory<?>> map,
@NotNull Map<VariableDescriptor, VariableControlFlowState> in,
@NotNull Map<VariableDescriptor, VariableControlFlowState> out,
@NotNull LexicalScopeVariableInfo lexicalScopeVariableInfo
@NotNull BlockScopeVariableInfo blockScopeVariableInfo
) {
super(instruction, map);
enterInitState = initialize(variableDescriptor, lexicalScopeVariableInfo, in);
exitInitState = initialize(variableDescriptor, lexicalScopeVariableInfo, out);
enterInitState = initialize(variableDescriptor, blockScopeVariableInfo, in);
exitInitState = initialize(variableDescriptor, blockScopeVariableInfo, out);
}
private VariableControlFlowState initialize(
VariableDescriptor variableDescriptor,
LexicalScopeVariableInfo lexicalScopeVariableInfo,
BlockScopeVariableInfo blockScopeVariableInfo,
Map<VariableDescriptor, VariableControlFlowState> map
) {
if (variableDescriptor == null) return null;
VariableControlFlowState state = map.get(variableDescriptor);
if (state != null) return state;
return PseudocodeVariablesData.getDefaultValueForInitializers(variableDescriptor, instruction, lexicalScopeVariableInfo);
return PseudocodeVariablesData.getDefaultValueForInitializers(variableDescriptor, instruction, blockScopeVariableInfo);
}
}
@@ -661,7 +661,7 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
}
var isFirst = true
for (catchClause in catchClauses) {
builder.enterLexicalScope(catchClause)
builder.enterBlockScope(catchClause)
if (!isFirst) {
builder.bindLabel(catchLabels.remove())
}
@@ -675,7 +675,7 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
}
generateInstructions(catchClause.catchBody)
builder.jump(afterCatches, expression)
builder.exitLexicalScope(catchClause)
builder.exitBlockScope(catchClause)
}
builder.bindLabel(afterCatches)
@@ -708,7 +708,7 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
}
override fun visitDoWhileExpression(expression: KtDoWhileExpression) {
builder.enterLexicalScope(expression)
builder.enterBlockScope(expression)
mark(expression)
val loopInfo = builder.enterLoop(expression)
@@ -728,11 +728,11 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
}
builder.bindLabel(loopInfo.exitPoint)
builder.loadUnit(expression)
builder.exitLexicalScope(expression)
builder.exitBlockScope(expression)
}
override fun visitForExpression(expression: KtForExpression) {
builder.enterLexicalScope(expression)
builder.enterBlockScope(expression)
generateInstructions(expression.loopRange)
declareLoopParameter(expression)
@@ -754,7 +754,7 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
builder.exitLoopBody(expression)
builder.bindLabel(loopInfo.exitPoint)
builder.loadUnit(expression)
builder.exitLexicalScope(expression)
builder.exitBlockScope(expression)
}
private fun declareLoopParameter(expression: KtForExpression) {
@@ -934,9 +934,9 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
}
override fun visitBlockExpression(expression: KtBlockExpression) {
val declareLexicalScope = !isBlockInDoWhile(expression)
if (declareLexicalScope) {
builder.enterLexicalScope(expression)
val declareBlockScope = !isBlockInDoWhile(expression)
if (declareBlockScope) {
builder.enterBlockScope(expression)
}
mark(expression)
val statements = expression.statements
@@ -956,8 +956,8 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
else {
copyValue(statements.lastOrNull(), expression)
}
if (declareLexicalScope) {
builder.exitLexicalScope(expression)
if (declareBlockScope) {
builder.exitBlockScope(expression)
}
}
@@ -18,7 +18,7 @@ package org.jetbrains.kotlin.cfg
import org.jetbrains.kotlin.cfg.pseudocode.Pseudocode
import org.jetbrains.kotlin.cfg.pseudocode.instructions.Instruction
import org.jetbrains.kotlin.cfg.pseudocode.instructions.LexicalScope
import org.jetbrains.kotlin.cfg.pseudocode.instructions.BlockScope
import org.jetbrains.kotlin.cfg.pseudocode.instructions.special.VariableDeclarationInstruction
import org.jetbrains.kotlin.cfg.pseudocodeTraverser.Edges
import org.jetbrains.kotlin.cfg.pseudocodeTraverser.TraversalOrder
@@ -33,7 +33,7 @@ class PseudocodeVariableDataCollector(
private val bindingContext: BindingContext,
private val pseudocode: Pseudocode
) {
val lexicalScopeVariableInfo = computeLexicalScopeVariableInfo(pseudocode)
val blockScopeVariableInfo = computeBlockScopeVariableInfo(pseudocode)
fun <I : ControlFlowInfo<*>> collectData(
traversalOrder: TraversalOrder,
@@ -54,23 +54,23 @@ class PseudocodeVariableDataCollector(
to: Instruction,
info: I
): I {
// If an edge goes from deeper lexical scope to a less deep one, this means that it points outside of the deeper scope.
val toDepth = to.lexicalScope.depth
if (toDepth >= from.lexicalScope.depth) return info
// If an edge goes from deeper scope to a less deep one, this means that it points outside of the deeper scope.
val toDepth = to.blockScope.depth
if (toDepth >= from.blockScope.depth) return info
// Variables declared in an inner (deeper) scope can't be accessed from an outer scope.
// Thus they can be filtered out upon leaving the inner scope.
@Suppress("UNCHECKED_CAST")
return info.copy().retainAll { variable ->
val lexicalScope = lexicalScopeVariableInfo.declaredIn[variable]
val blockScope = blockScopeVariableInfo.declaredIn[variable]
// '-1' for variables declared outside this pseudocode
val depth = lexicalScope?.depth ?: -1
val depth = blockScope?.depth ?: -1
depth <= toDepth
} as I
}
fun computeLexicalScopeVariableInfo(pseudocode: Pseudocode): LexicalScopeVariableInfo {
val lexicalScopeVariableInfo = LexicalScopeVariableInfoImpl()
fun computeBlockScopeVariableInfo(pseudocode: Pseudocode): BlockScopeVariableInfo {
val blockScopeVariableInfo = BlockScopeVariableInfoImpl()
pseudocode.traverse(TraversalOrder.FORWARD, { instruction ->
if (instruction is VariableDeclarationInstruction) {
val variableDeclarationElement = instruction.variableDeclarationElement
@@ -83,28 +83,28 @@ class PseudocodeVariableDataCollector(
"Variable descriptor should correspond to the instruction for ${instruction.element.text}.\n" +
"Descriptor: $descriptor"
}
lexicalScopeVariableInfo.registerVariableDeclaredInScope(
descriptor as VariableDescriptor, instruction.lexicalScope
blockScopeVariableInfo.registerVariableDeclaredInScope(
descriptor as VariableDescriptor, instruction.blockScope
)
}
}
})
return lexicalScopeVariableInfo
return blockScopeVariableInfo
}
}
interface LexicalScopeVariableInfo {
val declaredIn : Map<VariableDescriptor, LexicalScope>
val scopeVariables : Map<LexicalScope, Collection<VariableDescriptor>>
interface BlockScopeVariableInfo {
val declaredIn : Map<VariableDescriptor, BlockScope>
val scopeVariables : Map<BlockScope, Collection<VariableDescriptor>>
}
class LexicalScopeVariableInfoImpl : LexicalScopeVariableInfo {
override val declaredIn = HashMap<VariableDescriptor, LexicalScope>()
override val scopeVariables = HashMap<LexicalScope, MutableCollection<VariableDescriptor>>()
class BlockScopeVariableInfoImpl : BlockScopeVariableInfo {
override val declaredIn = HashMap<VariableDescriptor, BlockScope>()
override val scopeVariables = HashMap<BlockScope, MutableCollection<VariableDescriptor>>()
fun registerVariableDeclaredInScope(variable: VariableDescriptor, lexicalScope: LexicalScope) {
declaredIn[variable] = lexicalScope
val variablesInScope = scopeVariables.getOrPut(lexicalScope, { ArrayList<VariableDescriptor>() })
fun registerVariableDeclaredInScope(variable: VariableDescriptor, blockScope: BlockScope) {
declaredIn[variable] = blockScope
val variablesInScope = scopeVariables.getOrPut(blockScope, { ArrayList<VariableDescriptor>() })
variablesInScope.add(variable)
}
}
@@ -43,8 +43,8 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon
this.pseudocodeVariableDataCollector = PseudocodeVariableDataCollector(bindingContext, pseudocode)
}
val lexicalScopeVariableInfo: LexicalScopeVariableInfo
get() = pseudocodeVariableDataCollector.lexicalScopeVariableInfo
val blockScopeVariableInfo: BlockScopeVariableInfo
get() = pseudocodeVariableDataCollector.blockScopeVariableInfo
fun getDeclaredVariables(pseudocode: Pseudocode, includeInsideLocalDeclarations: Boolean): Set<VariableDescriptor> {
if (!includeInsideLocalDeclarations) {
@@ -88,7 +88,7 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon
private fun computeVariableInitializers(): Map<Instruction, Edges<InitControlFlowInfo>> {
val lexicalScopeVariableInfo = pseudocodeVariableDataCollector.lexicalScopeVariableInfo
val blockScopeVariableInfo = pseudocodeVariableDataCollector.blockScopeVariableInfo
return pseudocodeVariableDataCollector.collectData(
TraversalOrder.FORWARD, /*mergeDataWithLocalDeclarations=*/ true, InitControlFlowInfo()
@@ -97,7 +97,7 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon
val enterInstructionData = mergeIncomingEdgesDataForInitializers(incomingEdgesData)
val exitInstructionData = addVariableInitStateFromCurrentInstructionIfAny(
instruction, enterInstructionData, lexicalScopeVariableInfo)
instruction, enterInstructionData, blockScopeVariableInfo)
Edges(enterInstructionData, exitInstructionData)
}
}
@@ -105,7 +105,7 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon
private fun addVariableInitStateFromCurrentInstructionIfAny(
instruction: Instruction,
enterInstructionData: InitControlFlowInfo,
lexicalScopeVariableInfo: LexicalScopeVariableInfo): InitControlFlowInfo {
blockScopeVariableInfo: BlockScopeVariableInfo): InitControlFlowInfo {
if (instruction is MagicInstruction) {
if (instruction.kind === MagicKind.EXHAUSTIVE_WHEN_ELSE) {
val exitInstructionData = enterInstructionData.copy()
@@ -137,7 +137,7 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon
// instruction instanceof VariableDeclarationInstruction
var enterInitState: VariableControlFlowState? = enterInstructionData[variable]
if (enterInitState == null) {
enterInitState = getDefaultValueForInitializers(variable, instruction, lexicalScopeVariableInfo)
enterInitState = getDefaultValueForInitializers(variable, instruction, blockScopeVariableInfo)
}
if (!enterInitState.mayBeInitialized() || !enterInitState.isDeclared) {
val isInitialized = enterInitState.mayBeInitialized()
@@ -201,13 +201,13 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon
fun getDefaultValueForInitializers(
variable: VariableDescriptor,
instruction: Instruction,
lexicalScopeVariableInfo: LexicalScopeVariableInfo
blockScopeVariableInfo: BlockScopeVariableInfo
): VariableControlFlowState {
//todo: think of replacing it with "MapWithDefaultValue"
val declaredIn = lexicalScopeVariableInfo.declaredIn[variable]
val declaredIn = blockScopeVariableInfo.declaredIn[variable]
val declaredOutsideThisDeclaration =
declaredIn == null //declared outside this pseudocode
|| declaredIn.lexicalScopeForContainingDeclaration != instruction.lexicalScope.lexicalScopeForContainingDeclaration
|| declaredIn.blockScopeForContainingDeclaration != instruction.blockScope.blockScopeForContainingDeclaration
return VariableControlFlowState.create(/*initState=*/declaredOutsideThisDeclaration)
}
@@ -20,7 +20,7 @@ import com.intellij.util.containers.Stack
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.cfg.*
import org.jetbrains.kotlin.cfg.pseudocode.instructions.Instruction
import org.jetbrains.kotlin.cfg.pseudocode.instructions.LexicalScope
import org.jetbrains.kotlin.cfg.pseudocode.instructions.BlockScope
import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.*
import org.jetbrains.kotlin.cfg.pseudocode.instructions.jumps.*
import org.jetbrains.kotlin.cfg.pseudocode.instructions.special.*
@@ -39,7 +39,7 @@ class ControlFlowInstructionsGenerator : ControlFlowBuilderAdapter() {
get() = builder ?: throw AssertionError("Builder stack is empty in ControlFlowInstructionsGenerator!")
private val loopInfo = Stack<LoopInfo>()
private val lexicalScopes = Stack<LexicalScope>()
private val blockScopes = Stack<BlockScope>()
private val elementToBlockInfo = HashMap<KtElement, BreakableBlockInfo>()
private var labelCount = 0
@@ -72,13 +72,13 @@ class ControlFlowInstructionsGenerator : ControlFlowBuilderAdapter() {
else {
pushBuilder(subroutine, subroutine)
}
delegateBuilder.enterLexicalScope(subroutine)
delegateBuilder.enterBlockScope(subroutine)
delegateBuilder.enterSubroutine(subroutine)
}
override fun exitSubroutine(subroutine: KtElement): Pseudocode {
super.exitSubroutine(subroutine)
delegateBuilder.exitLexicalScope(subroutine)
delegateBuilder.exitBlockScope(subroutine)
val worker = popBuilder()
if (!builders.empty()) {
val builder = builders.peek()
@@ -176,23 +176,23 @@ class ControlFlowInstructionsGenerator : ControlFlowBuilderAdapter() {
return elementToBlockInfo[labelElement]?.exitPoint
}
private val currentScope: LexicalScope
get() = lexicalScopes.peek()
private val currentScope: BlockScope
get() = blockScopes.peek()
override fun enterLexicalScope(block: KtElement) {
val current = if (lexicalScopes.isEmpty()) null else currentScope
val scope = LexicalScope(current, block)
lexicalScopes.push(scope)
override fun enterBlockScope(block: KtElement) {
val current = if (blockScopes.isEmpty()) null else currentScope
val scope = BlockScope(current, block)
blockScopes.push(scope)
}
override fun exitLexicalScope(block: KtElement) {
override fun exitBlockScope(block: KtElement) {
val currentScope = currentScope
assert(currentScope.block === block) {
"Exit from not the current lexical scope.\n" +
"Exit from not the current block scope.\n" +
"Current scope is for a block: " + currentScope.block.text + ".\n" +
"Exit from the scope for: " + block.text
}
lexicalScopes.pop()
blockScopes.pop()
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -19,11 +19,11 @@ package org.jetbrains.kotlin.cfg.pseudocode.instructions
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtElement
class LexicalScope(private val parentScope: LexicalScope?, val block: KtElement) {
class BlockScope(private val parentScope: BlockScope?, val block: KtElement) {
val depth: Int = (parentScope?.depth ?: 0) + 1
val lexicalScopeForContainingDeclaration: LexicalScope? by lazy {
var scope: LexicalScope? = this
val blockScopeForContainingDeclaration: BlockScope? by lazy {
var scope: BlockScope? = this
while (scope != null) {
if (scope.block is KtDeclaration) {
break
@@ -27,7 +27,7 @@ interface Instruction {
val dead: Boolean
val lexicalScope: LexicalScope
val blockScope: BlockScope
val inputValues: List<PseudoValue>
@@ -21,7 +21,7 @@ import java.util.LinkedHashSet
import org.jetbrains.kotlin.cfg.pseudocode.Pseudocode
import org.jetbrains.kotlin.cfg.pseudocode.PseudoValue
abstract class InstructionImpl(override val lexicalScope: LexicalScope): Instruction {
abstract class InstructionImpl(override val blockScope: BlockScope): Instruction {
private var _owner: Pseudocode? = null
override var owner: Pseudocode
@@ -21,8 +21,8 @@ import org.jetbrains.kotlin.utils.emptyOrSingletonList
abstract class InstructionWithNext(
element: KtElement,
lexicalScope: LexicalScope
) : KtElementInstructionImpl(element, lexicalScope) {
blockScope: BlockScope
) : KtElementInstructionImpl(element, blockScope) {
var next: Instruction? = null
set(value: Instruction?) {
field = outgoingEdgeTo(value)
@@ -21,8 +21,8 @@ import org.jetbrains.kotlin.psi.KtElement
abstract class KtElementInstructionImpl(
override val element: KtElement,
lexicalScope: LexicalScope
) : InstructionImpl(lexicalScope), KtElementInstruction {
blockScope: BlockScope
) : InstructionImpl(blockScope), KtElementInstruction {
protected fun render(element: PsiElement): String =
element.text?.replace("\\s+".toRegex(), " ") ?: ""
}
@@ -19,14 +19,14 @@ package org.jetbrains.kotlin.cfg.pseudocode.instructions.eval
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionWithNext
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitor
import org.jetbrains.kotlin.cfg.pseudocode.instructions.LexicalScope
import org.jetbrains.kotlin.cfg.pseudocode.instructions.BlockScope
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionImpl
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitorWithResult
class LoadUnitValueInstruction(
expression: KtExpression,
lexicalScope: LexicalScope
) : InstructionWithNext(expression, lexicalScope) {
blockScope: BlockScope
) : InstructionWithNext(expression, blockScope) {
override fun accept(visitor: InstructionVisitor) {
visitor.visitLoadUnitValue(this)
}
@@ -39,5 +39,5 @@ class LoadUnitValueInstruction(
"read (Unit)"
override fun createCopy(): InstructionImpl =
LoadUnitValueInstruction(element as KtExpression, lexicalScope)
LoadUnitValueInstruction(element as KtExpression, blockScope)
}
@@ -41,25 +41,25 @@ sealed class AccessTarget {
abstract class AccessValueInstruction protected constructor(
element: KtElement,
lexicalScope: LexicalScope,
blockScope: BlockScope,
val target: AccessTarget,
override val receiverValues: Map<PseudoValue, ReceiverValue>
) : InstructionWithNext(element, lexicalScope), InstructionWithReceivers
) : InstructionWithNext(element, blockScope), InstructionWithReceivers
class ReadValueInstruction private constructor(
element: KtElement,
lexicalScope: LexicalScope,
blockScope: BlockScope,
target: AccessTarget,
receiverValues: Map<PseudoValue, ReceiverValue>,
private var _outputValue: PseudoValue?
) : AccessValueInstruction(element, lexicalScope, target, receiverValues), InstructionWithValue {
) : AccessValueInstruction(element, blockScope, target, receiverValues), InstructionWithValue {
constructor(
element: KtElement,
lexicalScope: LexicalScope,
blockScope: BlockScope,
target: AccessTarget,
receiverValues: Map<PseudoValue, ReceiverValue>,
factory: PseudoValueFactory
): this(element, lexicalScope, target, receiverValues, null) {
): this(element, blockScope, target, receiverValues, null) {
_outputValue = factory.newValue(element, this)
}
@@ -91,17 +91,17 @@ class ReadValueInstruction private constructor(
}
override fun createCopy(): InstructionImpl =
ReadValueInstruction(element, lexicalScope, target, receiverValues, outputValue)
ReadValueInstruction(element, blockScope, target, receiverValues, outputValue)
}
class WriteValueInstruction(
assignment: KtElement,
lexicalScope: LexicalScope,
blockScope: BlockScope,
target: AccessTarget,
receiverValues: Map<PseudoValue, ReceiverValue>,
val lValue: KtElement,
val rValue: PseudoValue
) : AccessValueInstruction(assignment, lexicalScope, target, receiverValues) {
) : AccessValueInstruction(assignment, blockScope, target, receiverValues) {
override val inputValues: List<PseudoValue>
get() = (receiverValues.keys as Collection<PseudoValue>) + rValue
@@ -119,5 +119,5 @@ class WriteValueInstruction(
}
override fun createCopy(): InstructionImpl =
WriteValueInstruction(element, lexicalScope, target, receiverValues, lValue, rValue)
WriteValueInstruction(element, blockScope, target, receiverValues, lValue, rValue)
}
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.cfg.pseudocode.TypePredicate
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitor
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitorWithResult
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionWithNext
import org.jetbrains.kotlin.cfg.pseudocode.instructions.LexicalScope
import org.jetbrains.kotlin.cfg.pseudocode.instructions.BlockScope
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
@@ -30,9 +30,9 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
abstract class OperationInstruction protected constructor(
element: KtElement,
lexicalScope: LexicalScope,
blockScope: BlockScope,
override val inputValues: List<PseudoValue>
) : InstructionWithNext(element, lexicalScope), InstructionWithValue {
) : InstructionWithNext(element, blockScope), InstructionWithValue {
protected var resultValue: PseudoValue? = null
override val outputValue: PseudoValue?
@@ -55,20 +55,20 @@ abstract class OperationInstruction protected constructor(
class CallInstruction private constructor(
element: KtElement,
lexicalScope: LexicalScope,
blockScope: BlockScope,
val resolvedCall: ResolvedCall<*>,
override val receiverValues: Map<PseudoValue, ReceiverValue>,
val arguments: Map<PseudoValue, ValueParameterDescriptor>
) : OperationInstruction(element, lexicalScope, (receiverValues.keys as Collection<PseudoValue>) + arguments.keys), InstructionWithReceivers {
) : OperationInstruction(element, blockScope, (receiverValues.keys as Collection<PseudoValue>) + arguments.keys), InstructionWithReceivers {
constructor (
element: KtElement,
lexicalScope: LexicalScope,
blockScope: BlockScope,
resolvedCall: ResolvedCall<*>,
receiverValues: Map<PseudoValue, ReceiverValue>,
arguments: Map<PseudoValue, ValueParameterDescriptor>,
factory: PseudoValueFactory?
): this(element, lexicalScope, resolvedCall, receiverValues, arguments) {
): this(element, blockScope, resolvedCall, receiverValues, arguments) {
setResult(factory)
}
@@ -81,7 +81,7 @@ class CallInstruction private constructor(
}
override fun createCopy() =
CallInstruction(element, lexicalScope, resolvedCall, receiverValues, arguments).setResult(resultValue)
CallInstruction(element, blockScope, resolvedCall, receiverValues, arguments).setResult(resultValue)
override fun toString() =
renderInstruction("call", "${render(element)}, ${resolvedCall.resultingDescriptor!!.name}")
@@ -94,18 +94,18 @@ class CallInstruction private constructor(
// pass more than one value to instruction which formally requires only one (e.g. jump)
class MagicInstruction(
element: KtElement,
lexicalScope: LexicalScope,
blockScope: BlockScope,
inputValues: List<PseudoValue>,
val kind: MagicKind
) : OperationInstruction(element, lexicalScope, inputValues) {
) : OperationInstruction(element, blockScope, inputValues) {
constructor (
element: KtElement,
valueElement: KtElement?,
lexicalScope: LexicalScope,
blockScope: BlockScope,
inputValues: List<PseudoValue>,
kind: MagicKind,
factory: PseudoValueFactory
): this(element, lexicalScope, inputValues, kind) {
): this(element, blockScope, inputValues, kind) {
setResult(factory, valueElement)
}
@@ -119,7 +119,7 @@ class MagicInstruction(
override fun <R> accept(visitor: InstructionVisitorWithResult<R>): R = visitor.visitMagic(this)
override fun createCopy() =
MagicInstruction(element, lexicalScope, inputValues, kind).setResult(resultValue)
MagicInstruction(element, blockScope, inputValues, kind).setResult(resultValue)
override fun toString() = renderInstruction("magic[$kind]", render(element))
}
@@ -149,15 +149,15 @@ enum class MagicKind(val sideEffectFree: Boolean = false) {
// Merges values produced by alternative control-flow paths (such as 'if' branches)
class MergeInstruction private constructor(
element: KtElement,
lexicalScope: LexicalScope,
blockScope: BlockScope,
inputValues: List<PseudoValue>
): OperationInstruction(element, lexicalScope, inputValues) {
): OperationInstruction(element, blockScope, inputValues) {
constructor (
element: KtElement,
lexicalScope: LexicalScope,
blockScope: BlockScope,
inputValues: List<PseudoValue>,
factory: PseudoValueFactory
): this(element, lexicalScope, inputValues) {
): this(element, blockScope, inputValues) {
setResult(factory)
}
@@ -168,7 +168,7 @@ class MergeInstruction private constructor(
override fun <R> accept(visitor: InstructionVisitorWithResult<R>): R = visitor.visitMerge(this)
override fun createCopy() = MergeInstruction(element, lexicalScope, inputValues).setResult(resultValue)
override fun createCopy() = MergeInstruction(element, blockScope, inputValues).setResult(resultValue)
override fun toString() = renderInstruction("merge", render(element))
}
@@ -18,7 +18,7 @@ package org.jetbrains.kotlin.cfg.pseudocode.instructions.jumps
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.cfg.Label
import org.jetbrains.kotlin.cfg.pseudocode.instructions.LexicalScope
import org.jetbrains.kotlin.cfg.pseudocode.instructions.BlockScope
import org.jetbrains.kotlin.cfg.pseudocode.instructions.KtElementInstructionImpl
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionImpl
import org.jetbrains.kotlin.cfg.pseudocode.instructions.Instruction
@@ -27,21 +27,21 @@ import org.jetbrains.kotlin.utils.emptyOrSingletonList
abstract class AbstractJumpInstruction(
element: KtElement,
val targetLabel: Label,
lexicalScope: LexicalScope
) : KtElementInstructionImpl(element, lexicalScope), JumpInstruction {
blockScope: BlockScope
) : KtElementInstructionImpl(element, blockScope), JumpInstruction {
var resolvedTarget: Instruction? = null
set(value: Instruction?) {
field = outgoingEdgeTo(value)
}
protected abstract fun createCopy(newLabel: Label, lexicalScope: LexicalScope): AbstractJumpInstruction
protected abstract fun createCopy(newLabel: Label, blockScope: BlockScope): AbstractJumpInstruction
fun copy(newLabel: Label): Instruction {
return updateCopyInfo(createCopy(newLabel, lexicalScope))
return updateCopyInfo(createCopy(newLabel, blockScope))
}
override fun createCopy(): InstructionImpl {
return createCopy(targetLabel, lexicalScope)
return createCopy(targetLabel, blockScope)
}
override val nextInstructions: Collection<Instruction>
@@ -20,7 +20,7 @@ import org.jetbrains.kotlin.cfg.pseudocode.PseudoValue
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.cfg.Label
import java.util.Arrays
import org.jetbrains.kotlin.cfg.pseudocode.instructions.LexicalScope
import org.jetbrains.kotlin.cfg.pseudocode.instructions.BlockScope
import org.jetbrains.kotlin.cfg.pseudocode.instructions.Instruction
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitorWithResult
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitor
@@ -29,9 +29,9 @@ import org.jetbrains.kotlin.utils.emptyOrSingletonList
class ConditionalJumpInstruction(
element: KtElement,
val onTrue: Boolean,
lexicalScope: LexicalScope,
blockScope: BlockScope,
targetLabel: Label,
val conditionValue: PseudoValue?) : AbstractJumpInstruction(element, targetLabel, lexicalScope) {
val conditionValue: PseudoValue?) : AbstractJumpInstruction(element, targetLabel, blockScope) {
private var _nextOnTrue: Instruction? = null
private var _nextOnFalse: Instruction? = null
@@ -67,6 +67,6 @@ class ConditionalJumpInstruction(
return "$instr(${targetLabel.name}$inValue)"
}
override fun createCopy(newLabel: Label, lexicalScope: LexicalScope): AbstractJumpInstruction =
ConditionalJumpInstruction(element, onTrue, lexicalScope, newLabel, conditionValue)
override fun createCopy(newLabel: Label, blockScope: BlockScope): AbstractJumpInstruction =
ConditionalJumpInstruction(element, onTrue, blockScope, newLabel, conditionValue)
}
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.cfg.Label
import com.google.common.collect.Maps
import com.google.common.collect.Lists
import org.jetbrains.kotlin.cfg.pseudocode.instructions.LexicalScope
import org.jetbrains.kotlin.cfg.pseudocode.instructions.BlockScope
import org.jetbrains.kotlin.cfg.pseudocode.instructions.KtElementInstructionImpl
import org.jetbrains.kotlin.cfg.pseudocode.instructions.Instruction
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitor
@@ -32,9 +32,9 @@ import org.jetbrains.kotlin.utils.emptyOrSingletonList
class NondeterministicJumpInstruction(
element: KtElement,
targetLabels: List<Label>,
lexicalScope: LexicalScope,
blockScope: BlockScope,
val inputValue: PseudoValue?
) : KtElementInstructionImpl(element, lexicalScope), JumpInstruction {
) : KtElementInstructionImpl(element, blockScope), JumpInstruction {
private var _next: Instruction? = null
private val _resolvedTargets: MutableMap<Label, Instruction> = Maps.newLinkedHashMap()
@@ -85,6 +85,6 @@ class NondeterministicJumpInstruction(
}
private fun createCopy(newTargetLabels: List<Label>): InstructionImpl {
return NondeterministicJumpInstruction(element, newTargetLabels, lexicalScope, inputValue)
return NondeterministicJumpInstruction(element, newTargetLabels, blockScope, inputValue)
}
}
@@ -18,15 +18,15 @@ package org.jetbrains.kotlin.cfg.pseudocode.instructions.jumps
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.cfg.Label
import org.jetbrains.kotlin.cfg.pseudocode.instructions.LexicalScope
import org.jetbrains.kotlin.cfg.pseudocode.instructions.BlockScope
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitor
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitorWithResult
class ReturnNoValueInstruction(
element: KtElement,
lexicalScope: LexicalScope,
blockScope: BlockScope,
targetLabel: Label
) : AbstractJumpInstruction(element, targetLabel, lexicalScope) {
) : AbstractJumpInstruction(element, targetLabel, blockScope) {
override fun accept(visitor: InstructionVisitor) {
visitor.visitReturnNoValue(this)
}
@@ -37,6 +37,6 @@ class ReturnNoValueInstruction(
override fun toString(): String = "ret $targetLabel"
override fun createCopy(newLabel: Label, lexicalScope: LexicalScope): AbstractJumpInstruction =
ReturnNoValueInstruction(element, lexicalScope, newLabel)
override fun createCopy(newLabel: Label, blockScope: BlockScope): AbstractJumpInstruction =
ReturnNoValueInstruction(element, blockScope, newLabel)
}
@@ -20,17 +20,17 @@ import org.jetbrains.kotlin.cfg.pseudocode.PseudoValue
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.cfg.Label
import java.util.Collections
import org.jetbrains.kotlin.cfg.pseudocode.instructions.LexicalScope
import org.jetbrains.kotlin.cfg.pseudocode.instructions.BlockScope
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitor
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitorWithResult
import org.jetbrains.kotlin.psi.KtReturnExpression
class ReturnValueInstruction(
returnExpression: KtExpression,
lexicalScope: LexicalScope,
blockScope: BlockScope,
targetLabel: Label,
val returnedValue: PseudoValue
) : AbstractJumpInstruction(returnExpression, targetLabel, lexicalScope) {
) : AbstractJumpInstruction(returnExpression, targetLabel, blockScope) {
override val inputValues: List<PseudoValue> get() = Collections.singletonList(returnedValue)
override fun accept(visitor: InstructionVisitor) {
@@ -45,8 +45,8 @@ class ReturnValueInstruction(
return "ret(*|$returnedValue) $targetLabel"
}
override fun createCopy(newLabel: Label, lexicalScope: LexicalScope): AbstractJumpInstruction {
return ReturnValueInstruction((element as KtExpression), lexicalScope, newLabel, returnedValue)
override fun createCopy(newLabel: Label, blockScope: BlockScope): AbstractJumpInstruction {
return ReturnValueInstruction((element as KtExpression), blockScope, newLabel, returnedValue)
}
val returnExpressionIfAny: KtReturnExpression? = element as? KtReturnExpression
@@ -20,16 +20,16 @@ import org.jetbrains.kotlin.cfg.pseudocode.PseudoValue
import org.jetbrains.kotlin.psi.KtThrowExpression
import org.jetbrains.kotlin.cfg.Label
import java.util.Collections
import org.jetbrains.kotlin.cfg.pseudocode.instructions.LexicalScope
import org.jetbrains.kotlin.cfg.pseudocode.instructions.BlockScope
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitor
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitorWithResult
class ThrowExceptionInstruction(
expression: KtThrowExpression,
lexicalScope: LexicalScope,
blockScope: BlockScope,
errorLabel: Label,
val thrownValue: PseudoValue
) : AbstractJumpInstruction(expression, errorLabel, lexicalScope) {
) : AbstractJumpInstruction(expression, errorLabel, blockScope) {
override val inputValues: List<PseudoValue> get() = Collections.singletonList(thrownValue)
override fun accept(visitor: InstructionVisitor) {
@@ -44,7 +44,7 @@ class ThrowExceptionInstruction(
return "throw (${element.text}|$thrownValue)"
}
override fun createCopy(newLabel: Label, lexicalScope: LexicalScope): AbstractJumpInstruction {
return ThrowExceptionInstruction((element as KtThrowExpression), lexicalScope, newLabel, thrownValue)
override fun createCopy(newLabel: Label, blockScope: BlockScope): AbstractJumpInstruction {
return ThrowExceptionInstruction((element as KtThrowExpression), blockScope, newLabel, thrownValue)
}
}
@@ -23,8 +23,8 @@ import org.jetbrains.kotlin.cfg.Label
class UnconditionalJumpInstruction(
element: KtElement,
targetLabel: Label,
lexicalScope: LexicalScope
) : AbstractJumpInstruction(element, targetLabel, lexicalScope) {
blockScope: BlockScope
) : AbstractJumpInstruction(element, targetLabel, blockScope) {
override fun accept(visitor: InstructionVisitor) {
visitor.visitUnconditionalJump(this)
}
@@ -35,6 +35,6 @@ class UnconditionalJumpInstruction(
override fun toString(): String = "jmp(${targetLabel.name})"
override fun createCopy(newLabel: Label, lexicalScope: LexicalScope): AbstractJumpInstruction =
UnconditionalJumpInstruction(element, newLabel, lexicalScope)
override fun createCopy(newLabel: Label, blockScope: BlockScope): AbstractJumpInstruction =
UnconditionalJumpInstruction(element, newLabel, blockScope)
}
@@ -19,7 +19,7 @@ package org.jetbrains.kotlin.cfg.pseudocode.instructions.special
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.cfg.pseudocode.Pseudocode
import com.google.common.collect.Lists
import org.jetbrains.kotlin.cfg.pseudocode.instructions.LexicalScope
import org.jetbrains.kotlin.cfg.pseudocode.instructions.BlockScope
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionWithNext
import org.jetbrains.kotlin.cfg.pseudocode.instructions.Instruction
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitor
@@ -29,8 +29,8 @@ import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionImpl
class LocalFunctionDeclarationInstruction(
element: KtElement,
val body: Pseudocode,
lexicalScope: LexicalScope
) : InstructionWithNext(element, lexicalScope) {
blockScope: BlockScope
) : InstructionWithNext(element, blockScope) {
var sink: SubroutineSinkInstruction? = null
set(value: SubroutineSinkInstruction?) {
field = outgoingEdgeTo(value) as SubroutineSinkInstruction?
@@ -57,5 +57,5 @@ class LocalFunctionDeclarationInstruction(
override fun toString(): String = "d(${render(element)})"
override fun createCopy(): InstructionImpl =
LocalFunctionDeclarationInstruction(element, body.copy(), lexicalScope)
LocalFunctionDeclarationInstruction(element, body.copy(), blockScope)
}
@@ -17,15 +17,15 @@
package org.jetbrains.kotlin.cfg.pseudocode.instructions.special
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.cfg.pseudocode.instructions.LexicalScope
import org.jetbrains.kotlin.cfg.pseudocode.instructions.BlockScope
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionWithNext
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitor
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitorWithResult
class MarkInstruction(
element: KtElement,
lexicalScope: LexicalScope
) : InstructionWithNext(element, lexicalScope) {
blockScope: BlockScope
) : InstructionWithNext(element, blockScope) {
override fun accept(visitor: InstructionVisitor) {
visitor.visitMarkInstruction(this)
@@ -35,7 +35,7 @@ class MarkInstruction(
return visitor.visitMarkInstruction(this)
}
override fun createCopy() = MarkInstruction(element, lexicalScope)
override fun createCopy() = MarkInstruction(element, blockScope)
override fun toString() = "mark(${render(element)})"
}
@@ -17,7 +17,7 @@
package org.jetbrains.kotlin.cfg.pseudocode.instructions.special
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.cfg.pseudocode.instructions.LexicalScope
import org.jetbrains.kotlin.cfg.pseudocode.instructions.BlockScope
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionWithNext
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitor
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitorWithResult
@@ -25,8 +25,8 @@ import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionImpl
class SubroutineEnterInstruction(
val subroutine: KtElement,
lexicalScope: LexicalScope
) : InstructionWithNext(subroutine, lexicalScope) {
blockScope: BlockScope
) : InstructionWithNext(subroutine, blockScope) {
override fun accept(visitor: InstructionVisitor) {
visitor.visitSubroutineEnter(this)
}
@@ -38,5 +38,5 @@ class SubroutineEnterInstruction(
override fun toString(): String = "<START>"
override fun createCopy(): InstructionImpl =
SubroutineEnterInstruction(subroutine, lexicalScope)
SubroutineEnterInstruction(subroutine, blockScope)
}
@@ -22,9 +22,9 @@ import java.util.*
class SubroutineExitInstruction(
val subroutine: KtElement,
lexicalScope: LexicalScope,
blockScope: BlockScope,
val isError: Boolean
) : InstructionImpl(lexicalScope) {
) : InstructionImpl(blockScope) {
private var _sink: SubroutineSinkInstruction? = null
var sink: SubroutineSinkInstruction
@@ -47,5 +47,5 @@ class SubroutineExitInstruction(
override fun toString(): String = if (isError) "<ERROR>" else "<END>"
override fun createCopy(): InstructionImpl =
SubroutineExitInstruction(subroutine, lexicalScope, isError)
SubroutineExitInstruction(subroutine, blockScope, isError)
}
@@ -18,7 +18,7 @@ package org.jetbrains.kotlin.cfg.pseudocode.instructions.special
import org.jetbrains.kotlin.psi.KtElement
import java.util.Collections
import org.jetbrains.kotlin.cfg.pseudocode.instructions.LexicalScope
import org.jetbrains.kotlin.cfg.pseudocode.instructions.BlockScope
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionImpl
import org.jetbrains.kotlin.cfg.pseudocode.instructions.Instruction
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitor
@@ -26,8 +26,8 @@ import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitorWithRe
class SubroutineSinkInstruction(
val subroutine: KtElement,
lexicalScope: LexicalScope,
private val debugLabel: String) : InstructionImpl(lexicalScope) {
blockScope: BlockScope,
private val debugLabel: String) : InstructionImpl(blockScope) {
override val nextInstructions: Collection<Instruction>
get() = Collections.emptyList()
@@ -42,5 +42,5 @@ class SubroutineSinkInstruction(
override fun toString(): String = debugLabel
override fun createCopy(): InstructionImpl =
SubroutineSinkInstruction(subroutine, lexicalScope, debugLabel)
SubroutineSinkInstruction(subroutine, blockScope, debugLabel)
}
@@ -20,15 +20,15 @@ import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtVariableDeclaration
import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionWithNext
import org.jetbrains.kotlin.cfg.pseudocode.instructions.LexicalScope
import org.jetbrains.kotlin.cfg.pseudocode.instructions.BlockScope
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitor
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitorWithResult
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionImpl
class VariableDeclarationInstruction(
element: KtDeclaration,
lexicalScope: LexicalScope
) : InstructionWithNext(element, lexicalScope) {
blockScope: BlockScope
) : InstructionWithNext(element, blockScope) {
init {
assert(element is KtVariableDeclaration || element is KtParameter) { "Invalid element: ${render(element)}}" }
}
@@ -47,5 +47,5 @@ class VariableDeclarationInstruction(
override fun toString(): String = "v(${render(element)})"
override fun createCopy(): InstructionImpl =
VariableDeclarationInstruction(variableDeclarationElement, lexicalScope)
VariableDeclarationInstruction(variableDeclarationElement, blockScope)
}
@@ -147,8 +147,8 @@ public abstract class AbstractPseudocodeTest extends KotlinTestWithEnvironment {
}
private static String getDepthInstructionPrefix(@NotNull Instruction instruction, @Nullable Instruction previous) {
Integer prevDepth = previous != null ? previous.getLexicalScope().getDepth() : null;
int depth = instruction.getLexicalScope().getDepth();
Integer prevDepth = previous != null ? previous.getBlockScope().getDepth() : null;
int depth = instruction.getBlockScope().getDepth();
if (prevDepth == null || depth != prevDepth) {
return String.format("%2d ", depth);
}