diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java index e57e1974596..a2b174491a0 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java @@ -65,7 +65,7 @@ public class PseudocodeTraverser { SKIP_LOCAL_DECLARATIONS } - protected static boolean shouldLookInside(Instruction instruction, LookInsideStrategy lookInside) { + public static boolean shouldLookInside(Instruction instruction, LookInsideStrategy lookInside) { return lookInside == LookInsideStrategy.ANALYSE_LOCAL_DECLARATIONS && instruction instanceof LocalFunctionDeclarationInstruction; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariableDataCollector.kt b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariableDataCollector.kt index 5f5797f477c..2684fc8c715 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariableDataCollector.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariableDataCollector.kt @@ -19,19 +19,22 @@ package org.jetbrains.jet.lang.cfg import org.jetbrains.jet.lang.cfg.pseudocode.Instruction import org.jetbrains.jet.lang.cfg.pseudocode.LocalFunctionDeclarationInstruction import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode -import org.jetbrains.jet.lang.descriptors.FunctionDescriptor import org.jetbrains.jet.lang.descriptors.VariableDescriptor -import org.jetbrains.jet.lang.psi.JetElement import org.jetbrains.jet.lang.resolve.BindingContext -import org.jetbrains.jet.lang.resolve.DescriptorUtils import org.jetbrains.jet.lang.cfg.PseudocodeTraverser.* +import org.jetbrains.jet.lang.cfg.pseudocode.LexicalScope +import org.jetbrains.jet.lang.cfg.pseudocode.VariableDeclarationInstruction +import org.jetbrains.jet.utils.addToStdlib.* + +import kotlin.properties.Delegates import java.util.* public class PseudocodeVariableDataCollector( private val bindingContext: BindingContext, private val pseudocode: Pseudocode -) : PseudocodeTraverser() { +) { + val lexicalScopeVariableInfo = computeLexicalScopeVariableInfo(pseudocode) suppress("UNCHECKED_CAST") public fun collectDataJ( @@ -118,9 +121,13 @@ public class PseudocodeVariableDataCollector( val lastInstruction = getLastInstruction(subroutinePseudocode, traversalOrder) val previousValue = edgesMap.get(instruction) val newValue = edgesMap.get(lastInstruction) - if (previousValue != newValue && newValue != null) { + val updatedValue = if (newValue == null) null else + Edges.create( + filterOutVariablesOutOfScope(lastInstruction, instruction, newValue.`in`), + filterOutVariablesOutOfScope(lastInstruction, instruction, newValue.out)) + if (previousValue != updatedValue && updatedValue != null) { changed[0] = true - edgesMap.put(instruction, newValue) + edgesMap.put(instruction, updatedValue) } continue } @@ -131,7 +138,8 @@ public class PseudocodeVariableDataCollector( for (previousInstruction in allPreviousInstructions) { val previousData = edgesMap.get(previousInstruction) if (previousData != null) { - incomingEdgesData.add(previousData.out) + incomingEdgesData.add(filterOutVariablesOutOfScope( + previousInstruction, instruction, previousData.out)) } } val mergedData = instructionDataMergeStrategy.execute(instruction, incomingEdgesData) @@ -141,4 +149,55 @@ public class PseudocodeVariableDataCollector( } } } + + private fun filterOutVariablesOutOfScope( + from: Instruction, + to: Instruction, + data: Map + ): Map { + // 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.getLexicalScope().depth + if (toDepth >= from.getLexicalScope().depth) return data + + // 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. + return data.filterKeys { variable -> + val lexicalScope = lexicalScopeVariableInfo.declaredIn[variable] + // '-1' for variables declared outside this pseudocode + val depth = lexicalScope?.depth ?: -1 + depth <= toDepth + } + } + + fun computeLexicalScopeVariableInfo(pseudocode: Pseudocode): LexicalScopeVariableInfo { + val lexicalScopeVariableInfo = LexicalScopeVariableInfoImpl() + PseudocodeTraverser.traverse(pseudocode, TraversalOrder.FORWARD, { instruction -> + if (instruction is VariableDeclarationInstruction) { + val variableDeclarationElement = instruction.getVariableDeclarationElement() + val descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, variableDeclarationElement) + assert(descriptor is VariableDescriptor, + "Variable descriptor should correspond to the instruction for ${instruction.getElement().getText()}.\n" + + "Descriptor : $descriptor") + lexicalScopeVariableInfo.registerVariableDeclaredInScope( + descriptor as VariableDescriptor, instruction.getLexicalScope()) + } + }) + return lexicalScopeVariableInfo + } +} + +public trait LexicalScopeVariableInfo { + val declaredIn : Map + val scopeVariables : Map> +} + +public class LexicalScopeVariableInfoImpl : LexicalScopeVariableInfo { + override val declaredIn = HashMap() + override val scopeVariables = HashMap>() + + fun registerVariableDeclaredInScope(variable: VariableDescriptor, lexicalScope: LexicalScope) { + declaredIn[variable] = lexicalScope + val variablesInScope = scopeVariables.getOrPut(lexicalScope, { ArrayList() }) + variablesInScope.add(variable) + } } diff --git a/compiler/testData/cfg-variables/basic/IfWithUninitialized.instructions b/compiler/testData/cfg-variables/basic/IfWithUninitialized.instructions index a294760d9b9..b5dee6bccb9 100644 --- a/compiler/testData/cfg-variables/basic/IfWithUninitialized.instructions +++ b/compiler/testData/cfg-variables/basic/IfWithUninitialized.instructions @@ -10,7 +10,7 @@ fun foo() { } --------------------- L0: - 1 INIT: in: {} out: {} + 1 INIT: in: {} out: {} USE: in: {} out: {} 2 mark({ val b: Boolean if (1 < 2) { use(b) } else { b = true } }) v(val b: Boolean) INIT: in: {} out: {b=D} mark(if (1 < 2) { use(b) } else { b = true }) INIT: in: {b=D} out: {b=D} @@ -30,11 +30,11 @@ L2: w(b) INIT: in: {b=D} out: {b=ID} USE: in: {} out: {b=ONLY_WRITTEN_NEVER_READ} L1: L3: - 1 INIT: in: {b=D} out: {b=D} + 1 INIT: in: {} out: {} error: - INIT: in: {} out: {} + sink: - INIT: in: {b=D} out: {b=D} USE: in: {} out: {} + USE: in: {} out: {} ===================== == use == fun use(vararg a: Any?) = a diff --git a/compiler/testData/cfg-variables/basic/UsageInFunctionLiteral.instructions b/compiler/testData/cfg-variables/basic/UsageInFunctionLiteral.instructions index 456697979a0..2c682b98d02 100644 --- a/compiler/testData/cfg-variables/basic/UsageInFunctionLiteral.instructions +++ b/compiler/testData/cfg-variables/basic/UsageInFunctionLiteral.instructions @@ -8,7 +8,7 @@ fun foo() { } --------------------- L0: - 1 INIT: in: {} out: {} + 1 INIT: in: {} out: {} USE: in: {} out: {} 2 mark({ val a = 1 val f = { (x: Int) -> val y = x + a use(a) } }) v(val a = 1) INIT: in: {} out: {a=D} r(1) INIT: in: {a=D} out: {a=D} @@ -16,16 +16,16 @@ L0: v(val f = { (x: Int) -> val y = x + a use(a) }) INIT: in: {a=ID} out: {a=ID, f=D} mark({ (x: Int) -> val y = x + a use(a) }) INIT: in: {a=ID, f=D} out: {a=ID, f=D} jmp?(L2) - d({ (x: Int) -> val y = x + a use(a) }) INIT: in: {a=ID, f=D, x=ID, y=ID} out: {a=ID, f=D, x=ID, y=ID} USE: in: {a=READ, x=READ} out: {a=READ, x=READ} + d({ (x: Int) -> val y = x + a use(a) }) USE: in: {a=READ} out: {a=READ} L2: - r({ (x: Int) -> val y = x + a use(a) }) INIT: in: {a=ID, f=D} out: {a=ID, f=D} + r({ (x: Int) -> val y = x + a use(a) }) w(f) INIT: in: {a=ID, f=D} out: {a=ID, f=ID} L1: - 1 INIT: in: {a=ID, f=ID} out: {a=ID, f=ID} + 1 INIT: in: {} out: {} error: - INIT: in: {} out: {} + sink: - INIT: in: {a=ID, f=D, x=ID, y=ID} out: {a=ID, f=D, x=ID, y=ID} USE: in: {} out: {} + USE: in: {} out: {} ===================== == anonymous_0 == { (x: Int) -> @@ -48,11 +48,11 @@ L3: r(a) USE: in: {} out: {a=READ} call(use, use) L4: - 3 + 3 INIT: in: {a=ID, f=D, x=ID} out: {a=ID, f=D, x=ID} error: INIT: in: {} out: {} sink: - INIT: in: {a=ID, f=D, x=ID, y=ID} out: {a=ID, f=D, x=ID, y=ID} USE: in: {} out: {} + INIT: in: {a=ID, f=D, x=ID} out: {a=ID, f=D, x=ID} USE: in: {} out: {} ===================== == use == fun use(vararg a: Any?) = a diff --git a/compiler/testData/cfg-variables/basic/VariablesInitialization.instructions b/compiler/testData/cfg-variables/basic/VariablesInitialization.instructions index c064769b6f9..cc0447ffe18 100644 --- a/compiler/testData/cfg-variables/basic/VariablesInitialization.instructions +++ b/compiler/testData/cfg-variables/basic/VariablesInitialization.instructions @@ -7,7 +7,7 @@ fun foo() { } --------------------- L0: - 1 INIT: in: {} out: {} + 1 INIT: in: {} out: {} USE: in: {} out: {} 2 mark({ val a = 1 val b: Int b = 2 42 }) v(val a = 1) INIT: in: {} out: {a=D} r(1) INIT: in: {a=D} out: {a=D} @@ -17,11 +17,11 @@ L0: w(b) INIT: in: {a=ID, b=D} out: {a=ID, b=ID} USE: in: {} out: {b=ONLY_WRITTEN_NEVER_READ} r(42) INIT: in: {a=ID, b=ID} out: {a=ID, b=ID} L1: - 1 + 1 INIT: in: {} out: {} error: - INIT: in: {} out: {} + sink: - INIT: in: {a=ID, b=ID} out: {a=ID, b=ID} USE: in: {} out: {} + USE: in: {} out: {} ===================== == bar == fun bar(foo: Foo) { diff --git a/compiler/testData/cfg-variables/basic/VariablesUsage.instructions b/compiler/testData/cfg-variables/basic/VariablesUsage.instructions index ec39747c79b..0c2c765077d 100644 --- a/compiler/testData/cfg-variables/basic/VariablesUsage.instructions +++ b/compiler/testData/cfg-variables/basic/VariablesUsage.instructions @@ -7,7 +7,7 @@ fun foo() { } --------------------- L0: - 1 INIT: in: {} out: {} + 1 INIT: in: {} out: {} USE: in: {} out: {} 2 mark({ var a = 1 use(a) a = 2 use(a) }) v(var a = 1) INIT: in: {} out: {a=D} r(1) INIT: in: {a=D} out: {a=D} @@ -21,11 +21,11 @@ L0: r(a) USE: in: {} out: {a=READ} call(use, use) L1: - 1 + 1 INIT: in: {} out: {} error: - INIT: in: {} out: {} + sink: - INIT: in: {a=ID} out: {a=ID} USE: in: {} out: {} + USE: in: {} out: {} ===================== == bar == fun bar() { @@ -34,17 +34,17 @@ fun bar() { } --------------------- L0: - 1 INIT: in: {} out: {} + 1 INIT: in: {} out: {} USE: in: {} out: {} 2 mark({ val b: Int b = 3 }) v(val b: Int) INIT: in: {} out: {b=D} - r(3) INIT: in: {b=D} out: {b=D} USE: in: {b=ONLY_WRITTEN_NEVER_READ} out: {b=ONLY_WRITTEN_NEVER_READ} - w(b) INIT: in: {b=D} out: {b=ID} USE: in: {} out: {b=ONLY_WRITTEN_NEVER_READ} + r(3) INIT: in: {b=D} out: {b=D} USE: in: {b=ONLY_WRITTEN_NEVER_READ} out: {b=ONLY_WRITTEN_NEVER_READ} + w(b) INIT: in: {b=D} out: {b=ID} USE: in: {} out: {b=ONLY_WRITTEN_NEVER_READ} L1: - 1 INIT: in: {b=ID} out: {b=ID} + 1 INIT: in: {} out: {} error: - INIT: in: {} out: {} + sink: - INIT: in: {b=ID} out: {b=ID} USE: in: {} out: {} + USE: in: {} out: {} ===================== == use == fun use(a: Int) = a diff --git a/compiler/testData/cfg-variables/lexicalScopes/doWhileScope.instructions b/compiler/testData/cfg-variables/lexicalScopes/doWhileScope.instructions index 891117eae2e..4bba63ecdff 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/doWhileScope.instructions +++ b/compiler/testData/cfg-variables/lexicalScopes/doWhileScope.instructions @@ -11,7 +11,7 @@ L0: 1 INIT: in: {} out: {} 2 mark({ "before" do { var a = 2 } while (a > 0) "after" }) mark("before") - r("before") + r("before") USE: in: {} out: {} 3 mark(do { var a = 2 } while (a > 0)) L2 [loop entry point]: L4 [body entry point]: @@ -27,12 +27,12 @@ L5 [condition entry point]: jt(L2 [loop entry point]) USE: in: {a=READ} out: {a=READ} L3 [loop exit point]: read (Unit) - 2 mark("after") + 2 mark("after") INIT: in: {} out: {} r("after") L1: 1 error: - INIT: in: {} out: {} + sink: - INIT: in: {a=ID} out: {a=ID} USE: in: {} out: {} + USE: in: {} out: {} ===================== diff --git a/compiler/testData/cfg-variables/lexicalScopes/forScope.instructions b/compiler/testData/cfg-variables/lexicalScopes/forScope.instructions index aeb4c2bb01c..d78a1b3932a 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/forScope.instructions +++ b/compiler/testData/cfg-variables/lexicalScopes/forScope.instructions @@ -11,7 +11,7 @@ L0: 1 INIT: in: {} out: {} 2 mark({ "before" for (i in 1..10) { val a = i } "after" }) mark("before") - r("before") + r("before") USE: in: {} out: {} 3 mark(for (i in 1..10) { val a = i }) mark(1..10) r(1) @@ -23,19 +23,19 @@ L3: jmp?(L2) INIT: in: {i=ID} out: {i=ID} L4 [loop entry point]: L5 [body entry point]: - 4 mark({ val a = i }) INIT: in: {a=ID, i=ID} out: {a=ID, i=ID} - v(val a = i) - r(i) - w(a) - 3 jmp?(L4 [loop entry point]) USE: in: {i=READ} out: {i=READ} + 4 mark({ val a = i }) + v(val a = i) INIT: in: {i=ID} out: {a=D, i=ID} + r(i) INIT: in: {a=D, i=ID} out: {a=D, i=ID} + w(a) INIT: in: {a=D, i=ID} out: {a=ID, i=ID} + 3 jmp?(L4 [loop entry point]) INIT: in: {i=ID} out: {i=ID} USE: in: {i=READ} out: {i=READ} L2: read (Unit) - 2 mark("after") + 2 mark("after") INIT: in: {} out: {} r("after") L1: 1 error: - INIT: in: {} out: {} + sink: - INIT: in: {a=ID, i=ID} out: {a=ID, i=ID} USE: in: {} out: {} + USE: in: {} out: {} ===================== diff --git a/compiler/testData/cfg-variables/lexicalScopes/functionLiteralScope.instructions b/compiler/testData/cfg-variables/lexicalScopes/functionLiteralScope.instructions index 0d78c540acc..de3a1b5783f 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/functionLiteralScope.instructions +++ b/compiler/testData/cfg-variables/lexicalScopes/functionLiteralScope.instructions @@ -9,7 +9,7 @@ fun foo() { } --------------------- L0: - 1 INIT: in: {} out: {} + 1 INIT: in: {} out: {} USE: in: {} out: {} 2 mark({ "before" val b = 1 val f = { (x: Int) -> val a = x + b } "after" }) mark("before") r("before") @@ -19,18 +19,18 @@ L0: v(val f = { (x: Int) -> val a = x + b }) INIT: in: {b=ID} out: {b=ID, f=D} mark({ (x: Int) -> val a = x + b }) INIT: in: {b=ID, f=D} out: {b=ID, f=D} jmp?(L2) - d({ (x: Int) -> val a = x + b }) INIT: in: {a=ID, b=ID, f=D, x=ID} out: {a=ID, b=ID, f=D, x=ID} USE: in: {b=READ, x=READ} out: {b=READ, x=READ} + d({ (x: Int) -> val a = x + b }) USE: in: {b=READ} out: {b=READ} L2: - r({ (x: Int) -> val a = x + b }) INIT: in: {b=ID, f=D} out: {b=ID, f=D} + r({ (x: Int) -> val a = x + b }) w(f) INIT: in: {b=ID, f=D} out: {b=ID, f=ID} mark("after") INIT: in: {b=ID, f=ID} out: {b=ID, f=ID} r("after") L1: - 1 + 1 INIT: in: {} out: {} error: - INIT: in: {} out: {} + sink: - INIT: in: {a=ID, b=ID, f=D, x=ID} out: {a=ID, b=ID, f=D, x=ID} USE: in: {} out: {} + USE: in: {} out: {} ===================== == anonymous_0 == { (x: Int) -> @@ -43,15 +43,15 @@ L3: w(x) INIT: in: {b=ID, f=D, x=D} out: {b=ID, f=D, x=ID} 4 mark(val a = x + b) INIT: in: {b=ID, f=D, x=ID} out: {b=ID, f=D, x=ID} v(val a = x + b) INIT: in: {b=ID, f=D, x=ID} out: {a=D, b=ID, f=D, x=ID} - mark(x + b) INIT: in: {a=D, b=ID, f=D, x=ID} out: {a=D, b=ID, f=D, x=ID} USE: in: {b=READ, x=READ} out: {b=READ, x=READ} - r(x) USE: in: {b=READ} out: {b=READ, x=READ} - r(b) USE: in: {} out: {b=READ} + mark(x + b) INIT: in: {a=D, b=ID, f=D, x=ID} out: {a=D, b=ID, f=D, x=ID} USE: in: {b=READ, x=READ} out: {b=READ, x=READ} + r(x) USE: in: {b=READ} out: {b=READ, x=READ} + r(b) USE: in: {} out: {b=READ} call(+, plus) w(a) INIT: in: {a=D, b=ID, f=D, x=ID} out: {a=ID, b=ID, f=D, x=ID} L4: - 3 INIT: in: {a=ID, b=ID, f=D, x=ID} out: {a=ID, b=ID, f=D, x=ID} + 3 INIT: in: {b=ID, f=D, x=ID} out: {b=ID, f=D, x=ID} error: INIT: in: {} out: {} sink: - INIT: in: {a=ID, b=ID, f=D, x=ID} out: {a=ID, b=ID, f=D, x=ID} USE: in: {} out: {} + INIT: in: {b=ID, f=D, x=ID} out: {b=ID, f=D, x=ID} USE: in: {} out: {} ===================== diff --git a/compiler/testData/cfg-variables/lexicalScopes/ifScope.instructions b/compiler/testData/cfg-variables/lexicalScopes/ifScope.instructions index bb9c40c699d..d3b59a53b20 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/ifScope.instructions +++ b/compiler/testData/cfg-variables/lexicalScopes/ifScope.instructions @@ -22,19 +22,19 @@ L0: v(val a = 1) INIT: in: {} out: {a=D} r(1) INIT: in: {a=D} out: {a=D} w(a) INIT: in: {a=D} out: {a=ID} - 2 jmp(L3) INIT: in: {a=ID} out: {a=ID} + 2 jmp(L3) INIT: in: {} out: {} L2: - 3 mark({ val b = 2 }) INIT: in: {} out: {} + 3 mark({ val b = 2 }) v(val b = 2) INIT: in: {} out: {b=D} r(2) INIT: in: {b=D} out: {b=D} w(b) INIT: in: {b=D} out: {b=ID} L3: - 2 mark("after") INIT: in: {a=ID, b=ID} out: {a=ID, b=ID} + 2 mark("after") INIT: in: {} out: {} r("after") L1: 1 error: - INIT: in: {} out: {} + sink: - INIT: in: {a=ID, b=ID} out: {a=ID, b=ID} USE: in: {} out: {} + USE: in: {} out: {} ===================== diff --git a/compiler/testData/cfg-variables/lexicalScopes/localClass.instructions b/compiler/testData/cfg-variables/lexicalScopes/localClass.instructions index 1cfe2b00aa4..37cac3519b8 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/localClass.instructions +++ b/compiler/testData/cfg-variables/lexicalScopes/localClass.instructions @@ -23,17 +23,17 @@ L0: v(val a = x) INIT: in: {x=ID} out: {a=D, x=ID} r(x) INIT: in: {a=D, x=ID} out: {a=D, x=ID} w(a) INIT: in: {a=D, x=ID} out: {a=ID, x=ID} - 2 jmp?(L2) INIT: in: {a=ID, x=ID} out: {a=ID, x=ID} - d(fun foo() { val b = x }) INIT: in: {a=ID, b=ID, x=ID} out: {a=ID, b=ID, x=ID} USE: in: {x=READ} out: {x=READ} + 2 jmp?(L2) INIT: in: {x=ID} out: {x=ID} + d(fun foo() { val b = x }) USE: in: {x=READ} out: {x=READ} L2: - mark("after") INIT: in: {a=ID, x=ID} out: {a=ID, x=ID} + mark("after") r("after") L1: - 1 + 1 INIT: in: {} out: {} error: - INIT: in: {} out: {} + sink: - INIT: in: {a=ID, b=ID, x=ID} out: {a=ID, b=ID, x=ID} USE: in: {} out: {} + USE: in: {} out: {} ===================== == foo == fun foo() { @@ -41,15 +41,15 @@ fun foo() { } --------------------- L3: - 3 INIT: in: {a=ID, x=ID} out: {a=ID, x=ID} + 3 INIT: in: {x=ID} out: {x=ID} 4 mark({ val b = x }) - v(val b = x) INIT: in: {a=ID, x=ID} out: {a=ID, b=D, x=ID} USE: in: {x=READ} out: {x=READ} - r(x) INIT: in: {a=ID, b=D, x=ID} out: {a=ID, b=D, x=ID} USE: in: {} out: {x=READ} - w(b) INIT: in: {a=ID, b=D, x=ID} out: {a=ID, b=ID, x=ID} + v(val b = x) INIT: in: {x=ID} out: {b=D, x=ID} USE: in: {x=READ} out: {x=READ} + r(x) INIT: in: {b=D, x=ID} out: {b=D, x=ID} USE: in: {} out: {x=READ} + w(b) INIT: in: {b=D, x=ID} out: {b=ID, x=ID} L4: - 3 INIT: in: {a=ID, b=ID, x=ID} out: {a=ID, b=ID, x=ID} + 3 INIT: in: {x=ID} out: {x=ID} error: INIT: in: {} out: {} sink: - INIT: in: {a=ID, b=ID, x=ID} out: {a=ID, b=ID, x=ID} USE: in: {} out: {} + INIT: in: {x=ID} out: {x=ID} USE: in: {} out: {} ===================== diff --git a/compiler/testData/cfg-variables/lexicalScopes/localFunctionScope.instructions b/compiler/testData/cfg-variables/lexicalScopes/localFunctionScope.instructions index 3f68ef0d30b..302b097e67b 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/localFunctionScope.instructions +++ b/compiler/testData/cfg-variables/lexicalScopes/localFunctionScope.instructions @@ -9,7 +9,7 @@ fun foo() { } --------------------- L0: - 1 INIT: in: {} out: {} + 1 INIT: in: {} out: {} USE: in: {} out: {} 2 mark({ "before" val b = 1 fun local(x: Int) { val a = x + b } "after" }) mark("before") r("before") @@ -17,16 +17,16 @@ L0: r(1) INIT: in: {b=D} out: {b=D} w(b) INIT: in: {b=D} out: {b=ID} jmp?(L2) INIT: in: {b=ID} out: {b=ID} - d(fun local(x: Int) { val a = x + b }) INIT: in: {a=ID, b=ID, x=ID} out: {a=ID, b=ID, x=ID} USE: in: {b=READ, x=READ} out: {b=READ, x=READ} + d(fun local(x: Int) { val a = x + b }) USE: in: {b=READ} out: {b=READ} L2: - mark("after") INIT: in: {b=ID} out: {b=ID} + mark("after") r("after") L1: - 1 + 1 INIT: in: {} out: {} error: - INIT: in: {} out: {} + sink: - INIT: in: {a=ID, b=ID, x=ID} out: {a=ID, b=ID, x=ID} USE: in: {} out: {} + USE: in: {} out: {} ===================== == local == fun local(x: Int) { @@ -39,15 +39,15 @@ L3: w(x) INIT: in: {b=ID, x=D} out: {b=ID, x=ID} 4 mark({ val a = x + b }) INIT: in: {b=ID, x=ID} out: {b=ID, x=ID} v(val a = x + b) INIT: in: {b=ID, x=ID} out: {a=D, b=ID, x=ID} - mark(x + b) INIT: in: {a=D, b=ID, x=ID} out: {a=D, b=ID, x=ID} USE: in: {b=READ, x=READ} out: {b=READ, x=READ} - r(x) USE: in: {b=READ} out: {b=READ, x=READ} - r(b) USE: in: {} out: {b=READ} + mark(x + b) INIT: in: {a=D, b=ID, x=ID} out: {a=D, b=ID, x=ID} USE: in: {b=READ, x=READ} out: {b=READ, x=READ} + r(x) USE: in: {b=READ} out: {b=READ, x=READ} + r(b) USE: in: {} out: {b=READ} call(+, plus) w(a) INIT: in: {a=D, b=ID, x=ID} out: {a=ID, b=ID, x=ID} L4: - 3 INIT: in: {a=ID, b=ID, x=ID} out: {a=ID, b=ID, x=ID} + 3 INIT: in: {b=ID, x=ID} out: {b=ID, x=ID} error: INIT: in: {} out: {} sink: - INIT: in: {a=ID, b=ID, x=ID} out: {a=ID, b=ID, x=ID} USE: in: {} out: {} + INIT: in: {b=ID, x=ID} out: {b=ID, x=ID} USE: in: {} out: {} ===================== diff --git a/compiler/testData/cfg-variables/lexicalScopes/localObject.instructions b/compiler/testData/cfg-variables/lexicalScopes/localObject.instructions index 433d51bd04b..1f8c916d409 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/localObject.instructions +++ b/compiler/testData/cfg-variables/lexicalScopes/localObject.instructions @@ -21,17 +21,17 @@ L0: v(val a = 1) INIT: in: {} out: {a=D} r(1) INIT: in: {a=D} out: {a=D} w(a) INIT: in: {a=D} out: {a=ID} - 2 jmp?(L2) INIT: in: {a=ID} out: {a=ID} - d(fun foo() { val b = 2 }) INIT: in: {a=ID, b=ID} out: {a=ID, b=ID} + 2 jmp?(L2) INIT: in: {} out: {} + d(fun foo() { val b = 2 }) L2: - mark("after") INIT: in: {a=ID} out: {a=ID} + mark("after") r("after") L1: 1 error: - INIT: in: {} out: {} + sink: - INIT: in: {a=ID, b=ID} out: {a=ID, b=ID} USE: in: {} out: {} + USE: in: {} out: {} ===================== == foo == fun foo() { @@ -39,15 +39,15 @@ fun foo() { } --------------------- L3: - 3 INIT: in: {a=ID} out: {a=ID} + 3 INIT: in: {} out: {} 4 mark({ val b = 2 }) - v(val b = 2) INIT: in: {a=ID} out: {a=ID, b=D} - r(2) INIT: in: {a=ID, b=D} out: {a=ID, b=D} - w(b) INIT: in: {a=ID, b=D} out: {a=ID, b=ID} + v(val b = 2) INIT: in: {} out: {b=D} + r(2) INIT: in: {b=D} out: {b=D} + w(b) INIT: in: {b=D} out: {b=ID} L4: - 3 INIT: in: {a=ID, b=ID} out: {a=ID, b=ID} + 3 INIT: in: {} out: {} error: - INIT: in: {} out: {} + sink: - INIT: in: {a=ID, b=ID} out: {a=ID, b=ID} USE: in: {} out: {} + USE: in: {} out: {} ===================== diff --git a/compiler/testData/cfg-variables/lexicalScopes/objectLiteralScope.instructions b/compiler/testData/cfg-variables/lexicalScopes/objectLiteralScope.instructions index 8ca2a2d055b..5ca5758f30b 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/objectLiteralScope.instructions +++ b/compiler/testData/cfg-variables/lexicalScopes/objectLiteralScope.instructions @@ -23,19 +23,19 @@ L0: v(val x = 1) INIT: in: {bar=D} out: {bar=D, x=D} r(1) INIT: in: {bar=D, x=D} out: {bar=D, x=D} w(x) INIT: in: {bar=D, x=D} out: {bar=D, x=ID} - 2 jmp?(L2) INIT: in: {bar=D, x=ID} out: {bar=D, x=ID} - d(fun foo() { val a = 2 }) INIT: in: {a=ID, bar=D, x=ID} out: {a=ID, bar=D, x=ID} + 2 jmp?(L2) INIT: in: {bar=D} out: {bar=D} + d(fun foo() { val a = 2 }) L2: - r(object { { val x = 1 } fun foo() { val a = 2 } }) INIT: in: {bar=D, x=ID} out: {bar=D, x=ID} - w(bar) INIT: in: {bar=D, x=ID} out: {bar=ID, x=ID} - mark("after") INIT: in: {bar=ID, x=ID} out: {bar=ID, x=ID} + r(object { { val x = 1 } fun foo() { val a = 2 } }) + w(bar) INIT: in: {bar=D} out: {bar=ID} + mark("after") INIT: in: {bar=ID} out: {bar=ID} r("after") L1: - 1 + 1 INIT: in: {} out: {} error: - INIT: in: {} out: {} + sink: - INIT: in: {a=ID, bar=D, x=ID} out: {a=ID, bar=D, x=ID} USE: in: {} out: {} + USE: in: {} out: {} ===================== == foo == fun foo() { @@ -43,15 +43,15 @@ fun foo() { } --------------------- L3: - 3 INIT: in: {bar=D, x=ID} out: {bar=D, x=ID} + 3 INIT: in: {bar=D} out: {bar=D} 4 mark({ val a = 2 }) - v(val a = 2) INIT: in: {bar=D, x=ID} out: {a=D, bar=D, x=ID} - r(2) INIT: in: {a=D, bar=D, x=ID} out: {a=D, bar=D, x=ID} - w(a) INIT: in: {a=D, bar=D, x=ID} out: {a=ID, bar=D, x=ID} + v(val a = 2) INIT: in: {bar=D} out: {a=D, bar=D} + r(2) INIT: in: {a=D, bar=D} out: {a=D, bar=D} + w(a) INIT: in: {a=D, bar=D} out: {a=ID, bar=D} L4: - 3 INIT: in: {a=ID, bar=D, x=ID} out: {a=ID, bar=D, x=ID} + 3 INIT: in: {bar=D} out: {bar=D} error: INIT: in: {} out: {} sink: - INIT: in: {a=ID, bar=D, x=ID} out: {a=ID, bar=D, x=ID} USE: in: {} out: {} + INIT: in: {bar=D} out: {bar=D} USE: in: {} out: {} ===================== diff --git a/compiler/testData/cfg-variables/lexicalScopes/tryScope.instructions b/compiler/testData/cfg-variables/lexicalScopes/tryScope.instructions index fb5130f8f01..3537c655af1 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/tryScope.instructions +++ b/compiler/testData/cfg-variables/lexicalScopes/tryScope.instructions @@ -19,41 +19,41 @@ L0: mark("before") r("before") mark(try { foo() } catch (e: Exception) { val a = e } finally { val a = 1 }) - jmp?(L2 [onException]) USE: in: {e=READ} out: {e=READ} + jmp?(L2 [onException]) jmp?(L3 [onExceptionToFinallyBlock]) 3 mark({ foo() }) mark(foo()) call(foo, foo) - 2 jmp(L4 [afterCatches]) USE: in: {} out: {} + 2 jmp(L4 [afterCatches]) USE: in: {} out: {} L2 [onException]: 3 v(e: Exception) INIT: in: {} out: {e=D} w(e) INIT: in: {e=D} out: {e=ID} 4 mark({ val a = e }) INIT: in: {e=ID} out: {e=ID} - v(val a = e) INIT: in: {e=ID} out: {a=D, e=ID} USE: in: {e=READ} out: {e=READ} - r(e) INIT: in: {a=D, e=ID} out: {a=D, e=ID} USE: in: {} out: {e=READ} + v(val a = e) INIT: in: {e=ID} out: {a=D, e=ID} USE: in: {e=READ} out: {e=READ} + r(e) INIT: in: {a=D, e=ID} out: {a=D, e=ID} USE: in: {} out: {e=READ} w(a) INIT: in: {a=D, e=ID} out: {a=ID, e=ID} - 3 jmp(L4 [afterCatches]) INIT: in: {a=ID, e=ID} out: {a=ID, e=ID} + 3 jmp(L4 [afterCatches]) INIT: in: {e=ID} out: {e=ID} L4 [afterCatches]: - 2 jmp(L5 [skipFinallyToErrorBlock]) + 2 jmp(L5 [skipFinallyToErrorBlock]) INIT: in: {} out: {} L3 [onExceptionToFinallyBlock]: L6 [start finally]: - 3 mark({ val a = 1 }) INIT: in: {} out: {} + 3 mark({ val a = 1 }) v(val a = 1) INIT: in: {} out: {a=D} r(1) INIT: in: {a=D} out: {a=D} w(a) INIT: in: {a=D} out: {a=ID} L7 [finish finally]: - 2 jmp(error) INIT: in: {a=ID} out: {a=ID} + 2 jmp(error) INIT: in: {} out: {} L5 [skipFinallyToErrorBlock]: - 3 mark({ val a = 1 }) INIT: in: {a=ID, e=ID} out: {a=ID, e=ID} - v(val a = 1) INIT: in: {a=ID, e=ID} out: {a=D, a=ID, e=ID} - r(1) INIT: in: {a=D, a=ID, e=ID} out: {a=D, a=ID, e=ID} - w(a) INIT: in: {a=D, a=ID, e=ID} out: {a=ID, a=ID, e=ID} - 2 mark("after") INIT: in: {a=ID, a=ID, e=ID} out: {a=ID, a=ID, e=ID} + 3 mark({ val a = 1 }) + v(val a = 1) INIT: in: {} out: {a=D} + r(1) INIT: in: {a=D} out: {a=D} + w(a) INIT: in: {a=D} out: {a=ID} + 2 mark("after") INIT: in: {} out: {} r("after") L1: 1 error: - INIT: in: {a=ID} out: {a=ID} + sink: - INIT: in: {a=ID, a=ID, e=ID} out: {a=ID, a=ID, e=ID} USE: in: {} out: {} + USE: in: {} out: {} ===================== diff --git a/compiler/testData/cfg-variables/lexicalScopes/whileScope.instructions b/compiler/testData/cfg-variables/lexicalScopes/whileScope.instructions index 0bdcfb43dfb..64ccfd2c6b1 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/whileScope.instructions +++ b/compiler/testData/cfg-variables/lexicalScopes/whileScope.instructions @@ -15,11 +15,11 @@ L0: mark(while (true) { val a: Int }) L2 [loop entry point]: L5 [condition entry point]: - r(true) INIT: in: {a=D} out: {a=D} + r(true) L4 [body entry point]: 3 mark({ val a: Int }) - v(val a: Int) - 2 jmp(L2 [loop entry point]) USE: in: {} out: {} + v(val a: Int) INIT: in: {} out: {a=D} + 2 jmp(L2 [loop entry point]) INIT: in: {} out: {} USE: in: {} out: {} L3 [loop exit point]: - read (Unit) - mark("after") @@ -29,5 +29,5 @@ L1: error: sink: - USE: in: {} out: {} + USE: in: {} out: {} ===================== diff --git a/compiler/util/src/org/jetbrains/jet/utils/addToStdlib.kt b/compiler/util/src/org/jetbrains/jet/utils/addToStdlib.kt new file mode 100644 index 00000000000..5b8f4cd2e50 --- /dev/null +++ b/compiler/util/src/org/jetbrains/jet/utils/addToStdlib.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2010-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.utils.addToStdlib + +import java.util.HashMap + +fun Map.filterKeys(predicate: (K)->Boolean): Map { + val result = HashMap() + for ((k, v) in this) { + if (predicate(k)) { + result[k] = v + } + } + return result +}