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 DoStatement extends Statement {
25 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(
42 BlockScope currentScope,
43 FlowContext flowContext,
46 breakLabel = new Label();
47 continueLabel = new Label();
48 LoopingFlowContext loopingContext =
49 new LoopingFlowContext(
56 Constant conditionConstant = condition.constant;
57 Constant conditionalConstant = condition.conditionalConstant();
58 boolean isFalseCondition =
59 ((conditionConstant != NotAConstant)
60 && (conditionConstant.booleanValue() == false))
61 || ((conditionalConstant != NotAConstant)
62 && (conditionalConstant.booleanValue() == false));
64 if ((action != null) && !action.isEmptyBlock()) {
65 flowInfo = action.analyseCode(currentScope, loopingContext, flowInfo.copy());
67 // code generation can be optimized when no need to continue in the loop
68 if ((flowInfo == FlowInfo.DeadEnd) || flowInfo.isFakeReachable()) {
69 if ((loopingContext.initsOnContinue == FlowInfo.DeadEnd)
70 || loopingContext.initsOnContinue.isFakeReachable()) {
73 flowInfo = loopingContext.initsOnContinue; // for condition
74 if (isFalseCondition) {
75 // continueLabel = null; - cannot nil the label since may be targeted already by 'continue' statements
77 loopingContext.complainOnFinalAssignmentsInLoop(currentScope, flowInfo);
81 if (isFalseCondition) {
82 // continueLabel = null; - cannot nil the label since may be targeted already by 'continue' statements
84 loopingContext.complainOnFinalAssignmentsInLoop(currentScope, flowInfo);
88 LoopingFlowContext condLoopContext;
90 condition.analyseCode(
93 new LoopingFlowContext(flowContext, this, null, null, currentScope)),
96 : (flowInfo.mergedWith(loopingContext.initsOnContinue))));
97 condLoopContext.complainOnFinalAssignmentsInLoop(currentScope, flowInfo);
101 if ((condition.constant != NotAConstant)
102 && (condition.constant.booleanValue() == true)) {
103 mergedInfo = loopingContext.initsOnBreak;
104 mergedInitStateIndex =
105 currentScope.methodScope().recordInitializationStates(mergedInfo);
109 // end of loop: either condition false or break
111 flowInfo.initsWhenFalse().unconditionalInits().mergedWith(
112 loopingContext.initsOnBreak);
113 mergedInitStateIndex =
114 currentScope.methodScope().recordInitializationStates(mergedInfo);
119 * Do statement code generation
122 public void generateCode(BlockScope currentScope, CodeStream codeStream) {
124 if ((bits & IsReachableMASK) == 0) {
127 int pc = codeStream.position;
130 Label actionLabel = new Label(codeStream);
132 breakLabel.codeStream = codeStream;
133 if (continueLabel != null) {
134 continueLabel.codeStream = codeStream;
138 if (action != null) {
139 action.generateCode(currentScope, codeStream);
141 // generate condition
142 if (continueLabel != null) {
143 continueLabel.place();
144 condition.generateOptimizedBoolean(
153 // May loose some local variable initializations : affecting the local variable attributes
154 if (mergedInitStateIndex != -1) {
155 codeStream.removeNotDefinitelyAssignedVariables(
157 mergedInitStateIndex);
159 codeStream.recordPositionsFrom(pc, this.sourceStart);
163 public void resetStateForCodeGeneration() {
165 this.breakLabel.resetStateForCodeGeneration();
166 this.continueLabel.resetStateForCodeGeneration();
169 public void resolve(BlockScope scope) {
171 TypeBinding type = condition.resolveTypeExpecting(scope, BooleanBinding);
172 condition.implicitWidening(type, type);
174 action.resolve(scope);
177 public String toString(int tab) {
179 String inFront, s = tabString(tab);
181 s = s + "do"; //$NON-NLS-1$
183 s = s + " {}\n"; //$NON-NLS-1$
184 else if (action instanceof Block)
185 s = s + "\n" + action.toString(tab + 1) + "\n"; //$NON-NLS-2$ //$NON-NLS-1$
187 s = s + " {\n" + action.toString(tab + 1) + ";}\n"; //$NON-NLS-1$ //$NON-NLS-2$
188 s = s + inFront + "while (" + condition.toStringExpression() + ")"; //$NON-NLS-1$ //$NON-NLS-2$
192 public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
194 if (visitor.visit(this, scope)) {
195 if (action != null) {
196 action.traverse(visitor, scope);
198 condition.traverse(visitor, scope);
200 visitor.endVisit(this, scope);