More cases for nullability analysis
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
package org.jetbrains.jet.lang.cfg;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public abstract class BlockInfo {}
|
||||
@@ -0,0 +1,30 @@
|
||||
package org.jetbrains.jet.lang.cfg;
|
||||
|
||||
import org.jetbrains.jet.lang.psi.JetElement;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class BreakableBlockInfo extends BlockInfo {
|
||||
private final JetElement element;
|
||||
private final Label entryPoint;
|
||||
private final Label exitPoint;
|
||||
|
||||
public BreakableBlockInfo(JetElement element, Label entryPoint, Label exitPoint) {
|
||||
this.element = element;
|
||||
this.entryPoint = entryPoint;
|
||||
this.exitPoint = exitPoint;
|
||||
}
|
||||
|
||||
public JetElement getElement() {
|
||||
return element;
|
||||
}
|
||||
|
||||
public Label getEntryPoint() {
|
||||
return entryPoint;
|
||||
}
|
||||
|
||||
public Label getExitPoint() {
|
||||
return exitPoint;
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,7 @@ public interface JetControlFlowBuilder {
|
||||
Label getExitPoint(@NotNull JetElement labelElement);
|
||||
|
||||
// Loops
|
||||
Label enterLoop(@NotNull JetExpression expression, Label loopExitPoint);
|
||||
LoopInfo enterLoop(@NotNull JetExpression expression, @Nullable Label loopExitPoint, @Nullable Label conditionEntryPoint);
|
||||
|
||||
void exitLoop(@NotNull JetExpression expression);
|
||||
@Nullable
|
||||
|
||||
@@ -73,8 +73,8 @@ public class JetControlFlowBuilderAdapter implements JetControlFlowBuilder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Label enterLoop(@NotNull JetExpression expression, Label loopExitPoint) {
|
||||
return builder.enterLoop(expression, loopExitPoint);
|
||||
public LoopInfo enterLoop(@NotNull JetExpression expression, Label loopExitPoint, Label conditionEntryPoint) {
|
||||
return builder.enterLoop(expression, loopExitPoint, conditionEntryPoint);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -350,35 +350,40 @@ public class JetControlFlowProcessor {
|
||||
|
||||
@Override
|
||||
public void visitWhileExpression(JetWhileExpression expression) {
|
||||
Label loopExitPoint = builder.createUnboundLabel();
|
||||
Label loopEntryPoint = builder.enterLoop(expression, loopExitPoint);
|
||||
LoopInfo loopInfo = builder.enterLoop(expression, null, null);
|
||||
|
||||
builder.bindLabel(loopInfo.getConditionEntryPoint());
|
||||
JetExpression condition = expression.getCondition();
|
||||
if (condition != null) {
|
||||
value(condition, false, true);
|
||||
}
|
||||
builder.jumpOnFalse(loopExitPoint);
|
||||
builder.jumpOnFalse(loopInfo.getExitPoint());
|
||||
|
||||
builder.bindLabel(loopInfo.getBodyEntryPoint());
|
||||
JetExpression body = expression.getBody();
|
||||
if (body != null) {
|
||||
value(body, true, false);
|
||||
}
|
||||
builder.jump(loopEntryPoint);
|
||||
builder.jump(loopInfo.getEntryPoint());
|
||||
builder.exitLoop(expression);
|
||||
builder.readUnit(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitDoWhileExpression(JetDoWhileExpression expression) {
|
||||
Label loopExitPoint = builder.createUnboundLabel();
|
||||
Label loopEntryPoint = builder.enterLoop(expression, loopExitPoint);
|
||||
LoopInfo loopInfo = builder.enterLoop(expression, null, null);
|
||||
|
||||
builder.bindLabel(loopInfo.getBodyEntryPoint());
|
||||
JetExpression body = expression.getBody();
|
||||
if (body != null) {
|
||||
value(body, true, false);
|
||||
}
|
||||
builder.bindLabel(loopInfo.getConditionEntryPoint());
|
||||
JetExpression condition = expression.getCondition();
|
||||
if (condition != null) {
|
||||
value(condition, false, true);
|
||||
}
|
||||
builder.jumpOnTrue(loopEntryPoint);
|
||||
builder.jumpOnTrue(loopInfo.getEntryPoint());
|
||||
builder.exitLoop(expression);
|
||||
builder.readUnit(expression);
|
||||
}
|
||||
@@ -391,13 +396,20 @@ public class JetControlFlowProcessor {
|
||||
}
|
||||
// TODO : primitive cases
|
||||
Label loopExitPoint = builder.createUnboundLabel();
|
||||
Label conditionEntryPoint = builder.createUnboundLabel();
|
||||
|
||||
builder.bindLabel(conditionEntryPoint);
|
||||
builder.nondeterministicJump(loopExitPoint);
|
||||
Label loopEntryPoint = builder.enterLoop(expression, loopExitPoint);
|
||||
|
||||
LoopInfo loopInfo = builder.enterLoop(expression, loopExitPoint, conditionEntryPoint);
|
||||
|
||||
builder.bindLabel(loopInfo.getBodyEntryPoint());
|
||||
JetExpression body = expression.getBody();
|
||||
if (body != null) {
|
||||
value(body, true, false);
|
||||
}
|
||||
builder.nondeterministicJump(loopEntryPoint);
|
||||
|
||||
builder.nondeterministicJump(loopInfo.getEntryPoint());
|
||||
builder.exitLoop(expression);
|
||||
builder.readUnit(expression);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.jetbrains.jet.lang.cfg;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.psi.JetElement;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetLoopExpression;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@@ -25,6 +26,12 @@ public interface JetFlowInformationProvider {
|
||||
public void collectDominatedExpressions(@NotNull JetExpression dominator, @NotNull Collection<JetElement> dominated) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBreakable(JetLoopExpression loop) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
JetFlowInformationProvider NONE = new JetFlowInformationProvider() {
|
||||
@@ -42,6 +49,12 @@ public interface JetFlowInformationProvider {
|
||||
public void collectDominatedExpressions(@NotNull JetExpression dominator, @NotNull Collection<JetElement> dominated) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBreakable(JetLoopExpression loop) {
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
void collectReturnedInformation(
|
||||
@@ -56,4 +69,6 @@ public interface JetFlowInformationProvider {
|
||||
void collectDominatedExpressions(
|
||||
@NotNull JetExpression dominator,
|
||||
@NotNull Collection<JetElement> dominated);
|
||||
|
||||
boolean isBreakable(JetLoopExpression loop);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package org.jetbrains.jet.lang.cfg;
|
||||
|
||||
import org.jetbrains.jet.lang.psi.JetElement;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class LoopInfo extends BreakableBlockInfo {
|
||||
private final Label bodyEntryPoint;
|
||||
private final Label conditionEntryPoint;
|
||||
|
||||
public LoopInfo(JetElement element, Label entryPoint, Label exitPoint, Label bodyEntryPoint, Label conditionEntryPoint) {
|
||||
super(element, entryPoint, exitPoint);
|
||||
this.bodyEntryPoint = bodyEntryPoint;
|
||||
this.conditionEntryPoint = conditionEntryPoint;
|
||||
}
|
||||
|
||||
public Label getBodyEntryPoint() {
|
||||
return bodyEntryPoint;
|
||||
}
|
||||
|
||||
public Label getConditionEntryPoint() {
|
||||
return conditionEntryPoint;
|
||||
}
|
||||
}
|
||||
+11
-33
@@ -1,10 +1,7 @@
|
||||
package org.jetbrains.jet.lang.cfg.pseudocode;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.cfg.GenerationTrigger;
|
||||
import org.jetbrains.jet.lang.cfg.JetControlFlowBuilder;
|
||||
import org.jetbrains.jet.lang.cfg.JetControlFlowBuilderAdapter;
|
||||
import org.jetbrains.jet.lang.cfg.Label;
|
||||
import org.jetbrains.jet.lang.cfg.*;
|
||||
import org.jetbrains.jet.lang.psi.JetElement;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression;
|
||||
@@ -101,14 +98,20 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Label enterLoop(@NotNull JetExpression expression, Label loopExitPoint) {
|
||||
public final LoopInfo enterLoop(@NotNull JetExpression expression, Label loopExitPoint, Label conditionEntryPoint) {
|
||||
Label label = createUnboundLabel();
|
||||
bindLabel(label);
|
||||
BreakableBlockInfo blockInfo = new BreakableBlockInfo(expression, label, loopExitPoint);
|
||||
LoopInfo blockInfo = new LoopInfo(
|
||||
expression,
|
||||
label,
|
||||
loopExitPoint != null ? loopExitPoint : createUnboundLabel(),
|
||||
createUnboundLabel(),
|
||||
conditionEntryPoint != null ? conditionEntryPoint : createUnboundLabel());
|
||||
loopInfo.push(blockInfo);
|
||||
elementToBlockInfo.put(expression, blockInfo);
|
||||
allBlocks.push(blockInfo);
|
||||
return label;
|
||||
trace.recordLoopInfo(expression, blockInfo);
|
||||
return blockInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -265,9 +268,7 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
|
||||
}
|
||||
}
|
||||
|
||||
private static abstract class BlockInfo {}
|
||||
|
||||
private static class TryFinallyBlockInfo extends BlockInfo {
|
||||
public static class TryFinallyBlockInfo extends BlockInfo {
|
||||
private final GenerationTrigger finallyBlock;
|
||||
|
||||
private TryFinallyBlockInfo(GenerationTrigger finallyBlock) {
|
||||
@@ -279,27 +280,4 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
|
||||
}
|
||||
}
|
||||
|
||||
private static class BreakableBlockInfo extends BlockInfo {
|
||||
private final JetElement element;
|
||||
private final Label entryPoint;
|
||||
private final Label exitPoint;
|
||||
|
||||
private BreakableBlockInfo(JetElement element, Label entryPoint, Label exitPoint) {
|
||||
this.element = element;
|
||||
this.entryPoint = entryPoint;
|
||||
this.exitPoint = exitPoint;
|
||||
}
|
||||
|
||||
public JetElement getElement() {
|
||||
return element;
|
||||
}
|
||||
|
||||
public Label getEntryPoint() {
|
||||
return entryPoint;
|
||||
}
|
||||
|
||||
public Label getExitPoint() {
|
||||
return exitPoint;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package org.jetbrains.jet.lang.cfg.pseudocode;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.cfg.LoopInfo;
|
||||
import org.jetbrains.jet.lang.psi.JetElement;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
@@ -21,10 +23,16 @@ public interface JetPseudocodeTrace {
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recordLoopInfo(JetExpression expression, LoopInfo blockInfo) {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
void recordControlFlowData(@NotNull JetElement element, @NotNull Pseudocode pseudocode);
|
||||
void recordRepresentativeInstruction(@NotNull JetElement element, @NotNull Instruction instruction);
|
||||
void close();
|
||||
|
||||
void recordLoopInfo(JetExpression expression, LoopInfo blockInfo);
|
||||
}
|
||||
|
||||
@@ -46,6 +46,11 @@ public class Pseudocode {
|
||||
return instructions.subList(getTargetInstructionIndex(), instructions.size());
|
||||
}
|
||||
|
||||
public Instruction resolveToInstruction() {
|
||||
assert targetInstructionIndex != null;
|
||||
return instructions.get(targetInstructionIndex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private final List<Instruction> instructions = new ArrayList<Instruction>();
|
||||
|
||||
@@ -2,6 +2,7 @@ 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 org.jetbrains.annotations.NotNull;
|
||||
@@ -9,6 +10,7 @@ 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.psi.*;
|
||||
@@ -721,6 +723,7 @@ public class ClassDescriptorResolver {
|
||||
final JetPseudocodeTrace pseudocodeTrace = flowDataTraceFactory.createTrace(declaration);
|
||||
final Map<JetElement, Pseudocode> pseudocodeMap = new HashMap<JetElement, Pseudocode>();
|
||||
final Map<JetElement, Instruction> representativeInstructions = new HashMap<JetElement, Instruction>();
|
||||
final Map<JetExpression, LoopInfo> loopInfo = Maps.newHashMap();
|
||||
JetPseudocodeTrace wrappedTrace = new JetPseudocodeTrace() {
|
||||
@Override
|
||||
public void recordControlFlowData(@NotNull JetElement element, @NotNull Pseudocode pseudocode) {
|
||||
@@ -732,6 +735,13 @@ public class ClassDescriptorResolver {
|
||||
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
|
||||
@@ -762,7 +772,7 @@ public class ClassDescriptorResolver {
|
||||
|
||||
SubroutineEnterInstruction enterInstruction = pseudocode.getEnterInstruction();
|
||||
Set<Instruction> visited = new HashSet<Instruction>();
|
||||
collectReachable(enterInstruction, visited);
|
||||
collectReachable(enterInstruction, visited, null);
|
||||
|
||||
for (Instruction instruction : pseudocode.getInstructions()) {
|
||||
if (!visited.contains(instruction) &&
|
||||
@@ -783,11 +793,11 @@ public class ClassDescriptorResolver {
|
||||
SubroutineEnterInstruction enterInstruction = dominatorInstruction.getOwner().getEnterInstruction();
|
||||
|
||||
Set<Instruction> reachable = new HashSet<Instruction>();
|
||||
collectReachable(enterInstruction, reachable);
|
||||
collectReachable(enterInstruction, reachable, null);
|
||||
|
||||
Set<Instruction> reachableWithDominatorProhibited = new HashSet<Instruction>();
|
||||
reachableWithDominatorProhibited.add(dominatorInstruction);
|
||||
collectReachable(enterInstruction, reachableWithDominatorProhibited);
|
||||
collectReachable(enterInstruction, reachableWithDominatorProhibited, null);
|
||||
|
||||
for (Instruction instruction : reachable) {
|
||||
if (instruction instanceof JetElementInstruction
|
||||
@@ -798,15 +808,39 @@ public class ClassDescriptorResolver {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@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<Instruction> 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.<Instruction>newHashSet(), toInstr);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void collectReachable(Instruction current, Set<Instruction> visited) {
|
||||
if (!visited.add(current)) return;
|
||||
private boolean collectReachable(Instruction current, Set<Instruction> visited, @Nullable Instruction lookFor) {
|
||||
if (!visited.add(current)) return false;
|
||||
if (current == lookFor) return true;
|
||||
|
||||
for (Instruction nextInstruction : current.getNextInstructions()) {
|
||||
collectReachable(nextInstruction, visited);
|
||||
if (collectReachable(nextInstruction, visited, lookFor)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void processPreviousInstructions(Instruction previousFor, final Set<Instruction> visited, final Collection<JetExpression> returnedExpressions, final Collection<JetElement> elementsReturningUnit) {
|
||||
|
||||
@@ -1307,12 +1307,16 @@ public class JetTypeInferrer {
|
||||
}
|
||||
}
|
||||
else if (thenBranch == null) {
|
||||
getType(scope, elseBranch, true, elseInfo);
|
||||
JetType type = getType(scope, elseBranch, true, elseInfo);
|
||||
if (type != null && JetStandardClasses.isNothing(type)) {
|
||||
resultDataFlowInfo = thenInfo;
|
||||
}
|
||||
result = JetStandardClasses.getUnitType();
|
||||
}
|
||||
else {
|
||||
JetType thenType = getType(scope, thenBranch, true, thenInfo);
|
||||
JetType elseType = getType(scope, elseBranch, true, elseInfo);
|
||||
|
||||
if (thenType == null) {
|
||||
result = elseType;
|
||||
}
|
||||
@@ -1322,10 +1326,22 @@ public class JetTypeInferrer {
|
||||
else {
|
||||
result = semanticServices.getTypeChecker().commonSupertype(Arrays.asList(thenType, elseType));
|
||||
}
|
||||
|
||||
boolean jumpInThen = thenType != null && JetStandardClasses.isNothing(thenType);
|
||||
boolean jumpInElse = elseType != null && JetStandardClasses.isNothing(elseType);
|
||||
|
||||
if (jumpInThen && !jumpInElse) {
|
||||
resultDataFlowInfo = elseInfo;
|
||||
}
|
||||
else if (jumpInElse && !jumpInThen) {
|
||||
resultDataFlowInfo = thenInfo;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private DataFlowInfo extractDataFlowInfoFromCondition(@NotNull JetExpression condition, final boolean conditionValue) {
|
||||
private DataFlowInfo extractDataFlowInfoFromCondition(@Nullable JetExpression condition, final boolean conditionValue) {
|
||||
if (condition == null) return dataFlowInfo;
|
||||
final DataFlowInfo[] result = new DataFlowInfo[] {dataFlowInfo};
|
||||
condition.accept(new JetVisitor() {
|
||||
@Override
|
||||
@@ -1410,7 +1426,9 @@ public class JetTypeInferrer {
|
||||
DataFlowInfo conditionInfo = condition == null ? dataFlowInfo : extractDataFlowInfoFromCondition(condition, true);
|
||||
getType(scope, body, true, conditionInfo);
|
||||
}
|
||||
resultDataFlowInfo = condition == null ? null : extractDataFlowInfoFromCondition(condition, false);
|
||||
if (!flowInformationProvider.isBreakable(expression)) {
|
||||
resultDataFlowInfo = extractDataFlowInfoFromCondition(condition, false);
|
||||
}
|
||||
result = JetStandardClasses.getUnitType();
|
||||
}
|
||||
|
||||
@@ -1434,7 +1452,11 @@ public class JetTypeInferrer {
|
||||
conditionScope = writableScope;
|
||||
getBlockReturnedTypeWithWritableScope(writableScope, Collections.singletonList(body), dataFlowInfo);
|
||||
}
|
||||
checkCondition(conditionScope, expression.getCondition());
|
||||
JetExpression condition = expression.getCondition();
|
||||
checkCondition(conditionScope, condition);
|
||||
if (!flowInformationProvider.isBreakable(expression)) {
|
||||
resultDataFlowInfo = extractDataFlowInfoFromCondition(condition, false);
|
||||
}
|
||||
result = JetStandardClasses.getUnitType();
|
||||
}
|
||||
|
||||
@@ -1918,6 +1940,7 @@ public class JetTypeInferrer {
|
||||
if (receiverType != null) {
|
||||
FunctionDescriptor functionDescriptor = lookupFunction(scope, expression, "get", receiverType, argumentTypes, true);
|
||||
if (functionDescriptor != null) {
|
||||
// checkNullSafety(receiverType, expression.getIndexExpressions().get(0).getNode(), functionDescriptor);
|
||||
result = functionDescriptor.getUnsubstitutedReturnType();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,26 +224,28 @@ fun t3() {
|
||||
---------------------
|
||||
l0:
|
||||
<START>
|
||||
l3:
|
||||
l2:
|
||||
l5:
|
||||
r(true)
|
||||
jf(l2)
|
||||
jmp?(l4)
|
||||
jf(l3)
|
||||
l4:
|
||||
jmp?(l6)
|
||||
r(1)
|
||||
r(2)
|
||||
r(3)
|
||||
r(>)
|
||||
r(2 > 3)
|
||||
jf(l5)
|
||||
r(2)
|
||||
jmp(l2)
|
||||
jmp(l6)
|
||||
l5:
|
||||
read (Unit)
|
||||
l4:
|
||||
l6:
|
||||
jf(l7)
|
||||
r(2)
|
||||
jmp(l3)
|
||||
l2:
|
||||
jmp(l8)
|
||||
l7:
|
||||
read (Unit)
|
||||
l6:
|
||||
l8:
|
||||
r(2)
|
||||
jmp(l2)
|
||||
l3:
|
||||
read (Unit)
|
||||
l1:
|
||||
<END>
|
||||
@@ -268,22 +270,24 @@ fun t3() {
|
||||
l0:
|
||||
<START>
|
||||
jmp?(l2)
|
||||
l4:
|
||||
l3:
|
||||
l6:
|
||||
r(true)
|
||||
jf(l3)
|
||||
jf(l4)
|
||||
l5:
|
||||
r(1)
|
||||
r(2)
|
||||
r(3)
|
||||
r(>)
|
||||
r(2 > 3)
|
||||
jf(l5)
|
||||
jmp(l3)
|
||||
jmp(l6)
|
||||
l5:
|
||||
read (Unit)
|
||||
l6:
|
||||
jf(l7)
|
||||
jmp(l4)
|
||||
l3:
|
||||
jmp(l8)
|
||||
l7:
|
||||
read (Unit)
|
||||
l8:
|
||||
jmp(l3)
|
||||
l4:
|
||||
read (Unit)
|
||||
r(5)
|
||||
l2:
|
||||
@@ -310,22 +314,24 @@ fun t3() {
|
||||
l0:
|
||||
<START>
|
||||
jmp?(l2)
|
||||
l4:
|
||||
l3:
|
||||
l6:
|
||||
r(true)
|
||||
jf(l3)
|
||||
jf(l4)
|
||||
l5:
|
||||
r(1)
|
||||
r(2)
|
||||
r(3)
|
||||
r(>)
|
||||
r(2 > 3)
|
||||
jf(l5)
|
||||
jmp(l3)
|
||||
jmp(l6)
|
||||
l5:
|
||||
read (Unit)
|
||||
l6:
|
||||
jf(l7)
|
||||
jmp(l4)
|
||||
l3:
|
||||
jmp(l8)
|
||||
l7:
|
||||
read (Unit)
|
||||
l8:
|
||||
jmp(l3)
|
||||
l4:
|
||||
read (Unit)
|
||||
l2:
|
||||
r(2)
|
||||
@@ -354,24 +360,26 @@ l0:
|
||||
r(a)
|
||||
r(..)
|
||||
r(1..a)
|
||||
jmp?(l2)
|
||||
l3:
|
||||
jmp?(l4)
|
||||
jmp?(l2)
|
||||
l4:
|
||||
l5:
|
||||
jmp?(l6)
|
||||
r(1)
|
||||
r(2)
|
||||
r(3)
|
||||
r(>)
|
||||
r(2 > 3)
|
||||
jf(l5)
|
||||
jf(l7)
|
||||
r(2)
|
||||
jmp(l3)
|
||||
jmp(l6)
|
||||
l5:
|
||||
jmp(l4)
|
||||
jmp(l8)
|
||||
l7:
|
||||
read (Unit)
|
||||
l4:
|
||||
l6:
|
||||
l8:
|
||||
r(2)
|
||||
jmp?(l3)
|
||||
jmp?(l4)
|
||||
l2:
|
||||
read (Unit)
|
||||
l1:
|
||||
@@ -401,20 +409,22 @@ l0:
|
||||
r(a)
|
||||
r(..)
|
||||
r(1..a)
|
||||
jmp?(l3)
|
||||
l4:
|
||||
jmp?(l3)
|
||||
l5:
|
||||
l6:
|
||||
r(1)
|
||||
r(2)
|
||||
r(3)
|
||||
r(>)
|
||||
r(2 > 3)
|
||||
jf(l5)
|
||||
jmp(l4)
|
||||
jmp(l6)
|
||||
l5:
|
||||
jf(l7)
|
||||
jmp(l5)
|
||||
jmp(l8)
|
||||
l7:
|
||||
read (Unit)
|
||||
l6:
|
||||
jmp?(l4)
|
||||
l8:
|
||||
jmp?(l5)
|
||||
l3:
|
||||
read (Unit)
|
||||
r(5)
|
||||
@@ -446,20 +456,22 @@ l0:
|
||||
r(a)
|
||||
r(..)
|
||||
r(1..a)
|
||||
jmp?(l3)
|
||||
l4:
|
||||
jmp?(l3)
|
||||
l5:
|
||||
l6:
|
||||
r(1)
|
||||
r(2)
|
||||
r(3)
|
||||
r(>)
|
||||
r(2 > 3)
|
||||
jf(l5)
|
||||
jmp(l4)
|
||||
jmp(l6)
|
||||
l5:
|
||||
jf(l7)
|
||||
jmp(l5)
|
||||
jmp(l8)
|
||||
l7:
|
||||
read (Unit)
|
||||
l6:
|
||||
jmp?(l4)
|
||||
l8:
|
||||
jmp?(l5)
|
||||
l3:
|
||||
read (Unit)
|
||||
l2:
|
||||
|
||||
@@ -7,15 +7,17 @@ fun main() {
|
||||
---------------------
|
||||
l0:
|
||||
<START>
|
||||
l3:
|
||||
l2:
|
||||
l5:
|
||||
r(1)
|
||||
r(0)
|
||||
r(>)
|
||||
r(1 > 0)
|
||||
jf(l2)
|
||||
jf(l3)
|
||||
l4:
|
||||
r(2)
|
||||
jmp(l3)
|
||||
l2:
|
||||
jmp(l2)
|
||||
l3:
|
||||
read (Unit)
|
||||
l1:
|
||||
<END>
|
||||
@@ -30,14 +32,16 @@ fun dowhile() {
|
||||
---------------------
|
||||
l0:
|
||||
<START>
|
||||
l3:
|
||||
l2:
|
||||
l4:
|
||||
ret l1
|
||||
l5:
|
||||
r(1)
|
||||
r(0)
|
||||
r(>)
|
||||
r(1 > 0)
|
||||
jt(l3)
|
||||
l2:
|
||||
jt(l2)
|
||||
l3:
|
||||
read (Unit)
|
||||
l1:
|
||||
<END>
|
||||
|
||||
@@ -139,3 +139,78 @@ fun test() {
|
||||
out.println()
|
||||
|
||||
}
|
||||
|
||||
|
||||
fun f(out : String?) {
|
||||
out?.get(0)
|
||||
if (out != null) else return;
|
||||
out.get(0)
|
||||
}
|
||||
|
||||
fun f1(out : String?) {
|
||||
out?.get(0)
|
||||
if (out != null) else {
|
||||
1 + 2
|
||||
return;
|
||||
}
|
||||
out.get(0)
|
||||
}
|
||||
|
||||
fun f2(out : String?) {
|
||||
out?.get(0)
|
||||
if (out == null) {
|
||||
1 + 2
|
||||
return;
|
||||
}
|
||||
out.get(0)
|
||||
}
|
||||
|
||||
fun f3(out : String?) {
|
||||
out?.get(0)
|
||||
if (out == null) {
|
||||
1 + 2
|
||||
return;
|
||||
}
|
||||
else {
|
||||
1 + 2
|
||||
}
|
||||
out.get(0)
|
||||
}
|
||||
|
||||
fun f4(s : String?) {
|
||||
s?.get(0)
|
||||
while (1 < 2 && s != null) {
|
||||
s.get(0)
|
||||
}
|
||||
s?.get(0)
|
||||
while (s == null || 1 < 2) {
|
||||
s?.get(0)
|
||||
}
|
||||
s.get(0)
|
||||
}
|
||||
|
||||
fun f5(s : String?) {
|
||||
s?.get(0)
|
||||
while (1 < 2 && s != null) {
|
||||
s.get(0)
|
||||
}
|
||||
s?.get(0)
|
||||
while (s == null || 1 < 2) {
|
||||
if (1 > 2) break
|
||||
s?.get(0)
|
||||
}
|
||||
s?.get(0);
|
||||
}
|
||||
|
||||
fun f6(s : String?) {
|
||||
s?.get(0)
|
||||
do {
|
||||
s?.get(0)
|
||||
if (1 < 2) break;
|
||||
} while (s == null)
|
||||
s?.get(0)
|
||||
do {
|
||||
s?.get(0)
|
||||
} while (s == null)
|
||||
s.get(0)
|
||||
}
|
||||
|
||||
@@ -8,11 +8,13 @@ import junit.framework.Test;
|
||||
import junit.framework.TestSuite;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.JetTestCaseBase;
|
||||
import org.jetbrains.jet.lang.cfg.LoopInfo;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.Instruction;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.JetPseudocodeTrace;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode;
|
||||
import org.jetbrains.jet.lang.psi.JetElement;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.psi.JetNamedDeclaration;
|
||||
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
|
||||
@@ -55,6 +57,10 @@ public class JetControlFlowTest extends JetTestCaseBase {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recordLoopInfo(JetExpression expression, LoopInfo blockInfo) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recordRepresentativeInstruction(@NotNull JetElement element, @NotNull Instruction instruction) {
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user