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 DoStatement extends Statement {
21 public Expression condition;
22 public Statement action;
24 private Label breakLabel, continueLabel;
26 // for local variables table attributes
27 int mergedInitStateIndex = -1;
29 public DoStatement(Expression condition, Statement action, int s, int e) {
33 this.condition = condition;
37 public FlowInfo analyseCode(
38 BlockScope currentScope,
39 FlowContext flowContext,
42 breakLabel = new Label();
43 continueLabel = new Label();
44 LoopingFlowContext loopingContext =
45 new LoopingFlowContext(
52 Constant conditionConstant = condition.constant;
53 Constant conditionalConstant = condition.conditionalConstant();
54 boolean isFalseCondition =
55 ((conditionConstant != NotAConstant)
56 && (conditionConstant.booleanValue() == false))
57 || ((conditionalConstant != NotAConstant)
58 && (conditionalConstant.booleanValue() == false));
60 if ((action != null) && !action.isEmptyBlock()) {
61 flowInfo = action.analyseCode(currentScope, loopingContext, flowInfo.copy());
63 // code generation can be optimized when no need to continue in the loop
64 if ((flowInfo == FlowInfo.DeadEnd) || flowInfo.isFakeReachable()) {
65 if ((loopingContext.initsOnContinue == FlowInfo.DeadEnd)
66 || loopingContext.initsOnContinue.isFakeReachable()) {
69 flowInfo = loopingContext.initsOnContinue; // for condition
70 if (isFalseCondition) {
71 // continueLabel = null; - cannot nil the label since may be targeted already by 'continue' statements
73 loopingContext.complainOnFinalAssignmentsInLoop(currentScope, flowInfo);
77 if (isFalseCondition) {
78 // continueLabel = null; - cannot nil the label since may be targeted already by 'continue' statements
80 loopingContext.complainOnFinalAssignmentsInLoop(currentScope, flowInfo);
84 LoopingFlowContext condLoopContext;
86 condition.analyseCode(
89 new LoopingFlowContext(flowContext, this, null, null, currentScope)),
92 : (flowInfo.mergedWith(loopingContext.initsOnContinue))));
93 condLoopContext.complainOnFinalAssignmentsInLoop(currentScope, flowInfo);
97 if ((condition.constant != NotAConstant)
98 && (condition.constant.booleanValue() == true)) {
99 mergedInfo = loopingContext.initsOnBreak;
100 mergedInitStateIndex =
101 currentScope.methodScope().recordInitializationStates(mergedInfo);
105 // end of loop: either condition false or break
107 flowInfo.initsWhenFalse().unconditionalInits().mergedWith(
108 loopingContext.initsOnBreak);
109 mergedInitStateIndex =
110 currentScope.methodScope().recordInitializationStates(mergedInfo);
115 * Do statement code generation
118 public void generateCode(BlockScope currentScope, CodeStream codeStream) {
120 if ((bits & IsReachableMASK) == 0) {
123 int pc = codeStream.position;
126 Label actionLabel = new Label(codeStream);
128 breakLabel.codeStream = codeStream;
129 if (continueLabel != null) {
130 continueLabel.codeStream = codeStream;
134 if (action != null) {
135 action.generateCode(currentScope, codeStream);
137 // generate condition
138 if (continueLabel != null) {
139 continueLabel.place();
140 condition.generateOptimizedBoolean(
149 // May loose some local variable initializations : affecting the local variable attributes
150 if (mergedInitStateIndex != -1) {
151 codeStream.removeNotDefinitelyAssignedVariables(
153 mergedInitStateIndex);
155 codeStream.recordPositionsFrom(pc, this.sourceStart);
159 public void resetStateForCodeGeneration() {
161 this.breakLabel.resetStateForCodeGeneration();
162 this.continueLabel.resetStateForCodeGeneration();
165 public void resolve(BlockScope scope) {
167 TypeBinding type = condition.resolveTypeExpecting(scope, BooleanBinding);
168 condition.implicitWidening(type, type);
170 action.resolve(scope);
173 public String toString(int tab) {
175 String inFront, s = tabString(tab);
177 s = s + "do"; //$NON-NLS-1$
179 s = s + " {}\n"; //$NON-NLS-1$
180 else if (action instanceof Block)
181 s = s + "\n" + action.toString(tab + 1) + "\n"; //$NON-NLS-2$ //$NON-NLS-1$
183 s = s + " {\n" + action.toString(tab + 1) + ";}\n"; //$NON-NLS-1$ //$NON-NLS-2$
184 s = s + inFront + "while (" + condition.toStringExpression() + ")"; //$NON-NLS-1$ //$NON-NLS-2$
188 public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
190 if (visitor.visit(this, scope)) {
191 if (action != null) {
192 action.traverse(visitor, scope);
194 condition.traverse(visitor, scope);
196 visitor.endVisit(this, scope);