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.IAbstractSyntaxTreeVisitor;
 
  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);
 
 170         public String toString(int tab) {
 
 172                 String inFront, s = tabString(tab);
 
 174                 s = s + "do"; //$NON-NLS-1$
 
 176                         s = s + " {}\n"; //$NON-NLS-1$
 
 177                 else if (action instanceof Block)
 
 178                         s = s + "\n" + action.toString(tab + 1) + "\n"; //$NON-NLS-2$ //$NON-NLS-1$
 
 180                         s = s + " {\n" + action.toString(tab + 1) + ";}\n"; //$NON-NLS-1$ //$NON-NLS-2$
 
 181                 s = s + inFront + "while (" + condition.toStringExpression() + ")"; //$NON-NLS-1$ //$NON-NLS-2$
 
 185         public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
 
 187                 if (visitor.visit(this, scope)) {
 
 188                         if (action != null) {
 
 189                                 action.traverse(visitor, scope);
 
 191                         condition.traverse(visitor, scope);
 
 193                 visitor.endVisit(this, scope);