Fixed: malfunctioned "Remove trailing spaces on editor save"
[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
26         public Statement action;
27
28         private Label breakLabel, continueLabel;
29
30         // for local variables table attributes
31         int mergedInitStateIndex = -1;
32
33         public DoStatement(Expression condition, Statement action, int s, int e) {
34
35                 this.sourceStart = s;
36                 this.sourceEnd = e;
37                 this.condition = condition;
38                 this.action = action;
39         }
40
41         public FlowInfo analyseCode(BlockScope currentScope,
42                         FlowContext flowContext, FlowInfo flowInfo) {
43
44                 breakLabel = new Label();
45                 continueLabel = new Label();
46                 LoopingFlowContext loopingContext = new LoopingFlowContext(flowContext,
47                                 this, breakLabel, continueLabel, currentScope);
48
49                 Constant cst = condition.constant;
50                 boolean isConditionTrue = cst != NotAConstant
51                                 && cst.booleanValue() == true;
52                 cst = condition.optimizedBooleanConstant();
53                 boolean isConditionOptimizedTrue = cst != NotAConstant
54                                 && cst.booleanValue() == true;
55                 boolean isConditionOptimizedFalse = cst != NotAConstant
56                                 && cst.booleanValue() == false;
57
58                 int previousMode = flowInfo.reachMode();
59
60                 if ((action != null) && !action.isEmptyBlock()) {
61                         flowInfo = action.analyseCode(currentScope, loopingContext,
62                                         flowInfo);
63
64                         // code generation can be optimized when no need to continue in the
65                         // loop
66                         if (!flowInfo.isReachable()
67                                         && !loopingContext.initsOnContinue.isReachable()) {
68                                 continueLabel = null;
69                         }
70                 }
71                 /*
72                  * Reset reach mode, to address following scenario. final blank; do { if
73                  * (true) break; else blank = 0; } while(false); blank = 1; // may be
74                  * initialized already
75                  */
76                 flowInfo.setReachMode(previousMode);
77
78                 flowInfo = condition.analyseCode(currentScope, loopingContext,
79                                 (action == null ? flowInfo : (flowInfo
80                                                 .mergedWith(loopingContext.initsOnContinue))));
81                 if (!isConditionOptimizedFalse && continueLabel != null) {
82                         loopingContext.complainOnFinalAssignmentsInLoop(currentScope,
83                                         flowInfo);
84                 }
85
86                 // infinite loop
87                 FlowInfo mergedInfo;
88                 if (isConditionTrue) {
89                         mergedInfo = loopingContext.initsOnBreak;
90                         if (!mergedInfo.isReachable())
91                                 mergedInfo.addPotentialInitializationsFrom(flowInfo
92                                                 .initsWhenFalse());
93                 } else {
94                         // end of loop: either condition false or break
95                         mergedInfo = flowInfo.initsWhenFalse().unconditionalInits()
96                                         .mergedWith(loopingContext.initsOnBreak);
97                         if (isConditionOptimizedTrue
98                                         && !loopingContext.initsOnBreak.isReachable()) {
99                                 mergedInfo.setReachMode(FlowInfo.UNREACHABLE);
100                         }
101                 }
102                 mergedInitStateIndex = currentScope.methodScope()
103                                 .recordInitializationStates(mergedInfo);
104                 return mergedInfo;
105         }
106
107         /**
108          * Do statement code generation
109          * 
110          */
111         // public void generateCode(BlockScope currentScope, CodeStream codeStream)
112         // {
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
144         // variable attributes
145         // if (mergedInitStateIndex != -1) {
146         // codeStream.removeNotDefinitelyAssignedVariables(
147         // currentScope,
148         // mergedInitStateIndex);
149         // }
150         // codeStream.recordPositionsFrom(pc, this.sourceStart);
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
165                                 .resolveTypeExpecting(scope, BooleanBinding);
166                 condition.implicitWidening(type, type);
167                 if (action != null)
168                         action.resolve(scope);
169         }
170
171         public StringBuffer printStatement(int indent, StringBuffer output) {
172
173                 printIndent(indent, output).append("do"); //$NON-NLS-1$
174                 if (action == null)
175                         output.append(" ;\n"); //$NON-NLS-1$
176                 else {
177                         output.append('\n');
178                         action.printStatement(indent + 1, output).append('\n');
179                 }
180                 output.append("while ("); //$NON-NLS-1$
181                 return condition.printExpression(0, output).append(");"); //$NON-NLS-1$
182         }
183
184         public String toString(int tab) {
185
186                 String inFront, s = tabString(tab);
187                 inFront = s;
188                 s = s + "do"; //$NON-NLS-1$
189                 if (action == null)
190                         s = s + " {}\n"; //$NON-NLS-1$
191                 else if (action instanceof Block)
192                         s = s + "\n" + action.toString(tab + 1) + "\n"; //$NON-NLS-2$ //$NON-NLS-1$
193                 else
194                         s = s + " {\n" + action.toString(tab + 1) + ";}\n"; //$NON-NLS-1$ //$NON-NLS-2$
195                 s = s + inFront + "while (" + condition.toStringExpression() + ")"; //$NON-NLS-1$ //$NON-NLS-2$
196                 return s;
197         }
198
199         public void traverse(ASTVisitor visitor, BlockScope scope) {
200
201                 if (visitor.visit(this, scope)) {
202                         if (action != null) {
203                                 action.traverse(visitor, scope);
204                         }
205                         condition.traverse(visitor, scope);
206                 }
207                 visitor.endVisit(this, scope);
208         }
209 }