Pseudocode: Track PSI elements which correspond to jump instructions
This commit is contained in:
@@ -63,12 +63,12 @@ public interface JetControlFlowBuilder {
|
|||||||
void bindLabel(@NotNull Label label);
|
void bindLabel(@NotNull Label label);
|
||||||
|
|
||||||
// Jumps
|
// Jumps
|
||||||
void jump(@NotNull Label label);
|
void jump(@NotNull Label label, @NotNull JetElement element);
|
||||||
void jumpOnFalse(@NotNull Label label);
|
void jumpOnFalse(@NotNull Label label, @NotNull JetElement element);
|
||||||
void jumpOnTrue(@NotNull Label label);
|
void jumpOnTrue(@NotNull Label label, @NotNull JetElement element);
|
||||||
void nondeterministicJump(@NotNull Label label); // Maybe, jump to label
|
void nondeterministicJump(@NotNull Label label, @NotNull JetElement element); // Maybe, jump to label
|
||||||
void nondeterministicJump(@NotNull List<Label> label);
|
void nondeterministicJump(@NotNull List<Label> label, @NotNull JetElement element);
|
||||||
void jumpToError();
|
void jumpToError(@NotNull JetElement element);
|
||||||
|
|
||||||
void returnValue(@NotNull JetExpression returnExpression, @NotNull JetElement subroutine);
|
void returnValue(@NotNull JetExpression returnExpression, @NotNull JetElement subroutine);
|
||||||
void returnNoValue(@NotNull JetElement returnExpression, @NotNull JetElement subroutine);
|
void returnNoValue(@NotNull JetElement returnExpression, @NotNull JetElement subroutine);
|
||||||
|
|||||||
+12
-12
@@ -100,33 +100,33 @@ public abstract class JetControlFlowBuilderAdapter implements JetControlFlowBuil
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void jump(@NotNull Label label) {
|
public void jump(@NotNull Label label, @NotNull JetElement element) {
|
||||||
getDelegateBuilder().jump(label);
|
getDelegateBuilder().jump(label, element);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void jumpOnFalse(@NotNull Label label) {
|
public void jumpOnFalse(@NotNull Label label, @NotNull JetElement element) {
|
||||||
getDelegateBuilder().jumpOnFalse(label);
|
getDelegateBuilder().jumpOnFalse(label, element);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void jumpOnTrue(@NotNull Label label) {
|
public void jumpOnTrue(@NotNull Label label, @NotNull JetElement element) {
|
||||||
getDelegateBuilder().jumpOnTrue(label);
|
getDelegateBuilder().jumpOnTrue(label, element);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nondeterministicJump(@NotNull Label label) {
|
public void nondeterministicJump(@NotNull Label label, @NotNull JetElement element) {
|
||||||
getDelegateBuilder().nondeterministicJump(label);
|
getDelegateBuilder().nondeterministicJump(label, element);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nondeterministicJump(@NotNull List<Label> labels) {
|
public void nondeterministicJump(@NotNull List<Label> labels, @NotNull JetElement element) {
|
||||||
getDelegateBuilder().nondeterministicJump(labels);
|
getDelegateBuilder().nondeterministicJump(labels, element);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void jumpToError() {
|
public void jumpToError(@NotNull JetElement element) {
|
||||||
getDelegateBuilder().jumpToError();
|
getDelegateBuilder().jumpToError(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import com.google.common.collect.ImmutableSet;
|
|||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import com.intellij.psi.tree.IElementType;
|
import com.intellij.psi.tree.IElementType;
|
||||||
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
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.cfg.pseudocode.JetControlFlowInstructionsGenerator;
|
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowInstructionsGenerator;
|
||||||
@@ -92,8 +93,12 @@ public class JetControlFlowProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void processLocalDeclaration(@NotNull JetDeclaration subroutine) {
|
private void processLocalDeclaration(@NotNull JetDeclaration subroutine) {
|
||||||
|
JetElement parent = PsiTreeUtil.getParentOfType(subroutine, JetElement.class);
|
||||||
|
assert parent != null;
|
||||||
|
|
||||||
Label afterDeclaration = builder.createUnboundLabel();
|
Label afterDeclaration = builder.createUnboundLabel();
|
||||||
builder.nondeterministicJump(afterDeclaration);
|
|
||||||
|
builder.nondeterministicJump(afterDeclaration, parent);
|
||||||
generate(subroutine);
|
generate(subroutine);
|
||||||
builder.bindLabel(afterDeclaration);
|
builder.bindLabel(afterDeclaration);
|
||||||
}
|
}
|
||||||
@@ -157,7 +162,10 @@ public class JetControlFlowProcessor {
|
|||||||
|
|
||||||
private void checkNothingType(JetElement element) {
|
private void checkNothingType(JetElement element) {
|
||||||
if (!(element instanceof JetExpression)) return;
|
if (!(element instanceof JetExpression)) return;
|
||||||
|
|
||||||
JetExpression expression = JetPsiUtil.deparenthesize((JetExpression) element);
|
JetExpression expression = JetPsiUtil.deparenthesize((JetExpression) element);
|
||||||
|
if (expression == null) return;
|
||||||
|
|
||||||
if (expression instanceof JetStatementExpression || expression instanceof JetTryExpression
|
if (expression instanceof JetStatementExpression || expression instanceof JetTryExpression
|
||||||
|| expression instanceof JetIfExpression || expression instanceof JetWhenExpression) {
|
|| expression instanceof JetIfExpression || expression instanceof JetWhenExpression) {
|
||||||
return;
|
return;
|
||||||
@@ -165,7 +173,7 @@ public class JetControlFlowProcessor {
|
|||||||
|
|
||||||
JetType type = trace.getBindingContext().get(BindingContext.EXPRESSION_TYPE, expression);
|
JetType type = trace.getBindingContext().get(BindingContext.EXPRESSION_TYPE, expression);
|
||||||
if (type != null && KotlinBuiltIns.getInstance().isNothing(type)) {
|
if (type != null && KotlinBuiltIns.getInstance().isNothing(type)) {
|
||||||
builder.jumpToError();
|
builder.jumpToError(expression);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,7 +253,7 @@ public class JetControlFlowProcessor {
|
|||||||
if (operationType == ANDAND) {
|
if (operationType == ANDAND) {
|
||||||
generateInstructions(expression.getLeft(), IN_CONDITION);
|
generateInstructions(expression.getLeft(), IN_CONDITION);
|
||||||
Label resultLabel = builder.createUnboundLabel();
|
Label resultLabel = builder.createUnboundLabel();
|
||||||
builder.jumpOnFalse(resultLabel);
|
builder.jumpOnFalse(resultLabel, expression);
|
||||||
if (right != null) {
|
if (right != null) {
|
||||||
generateInstructions(right, IN_CONDITION);
|
generateInstructions(right, IN_CONDITION);
|
||||||
}
|
}
|
||||||
@@ -257,7 +265,7 @@ public class JetControlFlowProcessor {
|
|||||||
else if (operationType == OROR) {
|
else if (operationType == OROR) {
|
||||||
generateInstructions(expression.getLeft(), IN_CONDITION);
|
generateInstructions(expression.getLeft(), IN_CONDITION);
|
||||||
Label resultLabel = builder.createUnboundLabel();
|
Label resultLabel = builder.createUnboundLabel();
|
||||||
builder.jumpOnTrue(resultLabel);
|
builder.jumpOnTrue(resultLabel, expression);
|
||||||
if (right != null) {
|
if (right != null) {
|
||||||
generateInstructions(right, IN_CONDITION);
|
generateInstructions(right, IN_CONDITION);
|
||||||
}
|
}
|
||||||
@@ -287,7 +295,7 @@ public class JetControlFlowProcessor {
|
|||||||
else if (operationType == ELVIS) {
|
else if (operationType == ELVIS) {
|
||||||
generateInstructions(expression.getLeft(), NOT_IN_CONDITION);
|
generateInstructions(expression.getLeft(), NOT_IN_CONDITION);
|
||||||
Label afterElvis = builder.createUnboundLabel();
|
Label afterElvis = builder.createUnboundLabel();
|
||||||
builder.jumpOnTrue(afterElvis);
|
builder.jumpOnTrue(afterElvis, expression);
|
||||||
if (right != null) {
|
if (right != null) {
|
||||||
generateInstructions(right, NOT_IN_CONDITION);
|
generateInstructions(right, NOT_IN_CONDITION);
|
||||||
}
|
}
|
||||||
@@ -398,7 +406,7 @@ public class JetControlFlowProcessor {
|
|||||||
generateInstructions(condition, IN_CONDITION);
|
generateInstructions(condition, IN_CONDITION);
|
||||||
}
|
}
|
||||||
Label elseLabel = builder.createUnboundLabel();
|
Label elseLabel = builder.createUnboundLabel();
|
||||||
builder.jumpOnFalse(elseLabel);
|
builder.jumpOnFalse(elseLabel, expression);
|
||||||
JetExpression thenBranch = expression.getThen();
|
JetExpression thenBranch = expression.getThen();
|
||||||
if (thenBranch != null) {
|
if (thenBranch != null) {
|
||||||
generateInstructions(thenBranch, context);
|
generateInstructions(thenBranch, context);
|
||||||
@@ -407,7 +415,7 @@ public class JetControlFlowProcessor {
|
|||||||
builder.loadUnit(expression);
|
builder.loadUnit(expression);
|
||||||
}
|
}
|
||||||
Label resultLabel = builder.createUnboundLabel();
|
Label resultLabel = builder.createUnboundLabel();
|
||||||
builder.jump(resultLabel);
|
builder.jump(resultLabel, expression);
|
||||||
builder.bindLabel(elseLabel);
|
builder.bindLabel(elseLabel);
|
||||||
JetExpression elseBranch = expression.getElse();
|
JetExpression elseBranch = expression.getElse();
|
||||||
if (elseBranch != null) {
|
if (elseBranch != null) {
|
||||||
@@ -472,18 +480,18 @@ public class JetControlFlowProcessor {
|
|||||||
Label onException = null;
|
Label onException = null;
|
||||||
if (hasCatches) {
|
if (hasCatches) {
|
||||||
onException = builder.createUnboundLabel("onException");
|
onException = builder.createUnboundLabel("onException");
|
||||||
builder.nondeterministicJump(onException);
|
builder.nondeterministicJump(onException, expression);
|
||||||
}
|
}
|
||||||
Label onExceptionToFinallyBlock = null;
|
Label onExceptionToFinallyBlock = null;
|
||||||
if (finallyBlock != null) {
|
if (finallyBlock != null) {
|
||||||
onExceptionToFinallyBlock = builder.createUnboundLabel("onExceptionToFinallyBlock");
|
onExceptionToFinallyBlock = builder.createUnboundLabel("onExceptionToFinallyBlock");
|
||||||
builder.nondeterministicJump(onExceptionToFinallyBlock);
|
builder.nondeterministicJump(onExceptionToFinallyBlock, expression);
|
||||||
}
|
}
|
||||||
generateInstructions(expression.getTryBlock(), context);
|
generateInstructions(expression.getTryBlock(), context);
|
||||||
|
|
||||||
if (hasCatches) {
|
if (hasCatches) {
|
||||||
Label afterCatches = builder.createUnboundLabel("afterCatches");
|
Label afterCatches = builder.createUnboundLabel("afterCatches");
|
||||||
builder.jump(afterCatches);
|
builder.jump(afterCatches, expression);
|
||||||
|
|
||||||
builder.bindLabel(onException);
|
builder.bindLabel(onException);
|
||||||
LinkedList<Label> catchLabels = Lists.newLinkedList();
|
LinkedList<Label> catchLabels = Lists.newLinkedList();
|
||||||
@@ -492,7 +500,7 @@ public class JetControlFlowProcessor {
|
|||||||
catchLabels.add(builder.createUnboundLabel("catch " + i));
|
catchLabels.add(builder.createUnboundLabel("catch " + i));
|
||||||
}
|
}
|
||||||
if (!catchLabels.isEmpty()) {
|
if (!catchLabels.isEmpty()) {
|
||||||
builder.nondeterministicJump(catchLabels);
|
builder.nondeterministicJump(catchLabels, expression);
|
||||||
}
|
}
|
||||||
boolean isFirst = true;
|
boolean isFirst = true;
|
||||||
for (JetCatchClause catchClause : catchClauses) {
|
for (JetCatchClause catchClause : catchClauses) {
|
||||||
@@ -512,7 +520,7 @@ public class JetControlFlowProcessor {
|
|||||||
if (catchBody != null) {
|
if (catchBody != null) {
|
||||||
generateInstructions(catchBody, NOT_IN_CONDITION);
|
generateInstructions(catchBody, NOT_IN_CONDITION);
|
||||||
}
|
}
|
||||||
builder.jump(afterCatches);
|
builder.jump(afterCatches, expression);
|
||||||
builder.exitLexicalScope(catchClause);
|
builder.exitLexicalScope(catchClause);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -523,10 +531,10 @@ public class JetControlFlowProcessor {
|
|||||||
builder.exitTryFinally();
|
builder.exitTryFinally();
|
||||||
|
|
||||||
Label skipFinallyToErrorBlock = builder.createUnboundLabel("skipFinallyToErrorBlock");
|
Label skipFinallyToErrorBlock = builder.createUnboundLabel("skipFinallyToErrorBlock");
|
||||||
builder.jump(skipFinallyToErrorBlock);
|
builder.jump(skipFinallyToErrorBlock, expression);
|
||||||
builder.bindLabel(onExceptionToFinallyBlock);
|
builder.bindLabel(onExceptionToFinallyBlock);
|
||||||
finallyBlockGenerator.generate();
|
finallyBlockGenerator.generate();
|
||||||
builder.jumpToError();
|
builder.jumpToError(expression);
|
||||||
builder.bindLabel(skipFinallyToErrorBlock);
|
builder.bindLabel(skipFinallyToErrorBlock);
|
||||||
|
|
||||||
finallyBlockGenerator.generate();
|
finallyBlockGenerator.generate();
|
||||||
@@ -545,7 +553,7 @@ public class JetControlFlowProcessor {
|
|||||||
}
|
}
|
||||||
boolean conditionIsTrueConstant = CompileTimeConstantUtils.canBeReducedToBooleanConstant(condition, trace, true);
|
boolean conditionIsTrueConstant = CompileTimeConstantUtils.canBeReducedToBooleanConstant(condition, trace, true);
|
||||||
if (!conditionIsTrueConstant) {
|
if (!conditionIsTrueConstant) {
|
||||||
builder.jumpOnFalse(loopInfo.getExitPoint());
|
builder.jumpOnFalse(loopInfo.getExitPoint(), expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.bindLabel(loopInfo.getBodyEntryPoint());
|
builder.bindLabel(loopInfo.getBodyEntryPoint());
|
||||||
@@ -553,7 +561,7 @@ public class JetControlFlowProcessor {
|
|||||||
if (body != null) {
|
if (body != null) {
|
||||||
generateInstructions(body, NOT_IN_CONDITION);
|
generateInstructions(body, NOT_IN_CONDITION);
|
||||||
}
|
}
|
||||||
builder.jump(loopInfo.getEntryPoint());
|
builder.jump(loopInfo.getEntryPoint(), expression);
|
||||||
builder.exitLoop(expression);
|
builder.exitLoop(expression);
|
||||||
builder.loadUnit(expression);
|
builder.loadUnit(expression);
|
||||||
}
|
}
|
||||||
@@ -574,7 +582,7 @@ public class JetControlFlowProcessor {
|
|||||||
if (condition != null) {
|
if (condition != null) {
|
||||||
generateInstructions(condition, IN_CONDITION);
|
generateInstructions(condition, IN_CONDITION);
|
||||||
}
|
}
|
||||||
builder.jumpOnTrue(loopInfo.getEntryPoint());
|
builder.jumpOnTrue(loopInfo.getEntryPoint(), expression);
|
||||||
builder.exitLoop(expression);
|
builder.exitLoop(expression);
|
||||||
builder.loadUnit(expression);
|
builder.loadUnit(expression);
|
||||||
builder.exitLexicalScope(expression);
|
builder.exitLexicalScope(expression);
|
||||||
@@ -595,7 +603,7 @@ public class JetControlFlowProcessor {
|
|||||||
Label conditionEntryPoint = builder.createUnboundLabel();
|
Label conditionEntryPoint = builder.createUnboundLabel();
|
||||||
|
|
||||||
builder.bindLabel(conditionEntryPoint);
|
builder.bindLabel(conditionEntryPoint);
|
||||||
builder.nondeterministicJump(loopExitPoint);
|
builder.nondeterministicJump(loopExitPoint, expression);
|
||||||
|
|
||||||
LoopInfo loopInfo = builder.enterLoop(expression, loopExitPoint, conditionEntryPoint);
|
LoopInfo loopInfo = builder.enterLoop(expression, loopExitPoint, conditionEntryPoint);
|
||||||
|
|
||||||
@@ -607,7 +615,7 @@ public class JetControlFlowProcessor {
|
|||||||
generateInstructions(body, NOT_IN_CONDITION);
|
generateInstructions(body, NOT_IN_CONDITION);
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.nondeterministicJump(loopInfo.getEntryPoint());
|
builder.nondeterministicJump(loopInfo.getEntryPoint(), expression);
|
||||||
builder.exitLoop(expression);
|
builder.exitLoop(expression);
|
||||||
builder.loadUnit(expression);
|
builder.loadUnit(expression);
|
||||||
builder.exitLexicalScope(expression);
|
builder.exitLexicalScope(expression);
|
||||||
@@ -642,7 +650,7 @@ public class JetControlFlowProcessor {
|
|||||||
JetElement loop = getCorrespondingLoop(expression);
|
JetElement loop = getCorrespondingLoop(expression);
|
||||||
if (loop != null) {
|
if (loop != null) {
|
||||||
checkJumpDoesNotCrossFunctionBoundary(expression, loop);
|
checkJumpDoesNotCrossFunctionBoundary(expression, loop);
|
||||||
builder.jump(builder.getExitPoint(loop));
|
builder.jump(builder.getExitPoint(loop), expression);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -651,7 +659,7 @@ public class JetControlFlowProcessor {
|
|||||||
JetElement loop = getCorrespondingLoop(expression);
|
JetElement loop = getCorrespondingLoop(expression);
|
||||||
if (loop != null) {
|
if (loop != null) {
|
||||||
checkJumpDoesNotCrossFunctionBoundary(expression, loop);
|
checkJumpDoesNotCrossFunctionBoundary(expression, loop);
|
||||||
builder.jump(builder.getEntryPoint(loop));
|
builder.jump(builder.getEntryPoint(loop), expression);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -921,18 +929,18 @@ public class JetControlFlowProcessor {
|
|||||||
JetWhenCondition condition = conditions[i];
|
JetWhenCondition condition = conditions[i];
|
||||||
condition.accept(conditionVisitor, context);
|
condition.accept(conditionVisitor, context);
|
||||||
if (i + 1 < conditions.length) {
|
if (i + 1 < conditions.length) {
|
||||||
builder.nondeterministicJump(bodyLabel);
|
builder.nondeterministicJump(bodyLabel, expression);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isElse) {
|
if (!isElse) {
|
||||||
nextLabel = builder.createUnboundLabel();
|
nextLabel = builder.createUnboundLabel();
|
||||||
builder.nondeterministicJump(nextLabel);
|
builder.nondeterministicJump(nextLabel, expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.bindLabel(bodyLabel);
|
builder.bindLabel(bodyLabel);
|
||||||
generateInstructions(whenEntry.getExpression(), context);
|
generateInstructions(whenEntry.getExpression(), context);
|
||||||
builder.jump(doneLabel);
|
builder.jump(doneLabel, expression);
|
||||||
|
|
||||||
if (!isElse) {
|
if (!isElse) {
|
||||||
builder.bindLabel(nextLabel);
|
builder.bindLabel(nextLabel);
|
||||||
|
|||||||
@@ -243,10 +243,19 @@ public class JetFlowInformationProvider {
|
|||||||
private Set<JetElement> collectUnreachableCode() {
|
private Set<JetElement> collectUnreachableCode() {
|
||||||
Collection<JetElement> unreachableElements = Lists.newArrayList();
|
Collection<JetElement> unreachableElements = Lists.newArrayList();
|
||||||
for (Instruction deadInstruction : pseudocode.getDeadInstructions()) {
|
for (Instruction deadInstruction : pseudocode.getDeadInstructions()) {
|
||||||
if (deadInstruction instanceof JetElementInstruction &&
|
if (!(deadInstruction instanceof JetElementInstruction) || deadInstruction instanceof LoadUnitValueInstruction) continue;
|
||||||
!(deadInstruction instanceof LoadUnitValueInstruction)) {
|
|
||||||
unreachableElements.add(((JetElementInstruction) deadInstruction).getElement());
|
JetElement element = ((JetElementInstruction) deadInstruction).getElement();
|
||||||
|
|
||||||
|
if (deadInstruction instanceof JumpInstruction) {
|
||||||
|
boolean isJumpElement = element instanceof JetBreakExpression
|
||||||
|
|| element instanceof JetContinueExpression
|
||||||
|
|| element instanceof JetReturnExpression
|
||||||
|
|| element instanceof JetThrowExpression;
|
||||||
|
if (!isJumpElement) continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unreachableElements.add(element);
|
||||||
}
|
}
|
||||||
// This is needed in order to highlight only '1 < 2' and not '1', '<' and '2' as well
|
// This is needed in order to highlight only '1 < 2' and not '1', '<' and '2' as well
|
||||||
return JetPsiUtil.findRootExpressions(unreachableElements);
|
return JetPsiUtil.findRootExpressions(unreachableElements);
|
||||||
|
|||||||
+4
-3
@@ -18,16 +18,17 @@ package org.jetbrains.jet.lang.cfg.pseudocode;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.cfg.Label;
|
import org.jetbrains.jet.lang.cfg.Label;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetElement;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
public abstract class AbstractJumpInstruction extends InstructionImpl {
|
public abstract class AbstractJumpInstruction extends JetElementInstructionImpl implements JumpInstruction {
|
||||||
private final Label targetLabel;
|
private final Label targetLabel;
|
||||||
private Instruction resolvedTarget;
|
private Instruction resolvedTarget;
|
||||||
|
|
||||||
public AbstractJumpInstruction(Label targetLabel, LexicalScope lexicalScope) {
|
public AbstractJumpInstruction(@NotNull JetElement element, Label targetLabel, LexicalScope lexicalScope) {
|
||||||
super(lexicalScope);
|
super(element, lexicalScope);
|
||||||
this.targetLabel = targetLabel;
|
this.targetLabel = targetLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-3
@@ -18,6 +18,7 @@ package org.jetbrains.jet.lang.cfg.pseudocode;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.cfg.Label;
|
import org.jetbrains.jet.lang.cfg.Label;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetElement;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -27,8 +28,8 @@ public class ConditionalJumpInstruction extends AbstractJumpInstruction {
|
|||||||
private Instruction nextOnTrue;
|
private Instruction nextOnTrue;
|
||||||
private Instruction nextOnFalse;
|
private Instruction nextOnFalse;
|
||||||
|
|
||||||
public ConditionalJumpInstruction(boolean onTrue, LexicalScope lexicalScope, Label targetLabel) {
|
public ConditionalJumpInstruction(@NotNull JetElement element, boolean onTrue, LexicalScope lexicalScope, Label targetLabel) {
|
||||||
super(targetLabel, lexicalScope);
|
super(element, targetLabel, lexicalScope);
|
||||||
this.onTrue = onTrue;
|
this.onTrue = onTrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,6 +77,6 @@ public class ConditionalJumpInstruction extends AbstractJumpInstruction {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected AbstractJumpInstruction createCopy(@NotNull Label newLabel, @NotNull LexicalScope lexicalScope) {
|
protected AbstractJumpInstruction createCopy(@NotNull Label newLabel, @NotNull LexicalScope lexicalScope) {
|
||||||
return new ConditionalJumpInstruction(onTrue, lexicalScope, newLabel);
|
return new ConditionalJumpInstruction(element, onTrue, lexicalScope, newLabel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-12
@@ -298,21 +298,21 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void jump(@NotNull Label label) {
|
public void jump(@NotNull Label label, @NotNull JetElement element) {
|
||||||
handleJumpInsideTryFinally(label);
|
handleJumpInsideTryFinally(label);
|
||||||
add(new UnconditionalJumpInstruction(label, getCurrentScope()));
|
add(new UnconditionalJumpInstruction(element, label, getCurrentScope()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void jumpOnFalse(@NotNull Label label) {
|
public void jumpOnFalse(@NotNull Label label, @NotNull JetElement element) {
|
||||||
handleJumpInsideTryFinally(label);
|
handleJumpInsideTryFinally(label);
|
||||||
add(new ConditionalJumpInstruction(false, getCurrentScope(), label));
|
add(new ConditionalJumpInstruction(element, false, getCurrentScope(), label));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void jumpOnTrue(@NotNull Label label) {
|
public void jumpOnTrue(@NotNull Label label, @NotNull JetElement element) {
|
||||||
handleJumpInsideTryFinally(label);
|
handleJumpInsideTryFinally(label);
|
||||||
add(new ConditionalJumpInstruction(true, getCurrentScope(), label));
|
add(new ConditionalJumpInstruction(element, true, getCurrentScope(), label));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -321,22 +321,22 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nondeterministicJump(@NotNull Label label) {
|
public void nondeterministicJump(@NotNull Label label, @NotNull JetElement element) {
|
||||||
handleJumpInsideTryFinally(label);
|
handleJumpInsideTryFinally(label);
|
||||||
add(new NondeterministicJumpInstruction(label, getCurrentScope()));
|
add(new NondeterministicJumpInstruction(element, label, getCurrentScope()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nondeterministicJump(@NotNull List<Label> labels) {
|
public void nondeterministicJump(@NotNull List<Label> labels, @NotNull JetElement element) {
|
||||||
//todo
|
//todo
|
||||||
//handleJumpInsideTryFinally(label);
|
//handleJumpInsideTryFinally(label);
|
||||||
add(new NondeterministicJumpInstruction(labels, getCurrentScope()));
|
add(new NondeterministicJumpInstruction(element, labels, getCurrentScope()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void jumpToError() {
|
public void jumpToError(@NotNull JetElement element) {
|
||||||
handleJumpInsideTryFinally(error);
|
handleJumpInsideTryFinally(error);
|
||||||
add(new UnconditionalJumpInstruction(error, getCurrentScope()));
|
add(new UnconditionalJumpInstruction(element, error, getCurrentScope()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -350,6 +350,7 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
|
|||||||
add(new ThrowExceptionInstruction(expression, getCurrentScope(), error));
|
add(new ThrowExceptionInstruction(expression, getCurrentScope(), error));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void exitTryFinally() {
|
public void exitTryFinally() {
|
||||||
BlockInfo pop = allBlocks.pop();
|
BlockInfo pop = allBlocks.pop();
|
||||||
assert pop instanceof TryFinallyBlockInfo;
|
assert pop instanceof TryFinallyBlockInfo;
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* 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.lang.cfg.pseudocode;/**/
|
||||||
|
|
||||||
|
public interface JumpInstruction extends Instruction {
|
||||||
|
}
|
||||||
+7
-6
@@ -20,22 +20,23 @@ import com.google.common.collect.Lists;
|
|||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.cfg.Label;
|
import org.jetbrains.jet.lang.cfg.Label;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetElement;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class NondeterministicJumpInstruction extends InstructionImpl{
|
public class NondeterministicJumpInstruction extends JetElementInstructionImpl implements JumpInstruction {
|
||||||
private Instruction next;
|
private Instruction next;
|
||||||
private final List<Label> targetLabels;
|
private final List<Label> targetLabels;
|
||||||
private final Map<Label, Instruction> resolvedTargets;
|
private final Map<Label, Instruction> resolvedTargets;
|
||||||
|
|
||||||
public NondeterministicJumpInstruction(List<Label> targetLabels, LexicalScope lexicalScope) {
|
public NondeterministicJumpInstruction(@NotNull JetElement element, List<Label> targetLabels, LexicalScope lexicalScope) {
|
||||||
super(lexicalScope);
|
super(element, lexicalScope);
|
||||||
this.targetLabels = Lists.newArrayList(targetLabels);
|
this.targetLabels = Lists.newArrayList(targetLabels);
|
||||||
resolvedTargets = Maps.newLinkedHashMap();
|
resolvedTargets = Maps.newLinkedHashMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
public NondeterministicJumpInstruction(Label targetLabel, LexicalScope lexicalScope) {
|
public NondeterministicJumpInstruction(@NotNull JetElement element, Label targetLabel, LexicalScope lexicalScope) {
|
||||||
this(Lists.newArrayList(targetLabel), lexicalScope);
|
this(element, Lists.newArrayList(targetLabel), lexicalScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Label> getTargetLabels() {
|
public List<Label> getTargetLabels() {
|
||||||
@@ -103,6 +104,6 @@ public class NondeterministicJumpInstruction extends InstructionImpl{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Instruction createCopy(@NotNull List<Label> newTargetLabels) {
|
private Instruction createCopy(@NotNull List<Label> newTargetLabels) {
|
||||||
return new NondeterministicJumpInstruction(newTargetLabels, lexicalScope);
|
return new NondeterministicJumpInstruction(getElement(), newTargetLabels, lexicalScope);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-11
@@ -21,18 +21,8 @@ import org.jetbrains.jet.lang.cfg.Label;
|
|||||||
import org.jetbrains.jet.lang.psi.JetElement;
|
import org.jetbrains.jet.lang.psi.JetElement;
|
||||||
|
|
||||||
public class ReturnNoValueInstruction extends AbstractJumpInstruction implements ReturnInstruction {
|
public class ReturnNoValueInstruction extends AbstractJumpInstruction implements ReturnInstruction {
|
||||||
|
|
||||||
private final JetElement element;
|
|
||||||
|
|
||||||
public ReturnNoValueInstruction(@NotNull JetElement element, LexicalScope lexicalScope, Label targetLabel) {
|
public ReturnNoValueInstruction(@NotNull JetElement element, LexicalScope lexicalScope, Label targetLabel) {
|
||||||
super(targetLabel, lexicalScope);
|
super(element, targetLabel, lexicalScope);
|
||||||
this.element = element;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public JetElement getElement() {
|
|
||||||
return element;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+6
-14
@@ -18,20 +18,18 @@ package org.jetbrains.jet.lang.cfg.pseudocode;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.cfg.Label;
|
import org.jetbrains.jet.lang.cfg.Label;
|
||||||
import org.jetbrains.jet.lang.psi.JetElement;
|
|
||||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||||
|
|
||||||
public class ReturnValueInstruction extends AbstractJumpInstruction implements ReturnInstruction {
|
public class ReturnValueInstruction extends AbstractJumpInstruction implements ReturnInstruction {
|
||||||
|
public ReturnValueInstruction(
|
||||||
private final JetElement element;
|
@NotNull JetExpression returnExpression,
|
||||||
|
@NotNull LexicalScope lexicalScope,
|
||||||
public ReturnValueInstruction(@NotNull JetExpression returnExpression, @NotNull LexicalScope lexicalScope, @NotNull Label targetLabel) {
|
@NotNull Label targetLabel) {
|
||||||
super(targetLabel, lexicalScope);
|
super(returnExpression, targetLabel, lexicalScope);
|
||||||
this.element = returnExpression;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accept(InstructionVisitor visitor) {
|
public void accept(@NotNull InstructionVisitor visitor) {
|
||||||
visitor.visitReturnValue(this);
|
visitor.visitReturnValue(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,12 +43,6 @@ public class ReturnValueInstruction extends AbstractJumpInstruction implements R
|
|||||||
return "ret(*) " + getTargetLabel();
|
return "ret(*) " + getTargetLabel();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public JetElement getElement() {
|
|
||||||
return element;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected AbstractJumpInstruction createCopy(@NotNull Label newLabel, @NotNull LexicalScope lexicalScope) {
|
protected AbstractJumpInstruction createCopy(@NotNull Label newLabel, @NotNull LexicalScope lexicalScope) {
|
||||||
return new ReturnValueInstruction((JetExpression) element, lexicalScope, newLabel);
|
return new ReturnValueInstruction((JetExpression) element, lexicalScope, newLabel);
|
||||||
|
|||||||
+9
-15
@@ -18,26 +18,20 @@ package org.jetbrains.jet.lang.cfg.pseudocode;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.cfg.Label;
|
import org.jetbrains.jet.lang.cfg.Label;
|
||||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
|
||||||
import org.jetbrains.jet.lang.psi.JetThrowExpression;
|
import org.jetbrains.jet.lang.psi.JetThrowExpression;
|
||||||
|
|
||||||
public class ThrowExceptionInstruction extends AbstractJumpInstruction implements JetElementInstruction {
|
public class ThrowExceptionInstruction extends AbstractJumpInstruction {
|
||||||
private final JetThrowExpression expression;
|
public ThrowExceptionInstruction(
|
||||||
|
@NotNull JetThrowExpression expression,
|
||||||
public ThrowExceptionInstruction(@NotNull JetThrowExpression expression, @NotNull LexicalScope lexicalScope, @NotNull Label errorLabel) {
|
@NotNull LexicalScope lexicalScope,
|
||||||
super(errorLabel, lexicalScope);
|
@NotNull Label errorLabel
|
||||||
this.expression = expression;
|
) {
|
||||||
}
|
super(expression, errorLabel, lexicalScope);
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public JetExpression getElement() {
|
|
||||||
return expression;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "throw (" + expression.getText() + ")";
|
return "throw (" + element.getText() + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -52,6 +46,6 @@ public class ThrowExceptionInstruction extends AbstractJumpInstruction implement
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected AbstractJumpInstruction createCopy(@NotNull Label newLabel, @NotNull LexicalScope lexicalScope) {
|
protected AbstractJumpInstruction createCopy(@NotNull Label newLabel, @NotNull LexicalScope lexicalScope) {
|
||||||
return new ThrowExceptionInstruction(expression, lexicalScope, newLabel);
|
return new ThrowExceptionInstruction((JetThrowExpression) element, lexicalScope, newLabel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-5
@@ -18,12 +18,11 @@ package org.jetbrains.jet.lang.cfg.pseudocode;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.cfg.Label;
|
import org.jetbrains.jet.lang.cfg.Label;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetElement;
|
||||||
|
|
||||||
public class UnconditionalJumpInstruction extends AbstractJumpInstruction {
|
public class UnconditionalJumpInstruction extends AbstractJumpInstruction {
|
||||||
|
public UnconditionalJumpInstruction(@NotNull JetElement element, Label targetLabel, @NotNull LexicalScope lexicalScope) {
|
||||||
|
super(element, targetLabel, lexicalScope);
|
||||||
public UnconditionalJumpInstruction(Label targetLabel, @NotNull LexicalScope lexicalScope) {
|
|
||||||
super(targetLabel, lexicalScope);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -43,6 +42,6 @@ public class UnconditionalJumpInstruction extends AbstractJumpInstruction {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected AbstractJumpInstruction createCopy(@NotNull Label newLabel, @NotNull LexicalScope lexicalScope) {
|
protected AbstractJumpInstruction createCopy(@NotNull Label newLabel, @NotNull LexicalScope lexicalScope) {
|
||||||
return new UnconditionalJumpInstruction(newLabel, lexicalScope);
|
return new UnconditionalJumpInstruction(element, newLabel, lexicalScope);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ class C {
|
|||||||
@a {
|
@a {
|
||||||
<!NOT_A_LOOP_LABEL!>break@f<!>
|
<!NOT_A_LOOP_LABEL!>break@f<!>
|
||||||
break
|
break
|
||||||
break@b
|
<!UNREACHABLE_CODE!>break@b<!>
|
||||||
<!NOT_A_LOOP_LABEL!>break@a<!>
|
<!NOT_A_LOOP_LABEL!>break@a<!>
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -15,7 +15,7 @@ class C {
|
|||||||
@a {
|
@a {
|
||||||
<!NOT_A_LOOP_LABEL!>continue@f<!>
|
<!NOT_A_LOOP_LABEL!>continue@f<!>
|
||||||
continue
|
continue
|
||||||
continue@b
|
<!UNREACHABLE_CODE!>continue@b<!>
|
||||||
<!NOT_A_LOOP_LABEL!>continue@a<!>
|
<!NOT_A_LOOP_LABEL!>continue@a<!>
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ class C {
|
|||||||
@a {
|
@a {
|
||||||
<error>break@f</error>
|
<error>break@f</error>
|
||||||
break
|
break
|
||||||
break@b
|
<warning>break@b</warning>
|
||||||
<error>break@a</error>
|
<error>break@a</error>
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -15,7 +15,7 @@ class C {
|
|||||||
@a {
|
@a {
|
||||||
<error>continue@f</error>
|
<error>continue@f</error>
|
||||||
continue
|
continue
|
||||||
continue@b
|
<warning>continue@b</warning>
|
||||||
<error>continue@a</error>
|
<error>continue@a</error>
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user