Labels resolve removed from control flow graph

This commit is contained in:
svtk
2011-10-12 15:53:41 +04:00
parent 06a7fa1f16
commit 8db6aa4ab4
2 changed files with 86 additions and 72 deletions
@@ -1,10 +1,12 @@
package org.jetbrains.jet.lang.cfg; package org.jetbrains.jet.lang.cfg;
import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.types.JetStandardClasses; import org.jetbrains.jet.lang.types.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
@@ -20,7 +22,7 @@ import static org.jetbrains.jet.lang.diagnostics.Errors.*;
*/ */
public class JetControlFlowProcessor { public class JetControlFlowProcessor {
private final Map<String, Stack<JetElement>> labeledElements = new HashMap<String, Stack<JetElement>>(); // private final Map<String, Stack<JetElement>> labeledElements = new HashMap<String, Stack<JetElement>>();
private final JetControlFlowBuilder builder; private final JetControlFlowBuilder builder;
private final BindingTrace trace; private final BindingTrace trace;
@@ -35,10 +37,10 @@ public class JetControlFlowProcessor {
} }
public void generateSubroutineControlFlow(@NotNull JetElement subroutineElement, @NotNull List<? extends JetElement> body) { public void generateSubroutineControlFlow(@NotNull JetElement subroutineElement, @NotNull List<? extends JetElement> body) {
if (subroutineElement instanceof JetNamedDeclaration) { // if (subroutineElement instanceof JetNamedDeclaration) {
JetNamedDeclaration namedDeclaration = (JetNamedDeclaration) subroutineElement; // JetNamedDeclaration namedDeclaration = (JetNamedDeclaration) subroutineElement;
enterLabeledElement(JetPsiUtil.safeName(namedDeclaration.getName()), namedDeclaration); // enterLabeledElement(JetPsiUtil.safeName(namedDeclaration.getName()), namedDeclaration);
} // }
boolean functionLiteral = subroutineElement instanceof JetFunctionLiteralExpression; boolean functionLiteral = subroutineElement instanceof JetFunctionLiteralExpression;
builder.enterSubroutine(subroutineElement, functionLiteral); builder.enterSubroutine(subroutineElement, functionLiteral);
for (JetElement statement : body) { for (JetElement statement : body) {
@@ -47,50 +49,50 @@ public class JetControlFlowProcessor {
builder.exitSubroutine(subroutineElement, functionLiteral); builder.exitSubroutine(subroutineElement, functionLiteral);
} }
private void enterLabeledElement(@NotNull String labelName, @NotNull JetElement labeledElement) { // private void enterLabeledElement(@NotNull String labelName, @NotNull JetElement labeledElement) {
Stack<JetElement> stack = labeledElements.get(labelName); // Stack<JetElement> stack = labeledElements.get(labelName);
if (stack == null) { // if (stack == null) {
stack = new Stack<JetElement>(); // stack = new Stack<JetElement>();
labeledElements.put(labelName, stack); // labeledElements.put(labelName, stack);
} // }
stack.push(labeledElement); // stack.push(labeledElement);
} // }
//
// private void exitElement(JetElement element) {
// // TODO : really suboptimal
// for (Iterator<Map.Entry<String, Stack<JetElement>>> mapIter = labeledElements.entrySet().iterator(); mapIter.hasNext(); ) {
// Map.Entry<String, Stack<JetElement>> entry = mapIter.next();
// Stack<JetElement> stack = entry.getValue();
// for (Iterator<JetElement> stackIter = stack.iterator(); stackIter.hasNext(); ) {
// JetElement recorded = stackIter.next();
// if (recorded == element) {
// stackIter.remove();
// }
// }
// if (stack.isEmpty()) {
// mapIter.remove();
// }
// }
// }
private void exitElement(JetElement element) { // @Nullable
// TODO : really suboptimal // private JetElement resolveLabel(@NotNull String labelName, @NotNull JetSimpleNameExpression labelExpression, boolean reportUnresolved) {
for (Iterator<Map.Entry<String, Stack<JetElement>>> mapIter = labeledElements.entrySet().iterator(); mapIter.hasNext(); ) { // Stack<JetElement> stack = labeledElements.get(labelName);
Map.Entry<String, Stack<JetElement>> entry = mapIter.next(); // if (stack == null || stack.isEmpty()) {
Stack<JetElement> stack = entry.getValue(); // if (reportUnresolved) {
for (Iterator<JetElement> stackIter = stack.iterator(); stackIter.hasNext(); ) { //// trace.report(UNRESOLVED_REFERENCE.on(labelExpression));
JetElement recorded = stackIter.next(); // }
if (recorded == element) { // return null;
stackIter.remove(); // }
} // else if (stack.size() > 1) {
} //// trace.getErrorHandler().genericWarning(labelExpression.getNode(), "There is more than one label with such a name in this scope");
if (stack.isEmpty()) { //// trace.report(LABEL_NAME_CLASH.on(labelExpression));
mapIter.remove(); // }
} //
} // JetElement result = stack.peek();
} //// trace.record(BindingContext.LABEL_TARGET, labelExpression, result);
// return result;
@Nullable // }
private JetElement resolveLabel(@NotNull String labelName, @NotNull JetSimpleNameExpression labelExpression, boolean reportUnresolved) {
Stack<JetElement> stack = labeledElements.get(labelName);
if (stack == null || stack.isEmpty()) {
if (reportUnresolved) {
// trace.report(UNRESOLVED_REFERENCE.on(labelExpression));
}
return null;
}
else if (stack.size() > 1) {
// trace.getErrorHandler().genericWarning(labelExpression.getNode(), "There is more than one label with such a name in this scope");
// trace.report(LABEL_NAME_CLASH.on(labelExpression));
}
JetElement result = stack.peek();
// trace.record(BindingContext.LABEL_TARGET, labelExpression, result);
return result;
}
private class CFPVisitor extends JetVisitorVoid { private class CFPVisitor extends JetVisitorVoid {
private final boolean inCondition; private final boolean inCondition;
@@ -109,7 +111,7 @@ public class JetControlFlowProcessor {
visitor = new CFPVisitor(inCondition); visitor = new CFPVisitor(inCondition);
} }
element.accept(visitor); element.accept(visitor);
exitElement(element); // exitElement(element);
} }
@Override @Override
@@ -122,12 +124,12 @@ public class JetControlFlowProcessor {
@Override @Override
public void visitThisExpression(JetThisExpression expression) { public void visitThisExpression(JetThisExpression expression) {
JetSimpleNameExpression targetLabel = expression.getTargetLabel(); // JetSimpleNameExpression targetLabel = expression.getTargetLabel();
if (targetLabel != null) { // if (targetLabel != null) {
String labelName = expression.getLabelName(); // String labelName = expression.getLabelName();
assert labelName != null; // assert labelName != null;
resolveLabel(labelName, targetLabel, false); // resolveLabel(labelName, targetLabel, false);
} // }
builder.read(expression); builder.read(expression);
} }
@@ -159,7 +161,7 @@ public class JetControlFlowProcessor {
private void visitLabeledExpression(@NotNull String labelName, @NotNull JetExpression labeledExpression) { private void visitLabeledExpression(@NotNull String labelName, @NotNull JetExpression labeledExpression) {
JetExpression deparenthesized = JetPsiUtil.deparenthesize(labeledExpression); JetExpression deparenthesized = JetPsiUtil.deparenthesize(labeledExpression);
if (deparenthesized != null) { if (deparenthesized != null) {
enterLabeledElement(labelName, deparenthesized); // enterLabeledElement(labelName, deparenthesized);
value(labeledExpression, inCondition); value(labeledExpression, inCondition);
} }
} }
@@ -443,12 +445,20 @@ public class JetControlFlowProcessor {
if (labelName != null) { if (labelName != null) {
JetSimpleNameExpression targetLabel = expression.getTargetLabel(); JetSimpleNameExpression targetLabel = expression.getTargetLabel();
assert targetLabel != null; assert targetLabel != null;
loop = resolveLabel(labelName, targetLabel, true); PsiElement labeledElement = BindingContextUtils.resolveToDeclarationPsiElement(trace.getBindingContext(), targetLabel);
if (!isLoop(loop)) { if (labeledElement instanceof JetLoopExpression) {
// trace.getErrorHandler().genericError(expression.getNode(), "The label '" + targetLabel.getText() + "' does not denote a loop"); loop = (JetLoopExpression) labeledElement;
}
else {
trace.report(NOT_A_LOOP_LABEL.on(expression, targetLabel.getText())); trace.report(NOT_A_LOOP_LABEL.on(expression, targetLabel.getText()));
loop = null; loop = null;
} }
// loop = resolveLabel(labelName, targetLabel, true);
// if (!isLoop(loop)) {
//// trace.getErrorHandler().genericError(expression.getNode(), "The label '" + targetLabel.getText() + "' does not denote a loop");
// trace.report(NOT_A_LOOP_LABEL.on(expression, targetLabel.getText()));
// loop = null;
// }
} }
else { else {
loop = builder.getCurrentLoop(); loop = builder.getCurrentLoop();
@@ -460,11 +470,11 @@ public class JetControlFlowProcessor {
return loop; return loop;
} }
private boolean isLoop(JetElement loop) { // private boolean isLoop(JetElement loop) {
return loop instanceof JetWhileExpression || // return loop instanceof JetWhileExpression ||
loop instanceof JetDoWhileExpression || // loop instanceof JetDoWhileExpression ||
loop instanceof JetForExpression; // loop instanceof JetForExpression;
} // }
@Override @Override
public void visitReturnExpression(JetReturnExpression expression) { public void visitReturnExpression(JetReturnExpression expression) {
@@ -477,7 +487,10 @@ public class JetControlFlowProcessor {
if (labelElement != null) { if (labelElement != null) {
String labelName = expression.getLabelName(); String labelName = expression.getLabelName();
assert labelName != null; assert labelName != null;
subroutine = resolveLabel(labelName, labelElement, true); PsiElement labeledElement = BindingContextUtils.resolveToDeclarationPsiElement(trace.getBindingContext(), labelElement);
assert labeledElement instanceof JetElement;
subroutine = (JetElement) labeledElement;
//subroutine = resolveLabel(labelName, labelElement, true);
} }
else { else {
subroutine = builder.getCurrentSubroutine(); subroutine = builder.getCurrentSubroutine();
@@ -1343,11 +1343,11 @@ public class JetTypeInferrer {
} }
else if (size == 0) { else if (size == 0) {
//todo (first we put to the context, then get from it) //todo (first we put to the context, then get from it)
labelsResolver.resolveLabel(labelName, targetLabel, false, context); JetElement element = labelsResolver.resolveLabel(labelName, targetLabel, false, context);
// This uses the info written by the control flow processor // This uses the info written by the control flow processor
PsiElement psiElement = BindingContextUtils.resolveToDeclarationPsiElement(context.trace.getBindingContext(), targetLabel); //PsiElement psiElement = BindingContextUtils.resolveToDeclarationPsiElement(context.trace.getBindingContext(), targetLabel);
if (psiElement instanceof JetFunctionLiteralExpression) { if (element instanceof JetFunctionLiteralExpression) {
DeclarationDescriptor declarationDescriptor = context.trace.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, psiElement); DeclarationDescriptor declarationDescriptor = context.trace.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, element);
if (declarationDescriptor instanceof FunctionDescriptor) { if (declarationDescriptor instanceof FunctionDescriptor) {
thisReceiver = ((FunctionDescriptor) declarationDescriptor).getReceiver(); thisReceiver = ((FunctionDescriptor) declarationDescriptor).getReceiver();
if (thisReceiver.exists()) { if (thisReceiver.exists()) {
@@ -2911,7 +2911,7 @@ public class JetTypeInferrer {
} }
} }
private void resolveLabel(@NotNull String labelName, @NotNull JetSimpleNameExpression labelExpression, boolean reportUnresolved, TypeInferenceContext context) { private JetElement resolveLabel(@NotNull String labelName, @NotNull JetSimpleNameExpression labelExpression, boolean reportUnresolved, TypeInferenceContext context) {
Collection<DeclarationDescriptor> declarationsByLabel = context.scope.getDeclarationsByLabel(labelName); Collection<DeclarationDescriptor> declarationsByLabel = context.scope.getDeclarationsByLabel(labelName);
int size = declarationsByLabel.size(); int size = declarationsByLabel.size();
@@ -2930,7 +2930,7 @@ public class JetTypeInferrer {
throw new UnsupportedOperationException(); // TODO throw new UnsupportedOperationException(); // TODO
} }
context.trace.record(LABEL_TARGET, labelExpression, element); context.trace.record(LABEL_TARGET, labelExpression, element);
return; return element;
} }
Stack<JetElement> stack = labeledElements.get(labelName); Stack<JetElement> stack = labeledElements.get(labelName);
@@ -2938,7 +2938,7 @@ public class JetTypeInferrer {
if (reportUnresolved) { if (reportUnresolved) {
context.trace.report(UNRESOLVED_REFERENCE.on(labelExpression)); context.trace.report(UNRESOLVED_REFERENCE.on(labelExpression));
} }
return; return null;
} }
else if (stack.size() > 1) { else if (stack.size() > 1) {
context.trace.report(LABEL_NAME_CLASH.on(labelExpression)); context.trace.report(LABEL_NAME_CLASH.on(labelExpression));
@@ -2946,6 +2946,7 @@ public class JetTypeInferrer {
JetElement result = stack.peek(); JetElement result = stack.peek();
context.trace.record(BindingContext.LABEL_TARGET, labelExpression, result); context.trace.record(BindingContext.LABEL_TARGET, labelExpression, result);
return result;
} }
private void resolveCorrespondingLoopLabel(JetLabelQualifiedExpression expression, TypeInferenceContext context) { private void resolveCorrespondingLoopLabel(JetLabelQualifiedExpression expression, TypeInferenceContext context) {