1 /*******************************************************************************
2 * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v0.5
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v05.html
9 * IBM Corporation - initial API and implementation
10 ******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.ast;
13 import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
14 import net.sourceforge.phpdt.internal.compiler.codegen.CodeStream;
15 import net.sourceforge.phpdt.internal.compiler.codegen.Label;
16 import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
17 import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
18 import net.sourceforge.phpdt.internal.compiler.flow.LoopingFlowContext;
19 import net.sourceforge.phpdt.internal.compiler.impl.Constant;
20 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
21 import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
23 public class WhileStatement extends Statement {
25 public Expression condition;
26 public Statement action;
27 private Label breakLabel, continueLabel;
28 int preCondInitStateIndex = -1;
29 int condIfTrueInitStateIndex = -1;
30 int mergedInitStateIndex = -1;
32 public WhileStatement(Expression condition, Statement action, int s, int e) {
34 this.condition = condition;
40 public FlowInfo analyseCode(
41 BlockScope currentScope,
42 FlowContext flowContext,
45 breakLabel = new Label();
46 continueLabel = new Label();
48 preCondInitStateIndex =
49 currentScope.methodScope().recordInitializationStates(flowInfo);
50 LoopingFlowContext condLoopContext;
51 FlowInfo postCondInfo =
52 condition.analyseCode(
55 new LoopingFlowContext(flowContext, this, null, null, currentScope)),
58 LoopingFlowContext loopingContext;
59 if ((action == null) || action.isEmptyBlock()) {
60 condLoopContext.complainOnFinalAssignmentsInLoop(currentScope, postCondInfo);
61 if ((condition.constant != NotAConstant)
62 && (condition.constant.booleanValue() == true)) {
63 return FlowInfo.DeadEnd;
65 FlowInfo mergedInfo = postCondInfo.initsWhenFalse().unconditionalInits();
66 mergedInitStateIndex =
67 currentScope.methodScope().recordInitializationStates(mergedInfo);
71 // in case the condition was inlined to false, record the fact that there is no way to reach any
72 // statement inside the looping action
74 new LoopingFlowContext(
81 ((condition.constant != Constant.NotAConstant)
82 && (condition.constant.booleanValue() == false))
84 : postCondInfo.initsWhenTrue().copy();
86 // for computing local var attributes
87 condIfTrueInitStateIndex =
88 currentScope.methodScope().recordInitializationStates(
89 postCondInfo.initsWhenTrue());
91 if (!actionInfo.complainIfUnreachable(action, currentScope)) {
92 actionInfo = action.analyseCode(currentScope, loopingContext, actionInfo);
95 // code generation can be optimized when no need to continue in the loop
96 if (((actionInfo == FlowInfo.DeadEnd) || actionInfo.isFakeReachable())
97 && ((loopingContext.initsOnContinue == FlowInfo.DeadEnd)
98 || loopingContext.initsOnContinue.isFakeReachable())) {
101 condLoopContext.complainOnFinalAssignmentsInLoop(currentScope, postCondInfo);
102 loopingContext.complainOnFinalAssignmentsInLoop(currentScope, actionInfo);
108 if ((condition.constant != Constant.NotAConstant)
109 && (condition.constant.booleanValue() == true)) {
110 mergedInitStateIndex =
111 currentScope.methodScope().recordInitializationStates(
112 mergedInfo = loopingContext.initsOnBreak);
116 // end of loop: either condition false or break
118 postCondInfo.initsWhenFalse().unconditionalInits().mergedWith(
119 loopingContext.initsOnBreak);
120 mergedInitStateIndex =
121 currentScope.methodScope().recordInitializationStates(mergedInfo);
126 * While code generation
128 * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
129 * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
131 public void generateCode(BlockScope currentScope, CodeStream codeStream) {
133 if ((bits & IsReachableMASK) == 0) {
136 int pc = codeStream.position;
137 breakLabel.codeStream = codeStream;
139 // generate condition
140 if (continueLabel == null) {
141 // no need to reverse condition
142 if (condition.constant == NotAConstant) {
143 condition.generateOptimizedBoolean(
151 continueLabel.codeStream = codeStream;
152 if (!(((condition.constant != NotAConstant)
153 && (condition.constant.booleanValue() == true))
155 || action.isEmptyBlock())) {
156 int jumpPC = codeStream.position;
157 codeStream.goto_(continueLabel);
158 codeStream.recordPositionsFrom(jumpPC, condition.sourceStart);
161 // generate the action
163 (actionLabel = new Label(codeStream)).place();
164 if (action != null) {
165 // Required to fix 1PR0XVS: LFRE:WINNT - Compiler: variable table for method appears incorrect
166 if (condIfTrueInitStateIndex != -1) {
167 // insert all locals initialized inside the condition into the action generated prior to the condition
168 codeStream.addDefinitelyAssignedVariables(
170 condIfTrueInitStateIndex);
172 action.generateCode(currentScope, codeStream);
173 // May loose some local variable initializations : affecting the local variable attributes
174 if (preCondInitStateIndex != -1) {
175 codeStream.removeNotDefinitelyAssignedVariables(
177 preCondInitStateIndex);
181 // output condition and branch back to the beginning of the repeated action
182 if (continueLabel != null) {
183 continueLabel.place();
184 condition.generateOptimizedBoolean(
193 // May loose some local variable initializations : affecting the local variable attributes
194 if (mergedInitStateIndex != -1) {
195 codeStream.removeNotDefinitelyAssignedVariables(
197 mergedInitStateIndex);
199 codeStream.recordPositionsFrom(pc, this.sourceStart);
202 public void resetStateForCodeGeneration() {
204 this.breakLabel.resetStateForCodeGeneration();
205 this.continueLabel.resetStateForCodeGeneration();
208 public void resolve(BlockScope scope) {
210 TypeBinding type = condition.resolveTypeExpecting(scope, BooleanBinding);
211 condition.implicitWidening(type, type);
213 action.resolve(scope);
216 public String toString(int tab) {
218 String s = tabString(tab);
219 s = s + "while (" + condition.toStringExpression() + ")"; //$NON-NLS-1$ //$NON-NLS-2$
221 s = s + " {} ;"; //$NON-NLS-1$
222 else if (action instanceof Block)
223 s = s + "\n" + action.toString(tab + 1); //$NON-NLS-1$
225 s = s + " {\n" + action.toString(tab + 1) + "}"; //$NON-NLS-2$ //$NON-NLS-1$
229 public void traverse(
230 IAbstractSyntaxTreeVisitor visitor,
231 BlockScope blockScope) {
233 if (visitor.visit(this, blockScope)) {
234 condition.traverse(visitor, blockScope);
236 action.traverse(visitor, blockScope);
238 visitor.endVisit(this, blockScope);