From d51c030803cc70ddd7f724f5562f207f90cefe0a Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Mon, 16 Jan 2012 20:59:06 +0400 Subject: [PATCH 1/4] New module script DSL --- .../jet/compiler/CompileEnvironment.java | 47 +++++++----------- compiler/testData/compiler/smoke/Smoke.kts | 7 +-- .../jet/compiler/CompileEnvironmentTest.java | 11 ++--- stdlib/ktSrc/modules/ModuleBuilder.kt | 49 +++---------------- stdlib/src/jet/modules/AllModules.java | 10 ++++ stdlib/src/jet/modules/IModuleSetBuilder.java | 10 ---- .../{IModuleBuilder.java => Module.java} | 3 +- 7 files changed, 47 insertions(+), 90 deletions(-) create mode 100644 stdlib/src/jet/modules/AllModules.java delete mode 100644 stdlib/src/jet/modules/IModuleSetBuilder.java rename stdlib/src/jet/modules/{IModuleBuilder.java => Module.java} (74%) diff --git a/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironment.java b/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironment.java index 545a248242b..17193241a1f 100644 --- a/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironment.java +++ b/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironment.java @@ -7,9 +7,8 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.Function; import com.intellij.util.Processor; -import jet.ExtensionFunction0; -import jet.modules.IModuleBuilder; -import jet.modules.IModuleSetBuilder; +import jet.modules.AllModules; +import jet.modules.Module; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.codegen.ClassFileFactory; import org.jetbrains.jet.codegen.GeneratedClassLoader; @@ -19,7 +18,7 @@ import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.plugin.JetMainDetector; import java.io.*; -import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; import java.util.List; @@ -174,13 +173,14 @@ public class CompileEnvironment { e.printStackTrace(); } - final IModuleSetBuilder moduleSetBuilder = loadModuleScript(moduleFile); - if (moduleSetBuilder == null) { - return; + final List modules = loadModuleScript(moduleFile); + + if (modules == null) { + throw new CompileEnvironmentException("Module script " + moduleFile + " compilation failed"); } final String directory = new File(moduleFile).getParent(); - for (IModuleBuilder moduleBuilder : moduleSetBuilder.getModules()) { + for (Module moduleBuilder : modules) { ClassFileFactory moduleFactory = compileModule(moduleBuilder, directory); final String path = jarPath != null ? jarPath : new File(directory, moduleBuilder.getModuleName() + ".jar").getPath(); try { @@ -191,7 +191,7 @@ public class CompileEnvironment { } } - public IModuleSetBuilder loadModuleScript(String moduleFile) { + public List loadModuleScript(String moduleFile) { CompileSession scriptCompileSession = new CompileSession(myEnvironment); scriptCompileSession.addSources(moduleFile); scriptCompileSession.addStdLibSources(true); @@ -204,34 +204,25 @@ public class CompileEnvironment { return runDefineModules(moduleFile, factory); } - private static IModuleSetBuilder runDefineModules(String moduleFile, ClassFileFactory factory) { + private static List runDefineModules(String moduleFile, ClassFileFactory factory) { GeneratedClassLoader loader = new GeneratedClassLoader(factory); try { - Class moduleSetBuilderClass = loader.loadClass("kotlin.modules.ModuleSetBuilder"); - final IModuleSetBuilder moduleSetBuilder = (IModuleSetBuilder) moduleSetBuilderClass.newInstance(); - Class namespaceClass = loader.loadClass(JvmAbi.PACKAGE_CLASS); - final Field[] fields = namespaceClass.getDeclaredFields(); - boolean modulesDefined = false; - for (Field field : fields) { - if (field.getName().equals("modules")) { - field.setAccessible(true); - ExtensionFunction0 defineMudules = (ExtensionFunction0) field.get(null); - defineMudules.invoke(moduleSetBuilder); - modulesDefined = true; - break; - } + final Method method = namespaceClass.getDeclaredMethod("project"); + if (method == null) { + throw new CompileEnvironmentException("Module script " + moduleFile + " must define project() function"); } - if (!modulesDefined) { - throw new CompileEnvironmentException("Module script " + moduleFile + " must define a modules() property"); - } - return moduleSetBuilder; + + method.setAccessible(true); + method.invoke(null); + + return AllModules.modules; } catch (Exception e) { throw new CompileEnvironmentException(e); } } - public ClassFileFactory compileModule(IModuleBuilder moduleBuilder, String directory) { + public ClassFileFactory compileModule(Module moduleBuilder, String directory) { CompileSession moduleCompileSession = new CompileSession(myEnvironment); if (!"stdlib".equals(moduleBuilder.getModuleName())) { moduleCompileSession.addStdLibSources(false); diff --git a/compiler/testData/compiler/smoke/Smoke.kts b/compiler/testData/compiler/smoke/Smoke.kts index d9429cd1b65..179d700646e 100644 --- a/compiler/testData/compiler/smoke/Smoke.kts +++ b/compiler/testData/compiler/smoke/Smoke.kts @@ -1,6 +1,7 @@ import kotlin.modules.* -val modules = module("smoke") { - source files "Smoke.kt" - jar name System.getProperty("java.io.tmpdir") + "/smoke.jar" +fun project() { + module("smoke") { + sources += "Smoke.kt" + } } diff --git a/compiler/tests/org/jetbrains/jet/compiler/CompileEnvironmentTest.java b/compiler/tests/org/jetbrains/jet/compiler/CompileEnvironmentTest.java index 31bba9535be..da1222b561c 100644 --- a/compiler/tests/org/jetbrains/jet/compiler/CompileEnvironmentTest.java +++ b/compiler/tests/org/jetbrains/jet/compiler/CompileEnvironmentTest.java @@ -1,7 +1,6 @@ package org.jetbrains.jet.compiler; -import jet.modules.IModuleBuilder; -import jet.modules.IModuleSetBuilder; +import jet.modules.Module; import junit.framework.TestCase; import org.jetbrains.jet.cli.KotlinCompiler; import org.jetbrains.jet.codegen.ClassFileFactory; @@ -37,9 +36,9 @@ public class CompileEnvironmentTest extends TestCase { environment.setJavaRuntime(activeRtJar); environment.initializeKotlinRuntime(); final String testDataDir = JetParsingTest.getTestDataDir() + "/compiler/smoke/"; - final IModuleSetBuilder setBuilder = environment.loadModuleScript(testDataDir + "Smoke.kts"); - assertEquals(1, setBuilder.getModules().size()); - final IModuleBuilder moduleBuilder = setBuilder.getModules().get(0); + final List modules = environment.loadModuleScript(testDataDir + "Smoke.kts"); + assertEquals(1, modules.size()); + final Module moduleBuilder = modules.get(0); final ClassFileFactory factory = environment.compileModule(moduleBuilder, testDataDir); assertNotNull(factory); assertNotNull(factory.asBytes("Smoke/namespace.class")); @@ -51,7 +50,7 @@ public class CompileEnvironmentTest extends TestCase { assertTrue(entries.contains("Smoke/namespace.class")); } - public void _testSmokeWithCompilerJar() throws IOException { + public void testSmokeWithCompilerJar() throws IOException { File tempFile = File.createTempFile("compilerTest", "compilerTest"); try { KotlinCompiler.main(Arrays.asList("-module", JetParsingTest.getTestDataDir() + "/compiler/smoke/Smoke.kts", "-jar", tempFile.getAbsolutePath()).toArray(new String[0])); diff --git a/stdlib/ktSrc/modules/ModuleBuilder.kt b/stdlib/ktSrc/modules/ModuleBuilder.kt index 39097b7d818..487ef408f20 100644 --- a/stdlib/ktSrc/modules/ModuleBuilder.kt +++ b/stdlib/ktSrc/modules/ModuleBuilder.kt @@ -3,57 +3,35 @@ package kotlin.modules import java.util.* import jet.modules.* -fun moduleSet(description: ModuleSetBuilder.() -> Unit) = description - -fun module(name: String, description: ModuleBuilder.() -> Unit) = moduleSet { - module(name, description) -} - -class ModuleSetBuilder(): IModuleSetBuilder { - private val modules = ArrayList() - - fun module(name: String, callback: ModuleBuilder.() -> Unit) { - val builder = ModuleBuilder(name) - builder.callback() - modules.add(builder) - } - - override fun getModules(): List? = modules +fun module(name: String, callback: ModuleBuilder.() -> Unit) { + val builder = ModuleBuilder(name) + builder.callback() + AllModules.modules?.add(builder) } class SourcesBuilder(val parent: ModuleBuilder) { - fun files(pattern: String) { + fun plusAssign(pattern: String) { parent.addSourceFiles(pattern) } } class ClasspathBuilder(val parent: ModuleBuilder) { - fun entry(name: String) { + fun plusAssign(name: String) { parent.addClasspathEntry(name) } } -class JarBuilder(val parent: ModuleBuilder) { - fun name(jarName: String) { - parent.setJarName(jarName) - } -} - -open class ModuleBuilder(val name: String): IModuleBuilder { +open class ModuleBuilder(val name: String): Module { // http://youtrack.jetbrains.net/issue/KT-904 private val sourceFiles0: ArrayList = ArrayList() private val classpathRoots0: ArrayList = ArrayList() - var _jarName: String? = null - val source: SourcesBuilder + val sources: SourcesBuilder get() = SourcesBuilder(this) val classpath: ClasspathBuilder get() = ClasspathBuilder(this) - val jar: JarBuilder - get() = JarBuilder(this) - fun addSourceFiles(pattern: String) { sourceFiles0.add(pattern) } @@ -62,19 +40,8 @@ open class ModuleBuilder(val name: String): IModuleBuilder { classpathRoots0.add(name) } - fun setJarName(name: String) { - _jarName = name - } - override fun getSourceFiles(): List? = sourceFiles0 override fun getClasspathRoots(): List? = classpathRoots0 override fun getModuleName(): String? = name - override fun getJarName(): String? = _jarName - -} - -class ModuleBuilder2(name: String): ModuleBuilder(name) { - - } diff --git a/stdlib/src/jet/modules/AllModules.java b/stdlib/src/jet/modules/AllModules.java new file mode 100644 index 00000000000..52a4595b8ca --- /dev/null +++ b/stdlib/src/jet/modules/AllModules.java @@ -0,0 +1,10 @@ +/* + * @author max + */ +package jet.modules; + +import java.util.ArrayList; + +public class AllModules { + public static final ArrayList modules = new ArrayList(); +} diff --git a/stdlib/src/jet/modules/IModuleSetBuilder.java b/stdlib/src/jet/modules/IModuleSetBuilder.java deleted file mode 100644 index 7f5f03dc3d2..00000000000 --- a/stdlib/src/jet/modules/IModuleSetBuilder.java +++ /dev/null @@ -1,10 +0,0 @@ -package jet.modules; - -import java.util.List; - -/** - * @author yole - */ -public interface IModuleSetBuilder { - List getModules(); -} diff --git a/stdlib/src/jet/modules/IModuleBuilder.java b/stdlib/src/jet/modules/Module.java similarity index 74% rename from stdlib/src/jet/modules/IModuleBuilder.java rename to stdlib/src/jet/modules/Module.java index f455eb5fabc..649ffb25174 100644 --- a/stdlib/src/jet/modules/IModuleBuilder.java +++ b/stdlib/src/jet/modules/Module.java @@ -5,9 +5,8 @@ import java.util.List; /** * @author yole */ -public interface IModuleBuilder { +public interface Module { String getModuleName(); List getSourceFiles(); List getClasspathRoots(); - String getJarName(); } From 62de24d6c9896072ee4f2ce6cffa040ef4ccc20d Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Tue, 17 Jan 2012 13:58:00 +0400 Subject: [PATCH 2/4] KT-1021 "internal" is suggested in completion where type is expected --- .../plugin/completion/JetKeywordCompletionContributor.java | 3 ++- idea/testData/completion/keywords/AfterClassProperty.kt | 7 +++++++ idea/testData/completion/keywords/InClassProperty.kt | 6 ++++++ 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 idea/testData/completion/keywords/AfterClassProperty.kt create mode 100644 idea/testData/completion/keywords/InClassProperty.kt diff --git a/idea/src/org/jetbrains/jet/plugin/completion/JetKeywordCompletionContributor.java b/idea/src/org/jetbrains/jet/plugin/completion/JetKeywordCompletionContributor.java index 0fbf10a8364..af001ad3809 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/JetKeywordCompletionContributor.java +++ b/idea/src/org/jetbrains/jet/plugin/completion/JetKeywordCompletionContributor.java @@ -118,7 +118,8 @@ public class JetKeywordCompletionContributor extends CompletionContributor { @Override public boolean isAcceptable(Object element, PsiElement context) { //noinspection unchecked - return PsiTreeUtil.getParentOfType(context, JetClassBody.class, true, JetBlockExpression.class) != null; + return PsiTreeUtil.getParentOfType(context, JetClassBody.class, true, + JetBlockExpression.class, JetProperty.class) != null; } @Override diff --git a/idea/testData/completion/keywords/AfterClassProperty.kt b/idea/testData/completion/keywords/AfterClassProperty.kt new file mode 100644 index 00000000000..0b0fe0c590d --- /dev/null +++ b/idea/testData/completion/keywords/AfterClassProperty.kt @@ -0,0 +1,7 @@ +class MouseMovedEventArgs +{ + public val X : int = 0 + in +} + +// EXIST: internal \ No newline at end of file diff --git a/idea/testData/completion/keywords/InClassProperty.kt b/idea/testData/completion/keywords/InClassProperty.kt new file mode 100644 index 00000000000..8647c7d465e --- /dev/null +++ b/idea/testData/completion/keywords/InClassProperty.kt @@ -0,0 +1,6 @@ +class MouseMovedEventArgs +{ + public val X : int = 0 +} + +// ABSENT: internal \ No newline at end of file From 3a634417b97d7cb56577339de6ff2a29dd4657a4 Mon Sep 17 00:00:00 2001 From: svtk Date: Tue, 17 Jan 2012 15:27:54 +0400 Subject: [PATCH 3/4] KT-776 Wrong detection of unreachable code KT-1001 Argument 2 for @NotNull parameter of JetFlowInformationProvider.checkIsInitialized must not be null --- .../jet/lang/cfg/JetControlFlowBuilder.java | 1 + .../cfg/JetControlFlowBuilderAdapter.java | 6 + .../cfg/JetControlFlowGraphTraverser.java | 6 +- .../jet/lang/cfg/JetControlFlowProcessor.java | 1 + .../lang/cfg/JetFlowInformationProvider.java | 10 +- .../jet/lang/cfg/pseudocode/Instruction.java | 2 - .../JetControlFlowInstructionsGenerator.java | 9 +- .../jet/lang/cfg/pseudocode/Pseudocode.java | 226 +++++++++++------- compiler/testData/cfg/Finally.instructions | 67 ++++-- compiler/testData/cfg/If.instructions | 4 +- .../cfg/OnlyWhileInFunctionBody.instructions | 12 +- .../tests/controlFlowAnalysis/kt1001.jet | 35 +++ .../tests/controlFlowAnalysis/kt776.jet | 38 +++ .../jetbrains/jet/cfg/JetControlFlowTest.java | 4 +- 14 files changed, 291 insertions(+), 130 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/controlFlowAnalysis/kt1001.jet create mode 100644 compiler/testData/diagnostics/tests/controlFlowAnalysis/kt776.jet diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilder.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilder.java index b4581a9200a..31bfcec6ce7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilder.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilder.java @@ -19,6 +19,7 @@ public interface JetControlFlowBuilder { void bindLabel(@NotNull Label label); void allowDead(); + void stopAllowDead(); // Jumps void jump(@NotNull Label label); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilderAdapter.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilderAdapter.java index d42a0cbd726..0c6ea512103 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilderAdapter.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilderAdapter.java @@ -43,6 +43,12 @@ public class JetControlFlowBuilderAdapter implements JetControlFlowBuilder { builder.allowDead(); } + @Override + public void stopAllowDead() { + assert builder != null; + builder.stopAllowDead(); + } + @Override public void jump(@NotNull Label label) { assert builder != null; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowGraphTraverser.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowGraphTraverser.java index 7befd95b142..9b35e30ec89 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowGraphTraverser.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowGraphTraverser.java @@ -8,10 +8,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.cfg.pseudocode.*; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import java.util.*; /** * @author svtk @@ -140,7 +137,6 @@ public class JetControlFlowGraphTraverser { Collections.reverse(instructions); } for (Instruction instruction : instructions) { - if (instruction.isDead()) continue; if (lookInside && instruction instanceof LocalDeclarationInstruction) { traverseAndAnalyzeInstructionGraph(((LocalDeclarationInstruction) instruction).getBody(), instructionDataAnalyzeStrategy); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java index c3dab813a27..3c32dfc6c2d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java @@ -408,6 +408,7 @@ public class JetControlFlowProcessor { builder.exitTryFinally(); value(finallyBlock.getFinalExpression(), inCondition); } + builder.stopAllowDead(); } @Override diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java index 37c96d9dce7..c0284d377b5 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java @@ -252,7 +252,10 @@ public class JetFlowInformationProvider { analyzeLocalDeclarations(processLocalDeclaration, pseudocode); } - private void checkIsInitialized(@NotNull VariableDescriptor variableDescriptor, @NotNull JetElement element, @NotNull VariableInitializers variableInitializers, @NotNull Collection varWithUninitializedErrorGenerated) { + private void checkIsInitialized(@NotNull VariableDescriptor variableDescriptor, + @NotNull JetElement element, + @NotNull VariableInitializers variableInitializers, + @NotNull Collection varWithUninitializedErrorGenerated) { if (!(element instanceof JetSimpleNameExpression)) return; boolean isInitialized = variableInitializers.isInitialized(); @@ -272,7 +275,10 @@ public class JetFlowInformationProvider { } } - private boolean checkValReassignment(@NotNull VariableDescriptor variableDescriptor, @NotNull JetExpression expression, @NotNull VariableInitializers enterInitializers, @NotNull Collection varWithValReassignErrorGenerated) { + private boolean checkValReassignment(@NotNull VariableDescriptor variableDescriptor, + @NotNull JetExpression expression, + @NotNull VariableInitializers enterInitializers, + @NotNull Collection varWithValReassignErrorGenerated) { boolean isInitializedNotHere = enterInitializers.isInitialized(); Set possibleLocalInitializers = enterInitializers.getPossibleLocalInitializers(); if (possibleLocalInitializers.size() == 1) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Instruction.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Instruction.java index 63f759c81d1..4a2cf3832e6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Instruction.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Instruction.java @@ -20,6 +20,4 @@ public interface Instruction { Collection getNextInstructions(); void accept(InstructionVisitor visitor); - - boolean isDead(); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/JetControlFlowInstructionsGenerator.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/JetControlFlowInstructionsGenerator.java index 0d6ac71d32c..71d5ffc290e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/JetControlFlowInstructionsGenerator.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/JetControlFlowInstructionsGenerator.java @@ -190,7 +190,7 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd bindLabel(getExitPoint(subroutine)); pseudocode.addExitInstruction(new SubroutineExitInstruction(subroutine, "")); bindLabel(error); - add(new SubroutineExitInstruction(subroutine, "")); + pseudocode.addErrorInstruction(new SubroutineExitInstruction(subroutine, "")); bindLabel(sink); pseudocode.addSinkInstruction(new SubroutineSinkInstruction(subroutine, "")); elementToBlockInfo.remove(subroutine); @@ -266,6 +266,13 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd pseudocode.allowDead(allowedDeadLabel); } + @Override + public void stopAllowDead() { + Label allowedDeadLabel = createUnboundLabel(); + bindLabel(allowedDeadLabel); + pseudocode.stopAllowDead(allowedDeadLabel); + } + @Override public void nondeterministicJump(Label label) { handleJumpInsideTryFinally(label); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java index 520b52437a8..f9e1ea2ded1 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java @@ -56,12 +56,16 @@ public class Pseudocode { private final List mutableInstructionList = new ArrayList(); private final List instructions = new ArrayList(); + private List deadInstructions; + private final List labels = new ArrayList(); private final List allowedDeadLabels = new ArrayList(); + private final List stopAllowDeadLabels = new ArrayList(); private final JetElement correspondingElement; private SubroutineExitInstruction exitInstruction; private SubroutineSinkInstruction sinkInstruction; + private SubroutineExitInstruction errorInstruction; private boolean postPrecessed = false; public Pseudocode(JetElement correspondingElement) { @@ -81,6 +85,10 @@ public class Pseudocode { public void allowDead(Label label) { allowedDeadLabels.add((PseudocodeLabel) label); } + + public void stopAllowDead(Label label) { + stopAllowDeadLabels.add((PseudocodeLabel) label); + } @NotNull public List getInstructions() { @@ -95,10 +103,17 @@ public class Pseudocode { @NotNull public List getDeadInstructions() { - List deadInstructions = Lists.newArrayList(); - for (Instruction instruction : instructions) { - if (instruction.isDead()) { - deadInstructions.add(instruction); + if (deadInstructions != null) { + return deadInstructions; + } + deadInstructions = Lists.newArrayList(); + Collection allowedDeadInstructions = collectAllowedDeadInstructions(); + + for (Instruction instruction : mutableInstructionList) { + if (((InstructionImpl)instruction).isDead()) { + if (!allowedDeadInstructions.contains(instruction)) { + deadInstructions.add(instruction); + } } } return deadInstructions; @@ -122,6 +137,12 @@ public class Pseudocode { this.sinkInstruction = sinkInstruction; } + public void addErrorInstruction(SubroutineExitInstruction errorInstruction) { + addInstruction(errorInstruction); + assert this.errorInstruction == null; + this.errorInstruction = errorInstruction; + } + public void addInstruction(Instruction instruction) { mutableInstructionList.add(instruction); instruction.setOwner(this); @@ -151,88 +172,107 @@ public class Pseudocode { if (postPrecessed) return; postPrecessed = true; for (int i = 0, instructionsSize = mutableInstructionList.size(); i < instructionsSize; i++) { - Instruction instruction = mutableInstructionList.get(i); - final int currentPosition = i; - instruction.accept(new InstructionVisitor() { - @Override - public void visitInstructionWithNext(InstructionWithNext instruction) { - instruction.setNext(getNextPosition(currentPosition)); - } - - @Override - public void visitJump(AbstractJumpInstruction instruction) { - instruction.setResolvedTarget(getJumpTarget(instruction.getTargetLabel())); - } - - @Override - public void visitNondeterministicJump(NondeterministicJumpInstruction instruction) { - instruction.setNext(getNextPosition(currentPosition)); - List