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.phpdt.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;
26 public Statement action;
28 private Label breakLabel, continueLabel;
30 // for local variables table attributes
31 int mergedInitStateIndex = -1;
33 public DoStatement(Expression condition, Statement action, int s, int e) {
37 this.condition = condition;
41 public FlowInfo analyseCode(BlockScope currentScope,
42 FlowContext flowContext, FlowInfo flowInfo) {
44 breakLabel = new Label();
45 continueLabel = new Label();
46 LoopingFlowContext loopingContext = new LoopingFlowContext(flowContext,
47 this, breakLabel, continueLabel, currentScope);
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;
58 int previousMode = flowInfo.reachMode();
60 if ((action != null) && !action.isEmptyBlock()) {
61 flowInfo = action.analyseCode(currentScope, loopingContext,
64 // code generation can be optimized when no need to continue in the
66 if (!flowInfo.isReachable()
67 && !loopingContext.initsOnContinue.isReachable()) {
72 * Reset reach mode, to address following scenario. final blank; do { if
73 * (true) break; else blank = 0; } while(false); blank = 1; // may be
76 flowInfo.setReachMode(previousMode);
78 flowInfo = condition.analyseCode(currentScope, loopingContext,
79 (action == null ? flowInfo : (flowInfo
80 .mergedWith(loopingContext.initsOnContinue))));
81 if (!isConditionOptimizedFalse && continueLabel != null) {
82 loopingContext.complainOnFinalAssignmentsInLoop(currentScope,
88 if (isConditionTrue) {
89 mergedInfo = loopingContext.initsOnBreak;
90 if (!mergedInfo.isReachable())
91 mergedInfo.addPotentialInitializationsFrom(flowInfo
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);
102 mergedInitStateIndex = currentScope.methodScope()
103 .recordInitializationStates(mergedInfo);
108 * Do statement code generation
111 // 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
144 // variable attributes
145 // if (mergedInitStateIndex != -1) {
146 // codeStream.removeNotDefinitelyAssignedVariables(
148 // mergedInitStateIndex);
150 // 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
165 .resolveTypeExpecting(scope, BooleanBinding);
166 condition.implicitWidening(type, type);
168 action.resolve(scope);
171 public StringBuffer printStatement(int indent, StringBuffer output) {
173 printIndent(indent, output).append("do"); //$NON-NLS-1$
175 output.append(" ;\n"); //$NON-NLS-1$
178 action.printStatement(indent + 1, output).append('\n');
180 output.append("while ("); //$NON-NLS-1$
181 return condition.printExpression(0, output).append(");"); //$NON-NLS-1$
184 public String toString(int tab) {
186 String inFront, s = tabString(tab);
188 s = s + "do"; //$NON-NLS-1$
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$
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$
199 public void traverse(ASTVisitor visitor, BlockScope scope) {
201 if (visitor.visit(this, scope)) {
202 if (action != null) {
203 action.traverse(visitor, scope);
205 condition.traverse(visitor, scope);
207 visitor.endVisit(this, scope);