Pseudocode: Track PSI elements which correspond to jump instructions

This commit is contained in:
Alexey Sedunov
2014-04-07 17:41:55 +04:00
parent 103165d674
commit 3952a121fb
15 changed files with 135 additions and 119 deletions
@@ -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);
@@ -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);
@@ -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;
} }
@@ -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);
} }
} }
@@ -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 {
}
@@ -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);
} }
} }
@@ -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
@@ -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);
@@ -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);
} }
} }
@@ -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<!>
}) })
@@ -82,4 +82,4 @@ class C {
} }
a<!UNSAFE_CALL!>.<!>compareTo("2") a<!UNSAFE_CALL!>.<!>compareTo("2")
} }
} }
+2 -2
View File
@@ -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>
}) })