Avoid NPE in update OccurrenceAnnotation
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / ast / DoStatement.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2003 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.ast;
12
13 import net.sourceforge.phpdt.internal.compiler.ASTVisitor;
14 import net.sourceforge.phpdt.internal.compiler.codegen.Label;
15 import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
16 import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
17 import net.sourceforge.phpdt.internal.compiler.flow.LoopingFlowContext;
18 import net.sourceforge.phpdt.internal.compiler.impl.Constant;
19 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
20 import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
21
22 public class DoStatement extends Statement {
23
24         public Expression condition;
25         public Statement action;
26
27         private Label breakLabel, continueLabel;
28
29         // for local variables table attributes
30         int mergedInitStateIndex = -1;
31
32         public DoStatement(Expression condition, Statement action, int s, int e) {
33
34                 this.sourceStart = s;
35                 this.sourceEnd = e;
36                 this.condition = condition;
37                 this.action = action;
38         }
39
40         public FlowInfo analyseCode(
41                 BlockScope currentScope,
42                 FlowContext flowContext,
43                 FlowInfo flowInfo) {
44
45                 breakLabel = new Label();
46                 continueLabel = new Label();
47                 LoopingFlowContext loopingContext =
48                         new LoopingFlowContext(
49                                 flowContext,
50                                 this,
51                                 breakLabel,
52                                 continueLabel,
53                                 currentScope);
54
55                 Constant cst = condition.constant;
56                 boolean isConditionTrue = cst != NotAConstant && cst.booleanValue() == true;
57                 cst = condition.optimizedBooleanConstant();
58                 boolean isConditionOptimizedTrue = cst != NotAConstant && cst.booleanValue() == true;
59                 boolean isConditionOptimizedFalse = cst != NotAConstant && cst.booleanValue() == false;
60
61                 int previousMode = flowInfo.reachMode();
62                                 
63                 if ((action != null) && !action.isEmptyBlock()) {
64                         flowInfo = action.analyseCode(currentScope, loopingContext, flowInfo);
65
66                         // code generation can be optimized when no need to continue in the loop
67                         if (!flowInfo.isReachable() && !loopingContext.initsOnContinue.isReachable()) {
68                                 continueLabel = null;
69                         }
70                 }
71                 /* Reset reach mode, to address following scenario.
72                  *   final blank;
73                  *   do { if (true) break; else blank = 0; } while(false);
74                  *   blank = 1; // may be initialized already 
75                  */
76                 flowInfo.setReachMode(previousMode);
77                 
78                 flowInfo =
79                         condition.analyseCode(
80                                 currentScope,
81                                 loopingContext,
82                                 (action == null
83                                         ? flowInfo
84                                         : (flowInfo.mergedWith(loopingContext.initsOnContinue))));
85                 if (!isConditionOptimizedFalse && continueLabel != null) {
86                         loopingContext.complainOnFinalAssignmentsInLoop(currentScope, flowInfo);
87                 }
88
89                 // infinite loop
90                 FlowInfo mergedInfo;
91                 if (isConditionTrue) {
92                         mergedInfo = loopingContext.initsOnBreak;
93                         if (!mergedInfo.isReachable()) mergedInfo.addPotentialInitializationsFrom(flowInfo.initsWhenFalse());
94                 } else {
95                         // end of loop: either condition false or break
96                         mergedInfo =
97                                 flowInfo.initsWhenFalse().unconditionalInits().mergedWith(
98                                         loopingContext.initsOnBreak);
99                         if (isConditionOptimizedTrue && !loopingContext.initsOnBreak.isReachable()) {
100                                 mergedInfo.setReachMode(FlowInfo.UNREACHABLE);
101                         }
102                 }
103                 mergedInitStateIndex =
104                         currentScope.methodScope().recordInitializationStates(mergedInfo);
105                 return mergedInfo;
106         }
107
108         /**
109          * Do statement code generation
110          *
111          */
112 //      public void generateCode(BlockScope currentScope, CodeStream codeStream) {
113 //
114 //              if ((bits & IsReachableMASK) == 0) {
115 //                      return;
116 //              }
117 //              int pc = codeStream.position;
118 //
119 //              // labels management
120 //              Label actionLabel = new Label(codeStream);
121 //              actionLabel.place();
122 //              breakLabel.codeStream = codeStream;
123 //              if (continueLabel != null) {
124 //                      continueLabel.codeStream = codeStream;
125 //              }
126 //
127 //              // generate action
128 //              if (action != null) {
129 //                      action.generateCode(currentScope, codeStream);
130 //              }
131 //              // generate condition
132 //              if (continueLabel != null) {
133 //                      continueLabel.place();
134 //                      condition.generateOptimizedBoolean(
135 //                              currentScope,
136 //                              codeStream,
137 //                              actionLabel,
138 //                              null,
139 //                              true);
140 //              }
141 //              breakLabel.place();
142 //
143 //              // May loose some local variable initializations : affecting the local variable attributes
144 //              if (mergedInitStateIndex != -1) {
145 //                      codeStream.removeNotDefinitelyAssignedVariables(
146 //                              currentScope,
147 //                              mergedInitStateIndex);
148 //              }
149 //              codeStream.recordPositionsFrom(pc, this.sourceStart);
150 //
151 //      }
152
153         public void resetStateForCodeGeneration() {
154                 if (this.breakLabel != null) {
155                         this.breakLabel.resetStateForCodeGeneration();
156                 }
157                 if (this.continueLabel != null) {
158                         this.continueLabel.resetStateForCodeGeneration();
159                 }
160         }
161
162         public void resolve(BlockScope scope) {
163
164                 TypeBinding type = condition.resolveTypeExpecting(scope, BooleanBinding);
165                 condition.implicitWidening(type, type);
166                 if (action != null)
167                         action.resolve(scope);
168         }
169         public StringBuffer printStatement(int indent, StringBuffer output) {
170
171                 printIndent(indent, output).append("do"); //$NON-NLS-1$
172                 if (action == null)
173                         output.append(" ;\n"); //$NON-NLS-1$
174                 else {
175                         output.append('\n');
176                         action.printStatement(indent + 1, output).append('\n');
177                 }
178                 output.append("while ("); //$NON-NLS-1$
179                 return condition.printExpression(0, output).append(");"); //$NON-NLS-1$
180         }
181         public String toString(int tab) {
182
183                 String inFront, s = tabString(tab);
184                 inFront = s;
185                 s = s + "do"; //$NON-NLS-1$
186                 if (action == null)
187                         s = s + " {}\n"; //$NON-NLS-1$
188                 else if (action instanceof Block)
189                         s = s + "\n" + action.toString(tab + 1) + "\n"; //$NON-NLS-2$ //$NON-NLS-1$
190                 else
191                         s = s + " {\n" + action.toString(tab + 1) + ";}\n"; //$NON-NLS-1$ //$NON-NLS-2$
192                 s = s + inFront + "while (" + condition.toStringExpression() + ")"; //$NON-NLS-1$ //$NON-NLS-2$
193                 return s;
194         }
195
196         public void traverse(ASTVisitor visitor, BlockScope scope) {
197
198                 if (visitor.visit(this, scope)) {
199                         if (action != null) {
200                                 action.traverse(visitor, scope);
201                         }
202                         condition.traverse(visitor, scope);
203                 }
204                 visitor.endVisit(this, scope);
205         }
206 }