diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/JetSemanticServices.java b/compiler/frontend/src/org/jetbrains/jet/lang/JetSemanticServices.java index 6b5517ace57..575a8b394b7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/JetSemanticServices.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/JetSemanticServices.java @@ -2,7 +2,6 @@ package org.jetbrains.jet.lang; import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider; import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.resolve.*; import org.jetbrains.jet.lang.types.*; @@ -19,18 +18,12 @@ public class JetSemanticServices { return new JetSemanticServices(JetStandardLibrary.getJetStandardLibrary(project), JetControlFlowDataTraceFactory.EMPTY); } - public static JetSemanticServices createSemanticServices(Project project, JetControlFlowDataTraceFactory flowDataTraceFactory) { - return new JetSemanticServices(JetStandardLibrary.getJetStandardLibrary(project), flowDataTraceFactory); - } - private final JetStandardLibrary standardLibrary; private final JetTypeChecker typeChecker; - private final JetControlFlowDataTraceFactory flowDataTraceFactory; private JetSemanticServices(JetStandardLibrary standardLibrary, JetControlFlowDataTraceFactory flowDataTraceFactory) { this.standardLibrary = standardLibrary; this.typeChecker = new JetTypeChecker(standardLibrary); - this.flowDataTraceFactory = flowDataTraceFactory; } @NotNull @@ -40,7 +33,7 @@ public class JetSemanticServices { @NotNull public ClassDescriptorResolver getClassDescriptorResolver(BindingTrace trace) { - return new ClassDescriptorResolver(this, trace, flowDataTraceFactory); + return new ClassDescriptorResolver(this, trace); } @NotNull 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 7430be1bed2..e38b2e8ca1c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java @@ -1,92 +1,236 @@ package org.jetbrains.jet.lang.cfg; +import com.google.common.collect.Maps; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.cfg.pseudocode.*; import org.jetbrains.jet.lang.psi.JetElement; import org.jetbrains.jet.lang.psi.JetExpression; -import org.jetbrains.jet.lang.psi.JetLoopExpression; +import org.jetbrains.jet.lang.resolve.BindingTrace; -import java.util.Collection; +import java.util.*; /** - * @author abreslav - */ -public interface JetFlowInformationProvider { -// JetFlowInformationProvider THROW_EXCEPTION = new JetFlowInformationProvider() { -// @Override +* @author svtk +*/ +public class JetFlowInformationProvider { + + private final Map pseudocodeMap; + + public JetFlowInformationProvider(@NotNull JetElement declaration, @NotNull final JetExpression bodyExpression, @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory, @NotNull BindingTrace trace) { + final JetPseudocodeTrace pseudocodeTrace = flowDataTraceFactory.createTrace(declaration); + pseudocodeMap = new HashMap(); + final Map representativeInstructions = new HashMap(); + final Map loopInfo = Maps.newHashMap(); + JetPseudocodeTrace wrappedTrace = new JetPseudocodeTrace() { + @Override + public void recordControlFlowData(@NotNull JetElement element, @NotNull Pseudocode pseudocode) { + pseudocodeTrace.recordControlFlowData(element, pseudocode); + pseudocodeMap.put(element, pseudocode); + } + + @Override + public void recordRepresentativeInstruction(@NotNull JetElement element, @NotNull Instruction instruction) { + Instruction oldValue = representativeInstructions.put(element, instruction); +// assert oldValue == null : element.getText(); + pseudocodeTrace.recordRepresentativeInstruction(element, instruction); + } + + @Override + public void recordLoopInfo(JetExpression expression, LoopInfo blockInfo) { + loopInfo.put(expression, blockInfo); + pseudocodeTrace.recordLoopInfo(expression, blockInfo); + } + + @Override + public void close() { + pseudocodeTrace.close(); + for (Pseudocode pseudocode : pseudocodeMap.values()) { + pseudocode.postProcess(); + } + } + }; + JetControlFlowInstructionsGenerator instructionsGenerator = new JetControlFlowInstructionsGenerator(wrappedTrace); + new JetControlFlowProcessor(trace, instructionsGenerator).generate(declaration, bodyExpression); + wrappedTrace.close(); + } + // public void collectReturnedInformation(@NotNull JetElement subroutine, @NotNull Collection returnedExpressions, @NotNull Collection elementsReturningUnit) { -// throw new UnsupportedOperationException(); -// } +// Pseudocode pseudocode = pseudocodeMap.get(subroutine); +// assert pseudocode != null; // -// @Override -// public void collectReturnExpressions(@NotNull JetElement subroutine, @NotNull Collection returnedExpressions) { -// throw new UnsupportedOperationException(); +// SubroutineExitInstruction exitInstruction = pseudocode.getExitInstruction(); +// processPreviousInstructions(exitInstruction, new HashSet(), returnedExpressions, elementsReturningUnit); // } -// -// @Override -// public void collectUnreachableExpressions(@NotNull JetElement subroutine, @NotNull Collection unreachableElements) { -// throw new UnsupportedOperationException(); -// } -// -// @Override + + public void collectReturnExpressions(@NotNull JetElement subroutine, @NotNull final Collection returnedExpressions) { + Pseudocode pseudocode = pseudocodeMap.get(subroutine); + assert pseudocode != null; + + SubroutineExitInstruction exitInstruction = pseudocode.getExitInstruction(); + for (Instruction previousInstruction : exitInstruction.getPreviousInstructions()) { + previousInstruction.accept(new InstructionVisitor() { + @Override + public void visitReturnValue(ReturnValueInstruction instruction) { + returnedExpressions.add((JetExpression) instruction.getElement()); + } + + @Override + public void visitReturnNoValue(ReturnNoValueInstruction instruction) { + returnedExpressions.add((JetExpression) instruction.getElement()); + } + + + @Override + public void visitJump(AbstractJumpInstruction instruction) { + // Nothing + } + + @Override + public void visitInstruction(Instruction instruction) { + if (instruction instanceof JetElementInstruction) { + JetElementInstruction elementInstruction = (JetElementInstruction) instruction; + returnedExpressions.add((JetExpression) elementInstruction.getElement()); + } + else { + throw new IllegalStateException(instruction + " precedes the exit point"); + } + } + }); + } + } + + public void collectUnreachableExpressions(@NotNull JetElement subroutine, @NotNull Collection unreachableElements) { + Pseudocode pseudocode = pseudocodeMap.get(subroutine); + assert pseudocode != null; + + SubroutineEnterInstruction enterInstruction = pseudocode.getEnterInstruction(); + Set visited = new HashSet(); + collectReachable(enterInstruction, visited, null); + + for (Instruction instruction : pseudocode.getInstructions()) { + if (!visited.contains(instruction) && + instruction instanceof JetElementInstruction && + // TODO : do {return} while (1 > a) + !(instruction instanceof ReadUnitValueInstruction)) { + unreachableElements.add(((JetElementInstruction) instruction).getElement()); + } + } + } // public void collectDominatedExpressions(@NotNull JetExpression dominator, @NotNull Collection dominated) { -// throw new UnsupportedOperationException(); +// Instruction dominatorInstruction = representativeInstructions.get(dominator); +// if (dominatorInstruction == null) { +// return; +// } +// SubroutineEnterInstruction enterInstruction = dominatorInstruction.getOwner().getEnterInstruction(); +// +// Set reachable = new HashSet(); +// collectReachable(enterInstruction, reachable, null); +// +// Set reachableWithDominatorProhibited = new HashSet(); +// reachableWithDominatorProhibited.add(dominatorInstruction); +// collectReachable(enterInstruction, reachableWithDominatorProhibited, null); +// +// for (Instruction instruction : reachable) { +// if (instruction instanceof JetElementInstruction +// && reachable.contains(instruction) +// && !reachableWithDominatorProhibited.contains(instruction)) { +// JetElementInstruction elementInstruction = (JetElementInstruction) instruction; +// dominated.add(elementInstruction.getElement()); +// } +// } // } // -// @Override // public boolean isBreakable(JetLoopExpression loop) { -// throw new UnsupportedOperationException(); +// LoopInfo info = loopInfo.get(loop); +// Pseudocode.PseudocodeLabel bodyEntryPoint = (Pseudocode.PseudocodeLabel) info.getBodyEntryPoint(); +// Pseudocode.PseudocodeLabel exitPoint = (Pseudocode.PseudocodeLabel) info.getExitPoint(); +// HashSet visited = Sets.newHashSet(); +// Pseudocode.PseudocodeLabel conditionEntryPoint = (Pseudocode.PseudocodeLabel) info.getConditionEntryPoint(); +// visited.add(conditionEntryPoint.resolveToInstruction()); +// return collectReachable(bodyEntryPoint.resolveToInstruction(), visited, exitPoint.resolveToInstruction()); // } // -// }; -// -// JetFlowInformationProvider NONE = new JetFlowInformationProvider() { -// @Override -// public void collectReturnedInformation(@NotNull JetElement subroutine, @NotNull Collection returnedExpressions, @NotNull Collection elementsReturningUnit) { +// public boolean isReachable(JetExpression from, JetExpression to) { +// Instruction fromInstr = representativeInstructions.get(from); +// assert fromInstr != null : "No representative instruction for " + from.getText(); +// Instruction toInstr = representativeInstructions.get(to); +// assert toInstr != null : "No representative instruction for " + to.getText(); // +// return collectReachable(fromInstr, Sets.newHashSet(), toInstr); // } -// -// @Override -// public void collectReturnExpressions(@NotNull JetElement subroutine, @NotNull Collection returnedExpressions) { -// -// } -// -// @Override -// public void collectUnreachableExpressions(@NotNull JetElement subroutine, @NotNull Collection unreachableElements) { -// -// } -// -// @Override -// public void collectDominatedExpressions(@NotNull JetExpression dominator, @NotNull Collection dominated) { -// -// } -// -// @Override -// public boolean isBreakable(JetLoopExpression loop) { -// return false; -// } -// -// }; +// } - /** - * Collects expressions returned from the given subroutine and 'return;' expressions - */ - void collectReturnedInformation( - @NotNull JetElement subroutine, - @NotNull Collection returnedExpressions, - @NotNull Collection elementsReturningUnit); + private boolean collectReachable(Instruction current, Set visited, @Nullable Instruction lookFor) { + if (!visited.add(current)) return false; + if (current == lookFor) return true; - /** - * Collects all 'return ...' expressions that return from the given subroutine and all the expressions that precede the exit point - */ - void collectReturnExpressions(@NotNull JetElement subroutine, @NotNull Collection returnedExpressions); + for (Instruction nextInstruction : current.getNextInstructions()) { + if (collectReachable(nextInstruction, visited, lookFor)) { + return true; + } + } + return false; + } - void collectUnreachableExpressions( - @NotNull JetElement subroutine, - @NotNull Collection unreachableElements); - - void collectDominatedExpressions( - @NotNull JetExpression dominator, - @NotNull Collection dominated); - - boolean isBreakable(JetLoopExpression loop); +// private void processPreviousInstructions(Instruction previousFor, final Set visited, final Collection returnedExpressions, final Collection elementsReturningUnit) { +// if (!visited.add(previousFor)) return; +// +// Collection previousInstructions = previousFor.getPreviousInstructions(); +// InstructionVisitor visitor = new InstructionVisitor() { +// @Override +// public void visitReadValue(ReadValueInstruction instruction) { +// returnedExpressions.add((JetExpression) instruction.getElement()); +// } +// +// @Override +// public void visitReturnValue(ReturnValueInstruction instruction) { +// processPreviousInstructions(instruction, visited, returnedExpressions, elementsReturningUnit); +// } +// +// @Override +// public void visitReturnNoValue(ReturnNoValueInstruction instruction) { +// elementsReturningUnit.add(instruction.getElement()); +// } +// +// @Override +// public void visitSubroutineEnter(SubroutineEnterInstruction instruction) { +// elementsReturningUnit.add(instruction.getSubroutine()); +// } +// +// @Override +// public void visitUnsupportedElementInstruction(UnsupportedElementInstruction instruction) { +// context.getTrace().report(UNSUPPORTED.on(instruction.getElement(), "Control-flow builder")); +// } +// +// @Override +// public void visitWriteValue(WriteValueInstruction writeValueInstruction) { +// elementsReturningUnit.add(writeValueInstruction.getElement()); +// } +// +// @Override +// public void visitJump(AbstractJumpInstruction instruction) { +// processPreviousInstructions(instruction, visited, returnedExpressions, elementsReturningUnit); +// } +// +// @Override +// public void visitReadUnitValue(ReadUnitValueInstruction instruction) { +// returnedExpressions.add((JetExpression) instruction.getElement()); +// } +// +// @Override +// public void visitInstruction(Instruction instruction) { +// if (instruction instanceof JetElementInstructionImpl) { +// JetElementInstructionImpl elementInstruction = (JetElementInstructionImpl) instruction; +// context.getTrace().report(UNSUPPORTED.on(elementInstruction.getElement(), "Control-flow builder")); +// } +// else { +// throw new UnsupportedOperationException(instruction.toString()); +// } +// } +// }; +// for (Instruction previousInstruction : previousInstructions) { +// previousInstruction.accept(visitor); +// } +// } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java index 7b39810143c..007c0c8340a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java @@ -74,7 +74,7 @@ public class AnalyzingUtils { public BindingContext analyzeNamespaces(@NotNull Project project, @NotNull List declarations, @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) { BindingTraceContext bindingTraceContext = new BindingTraceContext(); - JetSemanticServices semanticServices = JetSemanticServices.createSemanticServices(project, flowDataTraceFactory); + JetSemanticServices semanticServices = JetSemanticServices.createSemanticServices(project); JetScope libraryScope = semanticServices.getStandardLibrary().getLibraryScope(); ModuleDescriptor owner = new ModuleDescriptor(""); @@ -111,7 +111,7 @@ public class AnalyzingUtils { public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor) { throw new IllegalStateException("Must be guaranteed not to happen by the parser"); } - }, declarations); + }, declarations, flowDataTraceFactory); return bindingTraceContext.getBindingContext(); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java index 512f9f192c3..f79fd41bf89 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java @@ -4,7 +4,6 @@ import com.google.common.collect.Lists; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.JetSemanticServices; -import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.psi.JetAnnotationEntry; import org.jetbrains.jet.lang.psi.JetExpression; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java index e4820f5044c..c7ab16a33a1 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java @@ -6,7 +6,6 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.containers.Queue; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.scopes.JetScope; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java index ecffbcc9abc..e0f720f2547 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java @@ -2,17 +2,12 @@ package org.jetbrains.jet.lang.resolve; import com.google.common.collect.Lists; import com.google.common.collect.Maps; -import com.google.common.collect.Sets; import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElement; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.JetSemanticServices; -import org.jetbrains.jet.lang.cfg.JetControlFlowProcessor; -import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider; -import org.jetbrains.jet.lang.cfg.LoopInfo; -import org.jetbrains.jet.lang.cfg.pseudocode.*; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.diagnostics.Errors; @@ -35,15 +30,13 @@ public class ClassDescriptorResolver { private final TypeResolver typeResolver; private final TypeResolver typeResolverNotCheckingBounds; private final BindingTrace trace; - private final JetControlFlowDataTraceFactory flowDataTraceFactory; private final AnnotationResolver annotationResolver; - public ClassDescriptorResolver(JetSemanticServices semanticServices, BindingTrace trace, JetControlFlowDataTraceFactory flowDataTraceFactory) { + public ClassDescriptorResolver(JetSemanticServices semanticServices, BindingTrace trace) { this.semanticServices = semanticServices; this.typeResolver = new TypeResolver(semanticServices, trace, true); this.typeResolverNotCheckingBounds = new TypeResolver(semanticServices, trace, false); this.trace = trace; - this.flowDataTraceFactory = flowDataTraceFactory; this.annotationResolver = new AnnotationResolver(semanticServices, trace); } @@ -813,230 +806,4 @@ public class ClassDescriptorResolver { } } } - - public JetFlowInformationProvider computeFlowData(@NotNull JetElement declaration, @NotNull final JetExpression bodyExpression) { - final JetPseudocodeTrace pseudocodeTrace = flowDataTraceFactory.createTrace(declaration); - final Map pseudocodeMap = new HashMap(); - final Map representativeInstructions = new HashMap(); - final Map loopInfo = Maps.newHashMap(); - JetPseudocodeTrace wrappedTrace = new JetPseudocodeTrace() { - @Override - public void recordControlFlowData(@NotNull JetElement element, @NotNull Pseudocode pseudocode) { - pseudocodeTrace.recordControlFlowData(element, pseudocode); - pseudocodeMap.put(element, pseudocode); - } - - @Override - public void recordRepresentativeInstruction(@NotNull JetElement element, @NotNull Instruction instruction) { - Instruction oldValue = representativeInstructions.put(element, instruction); -// assert oldValue == null : element.getText(); - pseudocodeTrace.recordRepresentativeInstruction(element, instruction); - } - - @Override - public void recordLoopInfo(JetExpression expression, LoopInfo blockInfo) { - loopInfo.put(expression, blockInfo); - pseudocodeTrace.recordLoopInfo(expression, blockInfo); - } - - @Override - public void close() { - pseudocodeTrace.close(); - for (Pseudocode pseudocode : pseudocodeMap.values()) { - pseudocode.postProcess(); - } - } - }; - JetControlFlowInstructionsGenerator instructionsGenerator = new JetControlFlowInstructionsGenerator(wrappedTrace); - new JetControlFlowProcessor(trace, instructionsGenerator).generate(declaration, bodyExpression); - wrappedTrace.close(); - return new JetFlowInformationProvider() { - @Override - public void collectReturnedInformation(@NotNull JetElement subroutine, @NotNull Collection returnedExpressions, @NotNull Collection elementsReturningUnit) { - Pseudocode pseudocode = pseudocodeMap.get(subroutine); - assert pseudocode != null; - - SubroutineExitInstruction exitInstruction = pseudocode.getExitInstruction(); - processPreviousInstructions(exitInstruction, new HashSet(), returnedExpressions, elementsReturningUnit); - } - - @Override - public void collectReturnExpressions(@NotNull JetElement subroutine, @NotNull final Collection returnedExpressions) { - Pseudocode pseudocode = pseudocodeMap.get(subroutine); - assert pseudocode != null; - - SubroutineExitInstruction exitInstruction = pseudocode.getExitInstruction(); - for (Instruction previousInstruction : exitInstruction.getPreviousInstructions()) { - previousInstruction.accept(new InstructionVisitor() { - @Override - public void visitReturnValue(ReturnValueInstruction instruction) { - returnedExpressions.add((JetExpression) instruction.getElement()); - } - - @Override - public void visitReturnNoValue(ReturnNoValueInstruction instruction) { - returnedExpressions.add((JetExpression) instruction.getElement()); - } - - - - @Override - public void visitJump(AbstractJumpInstruction instruction) { - // Nothing - } - - @Override - public void visitInstruction(Instruction instruction) { - if (instruction instanceof JetElementInstruction) { - JetElementInstruction elementInstruction = (JetElementInstruction) instruction; - returnedExpressions.add((JetExpression) elementInstruction.getElement()); - } - else { - throw new IllegalStateException(instruction + " precedes the exit point"); - } - } - }); - } - } - - @Override - public void collectUnreachableExpressions(@NotNull JetElement subroutine, @NotNull Collection unreachableElements) { - Pseudocode pseudocode = pseudocodeMap.get(subroutine); - assert pseudocode != null; - - SubroutineEnterInstruction enterInstruction = pseudocode.getEnterInstruction(); - Set visited = new HashSet(); - collectReachable(enterInstruction, visited, null); - - for (Instruction instruction : pseudocode.getInstructions()) { - if (!visited.contains(instruction) && - instruction instanceof JetElementInstruction && - // TODO : do {return} while (1 > a) - !(instruction instanceof ReadUnitValueInstruction)) { - unreachableElements.add(((JetElementInstruction) instruction).getElement()); - } - } - } - - @Override - public void collectDominatedExpressions(@NotNull JetExpression dominator, @NotNull Collection dominated) { - Instruction dominatorInstruction = representativeInstructions.get(dominator); - if (dominatorInstruction == null) { - return; - } - SubroutineEnterInstruction enterInstruction = dominatorInstruction.getOwner().getEnterInstruction(); - - Set reachable = new HashSet(); - collectReachable(enterInstruction, reachable, null); - - Set reachableWithDominatorProhibited = new HashSet(); - reachableWithDominatorProhibited.add(dominatorInstruction); - collectReachable(enterInstruction, reachableWithDominatorProhibited, null); - - for (Instruction instruction : reachable) { - if (instruction instanceof JetElementInstruction - && reachable.contains(instruction) - && !reachableWithDominatorProhibited.contains(instruction)) { - JetElementInstruction elementInstruction = (JetElementInstruction) instruction; - dominated.add(elementInstruction.getElement()); - } - } - } - - @Override - public boolean isBreakable(JetLoopExpression loop) { - LoopInfo info = loopInfo.get(loop); - Pseudocode.PseudocodeLabel bodyEntryPoint = (Pseudocode.PseudocodeLabel) info.getBodyEntryPoint(); - Pseudocode.PseudocodeLabel exitPoint = (Pseudocode.PseudocodeLabel) info.getExitPoint(); - HashSet visited = Sets.newHashSet(); - Pseudocode.PseudocodeLabel conditionEntryPoint = (Pseudocode.PseudocodeLabel) info.getConditionEntryPoint(); - visited.add(conditionEntryPoint.resolveToInstruction()); - return collectReachable(bodyEntryPoint.resolveToInstruction(), visited, exitPoint.resolveToInstruction()); - } - - public boolean isReachable(JetExpression from, JetExpression to) { - Instruction fromInstr = representativeInstructions.get(from); - assert fromInstr != null : "No representative instruction for " + from.getText(); - Instruction toInstr = representativeInstructions.get(to); - assert toInstr != null : "No representative instruction for " + to.getText(); - - return collectReachable(fromInstr, Sets.newHashSet(), toInstr); - } - }; - } - - private boolean collectReachable(Instruction current, Set visited, @Nullable Instruction lookFor) { - if (!visited.add(current)) return false; - if (current == lookFor) return true; - - for (Instruction nextInstruction : current.getNextInstructions()) { - if (collectReachable(nextInstruction, visited, lookFor)) { - return true; - } - } - return false; - } - - private void processPreviousInstructions(Instruction previousFor, final Set visited, final Collection returnedExpressions, final Collection elementsReturningUnit) { - if (!visited.add(previousFor)) return; - - Collection previousInstructions = previousFor.getPreviousInstructions(); - InstructionVisitor visitor = new InstructionVisitor() { - @Override - public void visitReadValue(ReadValueInstruction instruction) { - returnedExpressions.add((JetExpression) instruction.getElement()); - } - - @Override - public void visitReturnValue(ReturnValueInstruction instruction) { - processPreviousInstructions(instruction, visited, returnedExpressions, elementsReturningUnit); - } - - @Override - public void visitReturnNoValue(ReturnNoValueInstruction instruction) { - elementsReturningUnit.add(instruction.getElement()); - } - - @Override - public void visitSubroutineEnter(SubroutineEnterInstruction instruction) { - elementsReturningUnit.add(instruction.getSubroutine()); - } - - @Override - public void visitUnsupportedElementInstruction(UnsupportedElementInstruction instruction) { -// trace.getErrorHandler().genericError(instruction.getElement().getNode(), "Unsupported by control-flow builder " + instruction.getElement()); - trace.report(UNSUPPORTED.on(instruction.getElement(), "Control-flow builder")); - } - - @Override - public void visitWriteValue(WriteValueInstruction writeValueInstruction) { - elementsReturningUnit.add(writeValueInstruction.getElement()); - } - - @Override - public void visitJump(AbstractJumpInstruction instruction) { - processPreviousInstructions(instruction, visited, returnedExpressions, elementsReturningUnit); - } - - @Override - public void visitReadUnitValue(ReadUnitValueInstruction instruction) { - returnedExpressions.add((JetExpression) instruction.getElement()); - } - - @Override - public void visitInstruction(Instruction instruction) { - if (instruction instanceof JetElementInstructionImpl) { - JetElementInstructionImpl elementInstruction = (JetElementInstructionImpl) instruction; -// trace.getErrorHandler().genericError(elementInstruction.getElement().getNode(), "Unsupported by control-flow builder " + elementInstruction.getElement()); - trace.report(UNSUPPORTED.on(elementInstruction.getElement(), "Control-flow builder")); - } - else { - throw new UnsupportedOperationException(instruction.toString()); - } - } - }; - for (Instruction previousInstruction : previousInstructions) { - previousInstruction.accept(visitor); - } - } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ControlFlowAnalyzer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ControlFlowAnalyzer.java index d4f0dec17dd..80525b8e113 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ControlFlowAnalyzer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ControlFlowAnalyzer.java @@ -3,6 +3,7 @@ package org.jetbrains.jet.lang.resolve; import com.google.common.collect.Lists; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider; +import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptorImpl; @@ -12,7 +13,6 @@ import org.jetbrains.jet.lang.types.JetStandardClasses; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetTypeInferrer; -import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; @@ -25,11 +25,13 @@ import static org.jetbrains.jet.lang.types.JetTypeInferrer.NO_EXPECTED_TYPE; */ public class ControlFlowAnalyzer { private TopDownAnalysisContext context; - private JetTypeInferrer.Services typeInferrer; + private JetTypeInferrer.Services typeInferrerServices; + private final JetControlFlowDataTraceFactory flowDataTraceFactory; - public ControlFlowAnalyzer(TopDownAnalysisContext context) { + public ControlFlowAnalyzer(TopDownAnalysisContext context, JetControlFlowDataTraceFactory flowDataTraceFactory) { this.context = context; - typeInferrer = context.getSemanticServices().getTypeInferrerServices(context.getTrace()); + this.flowDataTraceFactory = flowDataTraceFactory; + this.typeInferrerServices = context.getSemanticServices().getTypeInferrerServices(context.getTrace()); } public void process() { @@ -37,7 +39,9 @@ public class ControlFlowAnalyzer { JetNamedFunction function = entry.getKey(); FunctionDescriptorImpl functionDescriptor = entry.getValue(); - final JetType expectedReturnType = !function.hasBlockBody() && !function.hasDeclaredReturnType() ? NO_EXPECTED_TYPE : functionDescriptor.getReturnType(); + final JetType expectedReturnType = !function.hasBlockBody() && !function.hasDeclaredReturnType() + ? NO_EXPECTED_TYPE + : functionDescriptor.getReturnType(); checkFunction(function, functionDescriptor, expectedReturnType); } @@ -58,7 +62,7 @@ public class ControlFlowAnalyzer { private void checkFunction(JetDeclarationWithBody function, FunctionDescriptor functionDescriptor, final @NotNull JetType expectedReturnType) { JetExpression bodyExpression = function.getBodyExpression(); if (bodyExpression == null) return; - JetFlowInformationProvider flowInformationProvider = context.getClassDescriptorResolver().computeFlowData((JetElement) function, bodyExpression); + JetFlowInformationProvider flowInformationProvider = new JetFlowInformationProvider((JetElement) function, bodyExpression, flowDataTraceFactory, context.getTrace()); final boolean blockBody = function.hasBlockBody(); List unreachableElements = Lists.newArrayList(); @@ -96,7 +100,7 @@ public class ControlFlowAnalyzer { @Override public void visitExpression(JetExpression expression) { if (blockBody && expectedReturnType != NO_EXPECTED_TYPE && !JetStandardClasses.isUnit(expectedReturnType) && !rootUnreachableElements.contains(expression)) { - JetType type = typeInferrer.getType(scope, expression, expectedReturnType); + JetType type = typeInferrerServices.getType(scope, expression, expectedReturnType); if (type == null || !JetStandardClasses.isNothing(type)) { context.getTrace().report(NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY.on(expression)); } @@ -109,6 +113,6 @@ public class ControlFlowAnalyzer { private void checkProperty(JetProperty property) { JetExpression initializer = property.getInitializer(); if (initializer == null) return; - context.getClassDescriptorResolver().computeFlowData(property, initializer); + new JetFlowInformationProvider(property, initializer, flowDataTraceFactory, context.getTrace()); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java index 085f89bb0f1..ca3b4d4148d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java @@ -1,8 +1,8 @@ package org.jetbrains.jet.lang.resolve; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.JetSemanticServices; +import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.scopes.JetScope; @@ -55,13 +55,16 @@ public class TopDownAnalyzer { public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor) { return ClassObjectStatus.NOT_ALLOWED; } - }, Collections.singletonList(object)); + }, Collections.singletonList(object), JetControlFlowDataTraceFactory.EMPTY); } public static void process( @NotNull JetSemanticServices semanticServices, @NotNull BindingTrace trace, - @NotNull JetScope outerScope, NamespaceLike owner, @NotNull List declarations) { + @NotNull JetScope outerScope, + NamespaceLike owner, + @NotNull List declarations, + @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) { TopDownAnalysisContext context = new TopDownAnalysisContext(semanticServices, trace); new TypeHierarchyResolver(context).process(outerScope, owner, declarations); new DeclarationResolver(context).process(); @@ -69,7 +72,7 @@ public class TopDownAnalyzer { new OverrideResolver(context).process(); new BodyResolver(context).resolveBehaviorDeclarationBodies(); new DeclarationsChecker(context).process(); - new ControlFlowAnalyzer(context).process(); + new ControlFlowAnalyzer(context, flowDataTraceFactory).process(); } public static void processStandardLibraryNamespace( diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java index e2789599d2a..dd10cd26edb 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java @@ -8,7 +8,6 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiNameIdentifierOwner; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.psi.*; @@ -21,9 +20,7 @@ import org.jetbrains.jet.lexer.JetTokens; import java.util.*; import static org.jetbrains.jet.lang.diagnostics.Errors.*; -import static org.jetbrains.jet.lang.resolve.BindingContext.CONSTRUCTOR; -import static org.jetbrains.jet.lang.resolve.BindingContext.DESCRIPTOR_TO_DECLARATION; -import static org.jetbrains.jet.lang.resolve.BindingContext.TYPE; +import static org.jetbrains.jet.lang.resolve.BindingContext.*; /** * @author abreslav