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
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpeclipse.internal.compiler.ast;
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;
22 public class DoStatement extends Statement {
24 public Expression condition;
25 public Statement action;
27 private Label breakLabel, continueLabel;
29 // for local variables table attributes
30 int mergedInitStateIndex = -1;
32 public DoStatement(Expression condition, Statement action, int s, int e) {
36 this.condition = condition;
40 public FlowInfo analyseCode(
41 BlockScope currentScope,
42 FlowContext flowContext,
45 breakLabel = new Label();
46 continueLabel = new Label();
47 LoopingFlowContext loopingContext =
48 new LoopingFlowContext(
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;
61 int previousMode = flowInfo.reachMode();
63 if ((action != null) && !action.isEmptyBlock()) {
64 flowInfo = action.analyseCode(currentScope, loopingContext, flowInfo);
66 // code generation can be optimized when no need to continue in the loop
67 if (!flowInfo.isReachable() && !loopingContext.initsOnContinue.isReachable()) {
71 /* Reset reach mode, to address following scenario.
73 * do { if (true) break; else blank = 0; } while(false);
74 * blank = 1; // may be initialized already
76 flowInfo.setReachMode(previousMode);
79 condition.analyseCode(
84 : (flowInfo.mergedWith(loopingContext.initsOnContinue))));
85 if (!isConditionOptimizedFalse && continueLabel != null) {
86 loopingContext.complainOnFinalAssignmentsInLoop(currentScope, flowInfo);
91 if (isConditionTrue) {
92 mergedInfo = loopingContext.initsOnBreak;
93 if (!mergedInfo.isReachable()) mergedInfo.addPotentialInitializationsFrom(flowInfo.initsWhenFalse());
95 // end of loop: either condition false or break
97 flowInfo.initsWhenFalse().unconditionalInits().mergedWith(
98 loopingContext.initsOnBreak);
99 if (isConditionOptimizedTrue && !loopingContext.initsOnBreak.isReachable()) {
100 mergedInfo.setReachMode(FlowInfo.UNREACHABLE);
103 mergedInitStateIndex =
104 currentScope.methodScope().recordInitializationStates(mergedInfo);
109 * Do statement code generation
112 // public void generateCode(BlockScope currentScope, CodeStream codeStream) {
114 // if ((bits & IsReachableMASK) == 0) {
117 // int pc = codeStream.position;
119 // // labels management
120 // Label actionLabel = new Label(codeStream);
121 // actionLabel.place();
122 // breakLabel.codeStream = codeStream;
123 // if (continueLabel != null) {
124 // continueLabel.codeStream = codeStream;
127 // // generate action
128 // if (action != null) {
129 // action.generateCode(currentScope, codeStream);
131 // // generate condition
132 // if (continueLabel != null) {
133 // continueLabel.place();
134 // condition.generateOptimizedBoolean(
141 // breakLabel.place();
143 // // May loose some local variable initializations : affecting the local variable attributes
144 // if (mergedInitStateIndex != -1) {
145 // codeStream.removeNotDefinitelyAssignedVariables(
147 // mergedInitStateIndex);
149 // codeStream.recordPositionsFrom(pc, this.sourceStart);
153 public void resetStateForCodeGeneration() {
154 if (this.breakLabel != null) {
155 this.breakLabel.resetStateForCodeGeneration();
157 if (this.continueLabel != null) {
158 this.continueLabel.resetStateForCodeGeneration();
162 public void resolve(BlockScope scope) {
164 TypeBinding type = condition.resolveTypeExpecting(scope, BooleanBinding);
165 condition.implicitWidening(type, type);
167 action.resolve(scope);
169 public StringBuffer printStatement(int indent, StringBuffer output) {
171 printIndent(indent, output).append("do"); //$NON-NLS-1$
173 output.append(" ;\n"); //$NON-NLS-1$
176 action.printStatement(indent + 1, output).append('\n');
178 output.append("while ("); //$NON-NLS-1$
179 return condition.printExpression(0, output).append(");"); //$NON-NLS-1$
181 public String toString(int tab) {
183 String inFront, s = tabString(tab);
185 s = s + "do"; //$NON-NLS-1$
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$
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$
196 public void traverse(ASTVisitor visitor, BlockScope scope) {
198 if (visitor.visit(this, scope)) {
199 if (action != null) {
200 action.traverse(visitor, scope);
202 condition.traverse(visitor, scope);
204 visitor.endVisit(this, scope);