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