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.impl.*;
15 import net.sourceforge.phpdt.internal.compiler.codegen.*;
16 import net.sourceforge.phpdt.internal.compiler.flow.*;
17 import net.sourceforge.phpdt.internal.compiler.lookup.*;
19 public class WhileStatement extends Statement {
21 public Expression condition;
22 public Statement action;
23 private Label breakLabel, continueLabel;
24 int preCondInitStateIndex = -1;
25 int condIfTrueInitStateIndex = -1;
26 int mergedInitStateIndex = -1;
28 public WhileStatement(Expression condition, Statement action, int s, int e) {
30 this.condition = condition;
36 public FlowInfo analyseCode(
37 BlockScope currentScope,
38 FlowContext flowContext,
41 breakLabel = new Label();
42 continueLabel = new Label();
44 preCondInitStateIndex =
45 currentScope.methodScope().recordInitializationStates(flowInfo);
46 LoopingFlowContext condLoopContext;
47 FlowInfo postCondInfo =
48 condition.analyseCode(
51 new LoopingFlowContext(flowContext, this, null, null, currentScope)),
54 LoopingFlowContext loopingContext;
55 if ((action == null) || action.isEmptyBlock()) {
56 condLoopContext.complainOnFinalAssignmentsInLoop(currentScope, postCondInfo);
57 if ((condition.constant != NotAConstant)
58 && (condition.constant.booleanValue() == true)) {
59 return FlowInfo.DeadEnd;
61 FlowInfo mergedInfo = postCondInfo.initsWhenFalse().unconditionalInits();
62 mergedInitStateIndex =
63 currentScope.methodScope().recordInitializationStates(mergedInfo);
67 // in case the condition was inlined to false, record the fact that there is no way to reach any
68 // statement inside the looping action
70 new LoopingFlowContext(
77 ((condition.constant != Constant.NotAConstant)
78 && (condition.constant.booleanValue() == false))
80 : postCondInfo.initsWhenTrue().copy();
82 // for computing local var attributes
83 condIfTrueInitStateIndex =
84 currentScope.methodScope().recordInitializationStates(
85 postCondInfo.initsWhenTrue());
87 if (!actionInfo.complainIfUnreachable(action, currentScope)) {
88 actionInfo = action.analyseCode(currentScope, loopingContext, actionInfo);
91 // code generation can be optimized when no need to continue in the loop
92 if (((actionInfo == FlowInfo.DeadEnd) || actionInfo.isFakeReachable())
93 && ((loopingContext.initsOnContinue == FlowInfo.DeadEnd)
94 || loopingContext.initsOnContinue.isFakeReachable())) {
97 condLoopContext.complainOnFinalAssignmentsInLoop(currentScope, postCondInfo);
98 loopingContext.complainOnFinalAssignmentsInLoop(currentScope, actionInfo);
104 if ((condition.constant != Constant.NotAConstant)
105 && (condition.constant.booleanValue() == true)) {
106 mergedInitStateIndex =
107 currentScope.methodScope().recordInitializationStates(
108 mergedInfo = loopingContext.initsOnBreak);
112 // end of loop: either condition false or break
114 postCondInfo.initsWhenFalse().unconditionalInits().mergedWith(
115 loopingContext.initsOnBreak);
116 mergedInitStateIndex =
117 currentScope.methodScope().recordInitializationStates(mergedInfo);
122 * While code generation
124 * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
125 * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
127 public void generateCode(BlockScope currentScope, CodeStream codeStream) {
129 if ((bits & IsReachableMASK) == 0) {
132 int pc = codeStream.position;
133 breakLabel.codeStream = codeStream;
135 // generate condition
136 if (continueLabel == null) {
137 // no need to reverse condition
138 if (condition.constant == NotAConstant) {
139 condition.generateOptimizedBoolean(
147 continueLabel.codeStream = codeStream;
148 if (!(((condition.constant != NotAConstant)
149 && (condition.constant.booleanValue() == true))
151 || action.isEmptyBlock())) {
152 int jumpPC = codeStream.position;
153 codeStream.goto_(continueLabel);
154 codeStream.recordPositionsFrom(jumpPC, condition.sourceStart);
157 // generate the action
159 (actionLabel = new Label(codeStream)).place();
160 if (action != null) {
161 // Required to fix 1PR0XVS: LFRE:WINNT - Compiler: variable table for method appears incorrect
162 if (condIfTrueInitStateIndex != -1) {
163 // insert all locals initialized inside the condition into the action generated prior to the condition
164 codeStream.addDefinitelyAssignedVariables(
166 condIfTrueInitStateIndex);
168 action.generateCode(currentScope, codeStream);
169 // May loose some local variable initializations : affecting the local variable attributes
170 if (preCondInitStateIndex != -1) {
171 codeStream.removeNotDefinitelyAssignedVariables(
173 preCondInitStateIndex);
177 // output condition and branch back to the beginning of the repeated action
178 if (continueLabel != null) {
179 continueLabel.place();
180 condition.generateOptimizedBoolean(
189 // May loose some local variable initializations : affecting the local variable attributes
190 if (mergedInitStateIndex != -1) {
191 codeStream.removeNotDefinitelyAssignedVariables(
193 mergedInitStateIndex);
195 codeStream.recordPositionsFrom(pc, this.sourceStart);
198 public void resetStateForCodeGeneration() {
200 this.breakLabel.resetStateForCodeGeneration();
201 this.continueLabel.resetStateForCodeGeneration();
204 public void resolve(BlockScope scope) {
206 TypeBinding type = condition.resolveTypeExpecting(scope, BooleanBinding);
207 condition.implicitWidening(type, type);
209 action.resolve(scope);
212 public String toString(int tab) {
214 String s = tabString(tab);
215 s = s + "while (" + condition.toStringExpression() + ")"; //$NON-NLS-1$ //$NON-NLS-2$
217 s = s + " {} ;"; //$NON-NLS-1$
218 else if (action instanceof Block)
219 s = s + "\n" + action.toString(tab + 1); //$NON-NLS-1$
221 s = s + " {\n" + action.toString(tab + 1) + "}"; //$NON-NLS-2$ //$NON-NLS-1$
225 public void traverse(
226 IAbstractSyntaxTreeVisitor visitor,
227 BlockScope blockScope) {
229 if (visitor.visit(this, blockScope)) {
230 condition.traverse(visitor, blockScope);
232 action.traverse(visitor, blockScope);
234 visitor.endVisit(this, blockScope);