type inference

This commit is contained in:
Maxim.Medvedev
2012-06-04 17:25:58 +04:00
parent 5905401eab
commit d41471cade
22 changed files with 378 additions and 243 deletions
@@ -0,0 +1,44 @@
/*
* Copyright 2000-2012 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.plugins.groovy.lang.psi.controlFlow;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl.ConditionInstruction;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl.InstructionImpl;
/**
* @author Max Medvedev
*/
public abstract class GotoInstruction extends InstructionImpl {
@NotNull private final ConditionInstruction myCondition;
public GotoInstruction(@Nullable PsiElement element, int num, @NotNull ConditionInstruction condition) {
super(element, num);
myCondition = condition;
}
@NotNull
public ConditionInstruction getCondition() {
return myCondition;
}
@Override
protected String getElementPresentation() {
return " Positive goto instruction, condition=" + myCondition.num() + getElement();
}
}
@@ -16,6 +16,7 @@
package org.jetbrains.plugins.groovy.lang.psi.controlFlow;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
@@ -30,8 +31,8 @@ public interface Instruction {
int num();
@Nullable
NegatingGotoInstruction getNegatingGotoInstruction();
@NotNull
Iterable<? extends NegatingGotoInstruction> getNegatingGotoInstruction();
@Nullable
PsiElement getElement();
@@ -19,26 +19,17 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl.ConditionInstruction;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl.InstructionImpl;
/**
* @author Max Medvedev
*/
public class NegatingGotoInstruction extends InstructionImpl {
@NotNull private final ConditionInstruction myCondition;
public class NegatingGotoInstruction extends GotoInstruction {
public NegatingGotoInstruction(@Nullable PsiElement element, int num, @NotNull ConditionInstruction condition) {
super(element, num);
myCondition = condition;
}
@NotNull
public ConditionInstruction getCondition() {
return myCondition;
super(element, num, condition);
}
@Override
protected String getElementPresentation() {
return " Negating goto instruction, condition=" + myCondition.num() + getElement();
return " Negating goto instruction, condition=" + getCondition().num() + getElement();
}
}
@@ -0,0 +1,30 @@
/*
* Copyright 2000-2012 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.plugins.groovy.lang.psi.controlFlow;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl.ConditionInstruction;
/**
* @author Max Medvedev
*/
public class PositiveGotoInstruction extends GotoInstruction {
public PositiveGotoInstruction(@Nullable PsiElement element, int num, @NotNull ConditionInstruction condition) {
super(element, num, condition);
}
}
@@ -35,7 +35,7 @@ public class ConditionInstruction extends InstructionImpl implements Instruction
@Override
protected String getElementPresentation() {
return "Condition" + getElement();
return "Condition " + getElement();
}
void addDependent(ConditionInstruction i) {
@@ -88,11 +88,6 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor {
private Deque<ConditionInstruction> myConditions;
/**
* stack of negating instructions
*/
private Deque<NegatingGotoInstruction> myNegatingStack;
/**
* count of finally blocks surrounding current statement
*/
@@ -159,7 +154,6 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor {
myProcessingStack = new ArrayDeque<InstructionImpl>();
myCaughtExceptionInfos = new ArrayDeque<ExceptionInfo>();
myConditions = new ArrayDeque<ConditionInstruction>();
myNegatingStack = new ArrayDeque<NegatingGotoInstruction>();
myFinallyCount = 0;
myPending = new ArrayList<Pair<InstructionImpl, GroovyPsiElement>>();
@@ -222,7 +216,6 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor {
private <T extends InstructionImpl> T addNode(T instruction) {
myInstructions.add(instruction);
instruction.setNegating(myNegatingStack.peek());
if (myHead != null) {
addEdge(myHead, instruction);
}
@@ -239,6 +232,10 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor {
private static void addEdge(InstructionImpl begin, InstructionImpl end) {
begin.addSuccessor(end);
end.addPredecessor(begin);
if (!(begin instanceof ReadWriteVariableInstruction || begin instanceof MixinTypeInstruction)) {
end.addNegationsFrom(begin);
}
}
public void visitClosure(GrClosableBlock closure) {
@@ -398,30 +395,76 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor {
@Override
public void visitUnaryExpression(GrUnaryExpression expression) {
final GrExpression operand = expression.getOperand();
if (operand != null) {
ConditionInstruction cond = null;
if (expression.getOperationTokenType() == mLNOT) {
cond = new ConditionInstruction(expression, myInstructionNumber++);
addNodeAndCheckPending(cond);
registerCondition(cond);
}
if (operand == null) return;
if (expression.getOperationTokenType() != mLNOT) {
operand.accept(this);
visitCall(expression);
return;
}
if (cond != null) {
myConditions.removeFirstOccurrence(cond);
myNegatingStack.push(addNodeAndCheckPending(new NegatingGotoInstruction(expression, myInstructionNumber++, cond)));
ConditionInstruction cond = new ConditionInstruction(expression, myInstructionNumber++);
addNodeAndCheckPending(cond);
registerCondition(cond);
operand.accept(this);
visitCall(expression);
myConditions.removeFirstOccurrence(cond);
List<GotoInstruction> negations = collectAndRemoveAllPendingNegations(expression);
addPendingEdge(expression, addNodeAndCheckPending(new PositiveGotoInstruction(expression, myInstructionNumber++, cond)));
myHead = reduceAllNegationsIntoInstruction(expression, negations);
}
@Nullable
private InstructionImpl reduceAllNegationsIntoInstruction(GroovyPsiElement currentScope, List<? extends GotoInstruction> negations) {
if (negations.size() > 1) {
InstructionImpl instruction = addNode(new InstructionImpl(currentScope, myInstructionNumber++));
for (GotoInstruction negation : negations) {
addEdge(negation, instruction);
}
return instruction;
}
else if (negations.size() == 1) {
return negations.get(0);
}
return null;
}
private List<GotoInstruction> collectAndRemoveAllPendingNegations(GroovyPsiElement currentScope) {
List<GotoInstruction> negations = new ArrayList<GotoInstruction>();
for (Iterator<Pair<InstructionImpl, GroovyPsiElement>> iterator = myPending.iterator(); iterator.hasNext(); ) {
Pair<InstructionImpl, GroovyPsiElement> pair = iterator.next();
InstructionImpl instruction = pair.first;
GroovyPsiElement scope = pair.second;
if (!PsiTreeUtil.isAncestor(scope, currentScope, true) && instruction instanceof GotoInstruction) {
negations.add((GotoInstruction)instruction);
iterator.remove();
}
}
return negations;
}
@Override
public void visitInstanceofExpression(GrInstanceOfExpression expression) {
expression.getOperand().accept(this);
final ConditionInstruction cond = myConditions.peek();
if (cond != null) {
addNode(new InstanceOfInstruction(myInstructionNumber++, expression, cond));
}
ConditionInstruction cond = new ConditionInstruction(expression, myInstructionNumber++);
addNodeAndCheckPending(cond);
registerCondition(cond);
addNode(new InstanceOfInstruction(myInstructionNumber++, expression, cond));
NegatingGotoInstruction negation = new NegatingGotoInstruction(expression, myInstructionNumber++, cond);
addNode(negation);
addPendingEdge(expression, negation);
myHead = cond;
InstanceOfInstruction instruction = addNode(new InstanceOfInstruction(myInstructionNumber++, expression, cond));
myConditions.removeFirstOccurrence(cond);
}
public void visitReferenceExpression(GrReferenceExpression refExpr) {
@@ -478,41 +521,48 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor {
final GrExpression right = expression.getRightOperand();
final IElementType opType = expression.getOperationTokenType();
final ConditionInstruction cond;
if (opType == mLOR || opType == mLAND) {
cond = addNodeAndCheckPending(new ConditionInstruction(expression, myInstructionNumber++));
registerCondition(cond);
}
else {
cond = null;
if (opType != mLOR && opType != mLAND) {
left.accept(this);
if (right != null) {
right.accept(this);
}
visitCall(expression);
return;
}
ConditionInstruction condition = new ConditionInstruction(expression, myInstructionNumber++);
addNodeAndCheckPending(condition);
registerCondition(condition);
left.accept(this);
if (cond != null) {
myConditions.removeFirstOccurrence(cond);
}
if (right == null) return;
NegatingGotoInstruction first = null;
if (right != null) {
if (cond != null) {
final InstructionImpl head = myHead;
if (opType == mLAND) {
first = addNodeAndCheckPending(new NegatingGotoInstruction(expression, myInstructionNumber++, cond));
}
addPendingEdge(expression, myHead);
myHead = head;
if (opType == mLOR) {
myNegatingStack.push(addNodeAndCheckPending(new NegatingGotoInstruction(expression, myInstructionNumber++, cond)));
}
}
right.accept(this);
}
final List<GotoInstruction> negations = collectAndRemoveAllPendingNegations(expression);
visitCall(expression);
if (first != null) {
myNegatingStack.push(first);
if (opType == mLAND) {
for (GotoInstruction negation : negations) {
addPendingEdge(expression, negation);
}
if (negations.isEmpty()) {
InstructionImpl head = myHead;
NegatingGotoInstruction negation = addNode(new NegatingGotoInstruction(expression, myInstructionNumber++, condition));
addPendingEdge(expression, negation);
myHead = head;
}
}
else /*if (opType == mLOR)*/ {
addNodeAndCheckPending(new InstructionImpl(expression, myInstructionNumber++)); //collect all pending edges from left argument
addPendingEdge(expression, myHead);
myHead = reduceAllNegationsIntoInstruction(expression, negations);
//addNode(new NegatingGotoInstruction(expression, myInstructionNumber++, condition));
}
myConditions.removeFirstOccurrence(condition);
right.accept(this);
}
/**
@@ -539,8 +589,6 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor {
public void visitIfStatement(GrIfStatement ifStatement) {
InstructionImpl ifInstruction = startNode(ifStatement);
final InstructionImpl head = myHead;
final GrCondition condition = ifStatement.getCondition();
final GrStatement thenBranch = ifStatement.getThenBranch();
final GrStatement elseBranch = ifStatement.getElseBranch();
@@ -549,29 +597,13 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor {
InstructionImpl thenEnd = null;
InstructionImpl elseEnd = null;
List<NegatingGotoInstruction> pendingNegations = new ArrayList<NegatingGotoInstruction>();
ConditionInstruction conditionStart = null;
if (condition != null) {
final List<Pair<InstructionImpl, GroovyPsiElement>> oldPending = myPending;
myPending = new ArrayList<Pair<InstructionImpl, GroovyPsiElement>>();
conditionStart = addNodeAndCheckPending(new ConditionInstruction(condition, myInstructionNumber++));
registerCondition(conditionStart);
condition.accept(this);
conditionEnd = myHead;
List<Pair<InstructionImpl, GroovyPsiElement>> pendingFromCondition = myPending;
myPending = oldPending;
for (Pair<InstructionImpl, GroovyPsiElement> pair : pendingFromCondition) {
if (pair.first instanceof NegatingGotoInstruction) {
pendingNegations.add((NegatingGotoInstruction)pair.first);
}
else {
addPendingEdge(pair.second, pair.first);
}
}
}
List<GotoInstruction> negations = collectAndRemoveAllPendingNegations(ifStatement);
if (thenBranch != null) {
thenBranch.accept(this);
handlePossibleReturn(thenBranch);
@@ -579,30 +611,29 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor {
interruptFlow();
}
if (condition != null) {
myHead = reduceAllNegationsIntoInstruction(ifStatement, negations);
if (negations.isEmpty() && conditionEnd != null) {
myHead = conditionEnd;
myNegatingStack.push(addNode(new NegatingGotoInstruction(condition, myInstructionNumber++, conditionStart)));
}
else {
myHead = head;
}
for (NegatingGotoInstruction negation : pendingNegations) {
assert condition != null;
addPendingEdge(condition, negation);
}
if (elseBranch != null) {
elseBranch.accept(this);
handlePossibleReturn(elseBranch);
elseEnd = myHead;
interruptFlow();
}
if (thenBranch != null || elseBranch != null) {
final InstructionImpl end = new IfEndInstruction(ifStatement, myInstructionNumber++);
addNode(end);
if (thenEnd != null) addEdge(thenEnd, end);
if (elseEnd != null) addEdge(elseEnd, end);
if (elseEnd != null) {
addEdge(elseEnd, end);
}
else {
addEdge(conditionEnd != null ? conditionEnd : ifInstruction, end);
}
}
finishNode(ifInstruction);
}
@@ -750,6 +781,44 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor {
finishNode(instruction);
}
@Override
public void visitConditionalExpression(GrConditionalExpression expression) {
GrExpression condition = expression.getCondition();
GrExpression thenBranch = expression.getThenBranch();
GrExpression elseBranch = expression.getElseBranch();
condition.accept(this);
List<GotoInstruction> negations = collectAndRemoveAllPendingNegations(expression);
if (thenBranch != null) {
thenBranch.accept(this);
handlePossibleReturn(thenBranch);
addPendingEdge(expression, myHead);
}
if (elseBranch != null) {
myHead = reduceAllNegationsIntoInstruction(expression, negations);
elseBranch.accept(this);
handlePossibleReturn(elseBranch);
}
}
@Override
public void visitElvisExpression(GrElvisExpression expression) {
GrExpression condition = expression.getCondition();
GrExpression elseBranch = expression.getElseBranch();
condition.accept(this);
List<GotoInstruction> negations = collectAndRemoveAllPendingNegations(expression);
addPendingEdge(expression, myHead);
if (elseBranch != null) {
myHead = reduceAllNegationsIntoInstruction(expression, negations);
elseBranch.accept(this);
handlePossibleReturn(elseBranch);
}
}
private static boolean containsAllCases(GrSwitchStatement statement) {
final GrCaseSection[] sections = statement.getCaseSections();
for (GrCaseSection section : sections) {
@@ -16,6 +16,7 @@
package org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.CallEnvironment;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.CallInstruction;
@@ -31,10 +32,10 @@ import java.util.LinkedHashSet;
public class InstructionImpl implements Instruction {
private final LinkedHashSet<InstructionImpl> myPredecessors = new LinkedHashSet<InstructionImpl>();
private final LinkedHashSet<InstructionImpl> mySuccessors = new LinkedHashSet<InstructionImpl>();
private final LinkedHashSet<NegatingGotoInstruction> myNegations = new LinkedHashSet<NegatingGotoInstruction>();
PsiElement myPsiElement;
private final int myNumber;
private NegatingGotoInstruction myNegating;
@Nullable
public PsiElement getElement() {
@@ -93,9 +94,10 @@ public class InstructionImpl implements Instruction {
return myNumber;
}
@NotNull
@Override
public NegatingGotoInstruction getNegatingGotoInstruction() {
return myNegating;
public Iterable<? extends NegatingGotoInstruction> getNegatingGotoInstruction() {
return myNegations;
}
public void addSuccessor(InstructionImpl instruction) {
@@ -106,7 +108,12 @@ public class InstructionImpl implements Instruction {
myPredecessors.add(instruction);
}
void setNegating(NegatingGotoInstruction negating) {
myNegating = negating;
void addNegationsFrom(Instruction instruction) {
for (NegatingGotoInstruction negation : instruction.getNegatingGotoInstruction()) {
myNegations.add(negation);
}
if (instruction instanceof NegatingGotoInstruction) {
myNegations.add((NegatingGotoInstruction)instruction);
}
}
}
@@ -19,7 +19,9 @@ import com.intellij.psi.PsiIntersectionType;
import com.intellij.psi.PsiManager;
import com.intellij.psi.PsiType;
import com.intellij.psi.util.TypeConversionUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.NegatingGotoInstruction;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl.ConditionInstruction;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
@@ -92,15 +94,15 @@ public class DFAType {
return true;
}
public DFAType negate(NegatingGotoInstruction negating) {
public DFAType negate(@NotNull Instruction instruction) {
final DFAType type = new DFAType(primary);
for (Mixin mixin : mixins) {
type.mixins.add(mixin);
}
for (; negating != null; negating = negating.getNegatingGotoInstruction()) {
final Set<ConditionInstruction> conditionsToNegate = negating.getCondition().getDependentConditions();
for (NegatingGotoInstruction negation: instruction.getNegatingGotoInstruction()) {
final Set<ConditionInstruction> conditionsToNegate = negation.getCondition().getDependentConditions();
for (ListIterator<Mixin> iterator = type.mixins.listIterator(); iterator.hasNext(); ) {
Mixin mixin = iterator.next();
@@ -34,7 +34,10 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.*;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.InstanceOfInstruction;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.MixinTypeInstruction;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.ReadWriteVariableInstruction;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl.ArgumentInstruction;
import org.jetbrains.plugins.groovy.lang.psi.dataFlow.DFAEngine;
import org.jetbrains.plugins.groovy.lang.psi.dataFlow.DFAType;
@@ -150,9 +153,8 @@ public class TypeInferenceHelper {
for (int defIndex : varDefs.toArray()) {
DFAType defType = getDefinitionType(flow[defIndex], flow, scope);
final NegatingGotoInstruction negating = instruction.getNegatingGotoInstruction();
if (defType != null) {
defType = defType.negate(negating);
defType = defType.negate(instruction);
}
if (defType != null) {
@@ -528,6 +528,15 @@ def foo(def oo) {
''', null)
}
void testInstanceOfInferring6() {
doTest('''\
def foo(bar) {
if (!(bar instanceof String) && bar instanceof Runnable) {
ba<caret>r
}
}''', 'java.lang.Runnable')
}
private void doTest(String text, String type) {
def file = myFixture.configureByText('_.groovy', text)
def ref = file.findReferenceAt(myFixture.editor.caretModel.offset) as GrReferenceExpression
+11 -13
View File
@@ -5,16 +5,14 @@ println blah
-----
0(1) element: null
1(2) WRITE blah
2(3) element: IF statement
3(4,6) Condition
4(5) READ blah
5(7) WRITE blah
6(7) Negating goto instruction, condition=3
7(8) element: IF statement
8(9) READ blah
9(10) WRITE blah
10(11) READ println
11(12) READ blah
12(13) ARGUMENT element: Reference expression
13(14) element: Call expression MAYBE_RETURN
14() element: null
2(3,5) element: IF statement
3(4) READ blah
4(5) WRITE blah
5(6) element: IF statement
6(7) READ blah
7(8) WRITE blah
8(9) READ println
9(10) READ blah
10(11) ARGUMENT element: Reference expression
11(12) element: Call expression MAYBE_RETURN
12() element: null
+7 -9
View File
@@ -5,12 +5,10 @@ if (true) {
a = 2
-----
0(1) element: null
1(2) element: IF statement
2(3,5) Condition
3(4) WRITE a
4(8) element: Assignment expression MAYBE_RETURN
5(6) Negating goto instruction, condition=2
6(7) WRITE a
7(8) element: Assignment expression MAYBE_RETURN
8(9) element: IF statement
9() element: null
1(2,4) element: IF statement
2(3) WRITE a
3(6) element: Assignment expression MAYBE_RETURN
4(5) WRITE a
5(6) element: Assignment expression MAYBE_RETURN
6(7) element: IF statement
7() element: null
@@ -4,23 +4,25 @@ else b = 3
-----
0(1) element: null
1(2) element: IF statement
2(3) Condition
3(4) READ o
4(5,7) instanceof: o instanceof String
5(6) WRITE b
6(20) element: Assignment expression MAYBE_RETURN
7(8) Negating goto instruction, condition=2
8(9) element: IF statement
9(10) Condition
10(11) Condition
2(3) READ o
3(4,6) Condition Instanceof expression
4(5) instanceof: o instanceof String
5(9) Negating goto instruction, condition=3Instanceof expression
6(7) instanceof: o instanceof String
7(8) WRITE b
8(22) element: Assignment expression MAYBE_RETURN
9(10) element: IF statement
10(11) Condition Unary expression
11(12) READ o
12(13) instanceof: o instanceof Integer
13(14,16) Negating goto instruction, condition=10
14(15) WRITE b
15(19) element: Assignment expression MAYBE_RETURN
16(17) Negating goto instruction, condition=9
12(13,15) Condition Instanceof expression
13(14) instanceof: o instanceof Integer
14(17) Negating goto instruction, condition=12Instanceof expression
15(16) instanceof: o instanceof Integer
16(19) Positive goto instruction, condition=10Unary expression
17(18) WRITE b
18(19) element: Assignment expression MAYBE_RETURN
19(20) element: IF statement
20(21) element: IF statement
21() element: null
18(21) element: Assignment expression MAYBE_RETURN
19(20) WRITE b
20(21) element: Assignment expression MAYBE_RETURN
21(22) element: IF statement
22(23) element: IF statement
23() element: null
+7 -9
View File
@@ -9,16 +9,14 @@ for (e in [1,2,3,4]) {
0(1) element: null
1(2) element: Labeled statement
2(3) WRITE e
3(4,15) element: For statement
3(4,13) element: For statement
4(5) element: Block statement
5(6) WRITE ee
6(7,3) element: For statement
7(8) element: Block statement
8(9) element: IF statement
9(1,10) Condition
10(11) Negating goto instruction, condition=9
11(12) element: IF statement
12(13) READ print
13(14) READ e
14(6) READ ee
15() element: null
8(1,9) element: IF statement
9(10) element: IF statement
10(11) READ print
11(12) READ e
12(6) READ ee
13() element: null
+7 -9
View File
@@ -1,12 +1,10 @@
if (true) return a else return b
-----
0(1) element: null
1(2) element: IF statement
2(3,5) Condition
3(4) READ a
4(9) element: RETURN statement
5(6) Negating goto instruction, condition=2
6(7) READ b
7(9) element: RETURN statement
8(9) element: IF statement
9() element: null
1(2,4,6) element: IF statement
2(3) READ a
3(7) element: RETURN statement
4(5) READ b
5(7) element: RETURN statement
6(7) element: IF statement
7() element: null
+15 -17
View File
@@ -8,20 +8,18 @@ print e
0(1) element: null
1(2) element: Open block
2(3) element: IF statement
3(4) Condition
4(5,6) READ c
5(9) element: RETURN statement
6(7) Negating goto instruction, condition=3
7(11) element: IF statement
8(13) element: Finally clause
9(8,10) CALL 8
10(19) AFTER CALL 9
11(8,12) CALL 8
12(15) AFTER CALL 11
13(14) READ e
14(10,12) RETURN
15(16) READ print
16(17) READ e
17(18) ARGUMENT element: Reference expression
18(19) element: Call expression MAYBE_RETURN
19() element: null
3(4,5) READ c
4(7) element: RETURN statement
5(9) element: IF statement
6(11) element: Finally clause
7(6,8) CALL 6
8(17) AFTER CALL 7
9(6,10) CALL 6
10(13) AFTER CALL 9
11(12) READ e
12(8,10) RETURN
13(14) READ print
14(15) READ e
15(16) ARGUMENT element: Reference expression
16(17) element: Call expression MAYBE_RETURN
17() element: null
+7 -9
View File
@@ -10,15 +10,13 @@ cde
1(3) element: Open block
2(5) element: Finally clause
3(2,4) CALL 2
4(13) AFTER CALL 3
4(11) AFTER CALL 3
5(6) element: For statement
6(7) element: Block statement
7(8) element: IF statement
8(9) Condition
9(10,12) READ abc
10(11) Negating goto instruction, condition=8
11(5) element: IF statement
12(4) RETURN
13(14) READ cde
14(15) element: Reference expression MAYBE_RETURN
15() element: null
8(9,10) READ abc
9(5) element: IF statement
10(4) RETURN
11(12) READ cde
12(13) element: Reference expression MAYBE_RETURN
13() element: null
+15 -17
View File
@@ -12,20 +12,18 @@ fScript.previewTask(taskName)
-----
0(1) element: null
1(2) element: IF statement
2(3) Condition
3(4,6) READ ddd
4(5) READ fXRec
5(18) element: RETURN statement
6(7) Negating goto instruction, condition=2
7(8) element: IF statement
8(9) WRITE fScript
9(11) element: Open block
10(13) element: Finally clause
11(10,12) CALL 10
12(14) AFTER CALL 11
13(12) RETURN
14(15) READ fScript
15(16) READ taskName
16(17) ARGUMENT element: Reference expression
17(18) element: Method call MAYBE_RETURN
18() element: null
2(3,5) READ ddd
3(4) READ fXRec
4(16) element: RETURN statement
5(6) element: IF statement
6(7) WRITE fScript
7(9) element: Open block
8(11) element: Finally clause
9(8,10) CALL 8
10(12) AFTER CALL 9
11(10) RETURN
12(13) READ fScript
13(14) READ taskName
14(15) ARGUMENT element: Reference expression
15(16) element: Method call MAYBE_RETURN
16() element: null
+12 -14
View File
@@ -10,17 +10,15 @@ return url
-----
0(1) element: null
1(2) element: IF statement
2(3) Condition
3(4,11) READ url
4(5) element: Open block
5(13) WRITE url
6(7) element: Catch clause
7(8) WRITE e
8(9) READ e
9(10) ARGUMENT element: Reference expression
10(15) THROW. element: THROW statement
11(12) Negating goto instruction, condition=2
12(13) element: IF statement
13(14) READ url
14(15) element: RETURN statement
15() element: null
2(3,10) READ url
3(4) element: Open block
4(11) WRITE url
5(6) element: Catch clause
6(7) WRITE e
7(8) READ e
8(9) ARGUMENT element: Reference expression
9(13) THROW. element: THROW statement
10(11) element: IF statement
11(12) READ url
12(13) element: RETURN statement
13() element: null
+5 -7
View File
@@ -8,10 +8,8 @@ while (true) {
1(2) WRITE i
2(3) element: WHILE statement
3(4) element: IF statement
4(5) Condition
5(6,10) READ i
6(7) Negating goto instruction, condition=4
7(8) element: IF statement
8(9) READ i
9(2) WRITE i
10() element: null
4(5,8) READ i
5(6) element: IF statement
6(7) READ i
7(2) WRITE i
8() element: null
+5 -7
View File
@@ -8,10 +8,8 @@ while (true) {
1(2) WRITE i
2(3) element: WHILE statement
3(4) element: IF statement
4(5) Condition
5(2,6) READ i
6(7) Negating goto instruction, condition=4
7(8) element: IF statement
8(9) READ i
9(2) WRITE j
10() element: null
4(2,5) READ i
5(6) element: IF statement
6(7) READ i
7(2) WRITE j
8() element: null
@@ -7,12 +7,10 @@ while (condition()) {
0(1) element: null
1(2) WRITE i
2(3) element: WHILE statement
3(4,11) READ condition
3(4,9) READ condition
4(5) element: IF statement
5(6) Condition
6(7,11) READ i
7(8) Negating goto instruction, condition=5
8(9) element: IF statement
9(10) READ i
10(2) WRITE i
11() element: null
5(6,9) READ i
6(7) element: IF statement
7(8) READ i
8(2) WRITE i
9() element: null