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;
 
  23 public class WhileStatement extends Statement {
 
  25         public Expression condition;
 
  26         public Statement action;
 
  27         private Label breakLabel, continueLabel;
 
  28         int preCondInitStateIndex = -1;
 
  29         int condIfTrueInitStateIndex = -1;
 
  30         int mergedInitStateIndex = -1;
 
  32         public WhileStatement(Expression condition, Statement action, int s, int e) {
 
  34                 this.condition = condition;
 
  40         public FlowInfo analyseCode(
 
  41                 BlockScope currentScope,
 
  42                 FlowContext flowContext,
 
  45                 breakLabel = new Label();
 
  46                 continueLabel = new Label(); 
 
  48                 Constant cst = this.condition.constant;
 
  49                 boolean isConditionTrue = cst != NotAConstant && cst.booleanValue() == true;
 
  50                 boolean isConditionFalse = cst != NotAConstant && cst.booleanValue() == false;
 
  52                 cst = this.condition.optimizedBooleanConstant();
 
  53                 boolean isConditionOptimizedTrue = cst != NotAConstant && cst.booleanValue() == true;
 
  54                 boolean isConditionOptimizedFalse = cst != NotAConstant && cst.booleanValue() == false;
 
  56                 preCondInitStateIndex =
 
  57                         currentScope.methodScope().recordInitializationStates(flowInfo);
 
  58                 LoopingFlowContext condLoopContext;
 
  59                 FlowInfo postCondInfo =
 
  60                         this.condition.analyseCode(
 
  63                                         new LoopingFlowContext(flowContext, this, null, null, currentScope)),
 
  66                 LoopingFlowContext loopingContext;
 
  69 //                      || (action.isEmptyBlock() && currentScope.environment().options.complianceLevel <= CompilerOptions.JDK1_3)) {
 
  70 //                      condLoopContext.complainOnFinalAssignmentsInLoop(currentScope, postCondInfo);
 
  71 //                      if (isConditionTrue) {
 
  72 //                              return FlowInfo.DEAD_END;
 
  74 //                              FlowInfo mergedInfo = postCondInfo.initsWhenFalse().unconditionalInits();
 
  75 //                              if (isConditionOptimizedTrue){
 
  76 //                                      mergedInfo.setReachMode(FlowInfo.UNREACHABLE);
 
  78 //                              mergedInitStateIndex =
 
  79 //                                      currentScope.methodScope().recordInitializationStates(mergedInfo);
 
  83                         // in case the condition was inlined to false, record the fact that there is no way to reach any 
 
  84                         // statement inside the looping action
 
  86                                 new LoopingFlowContext(
 
  92                         if (isConditionFalse) {
 
  93                                 actionInfo = FlowInfo.DEAD_END;
 
  95                                 actionInfo = postCondInfo.initsWhenTrue().copy();
 
  96                                 if (isConditionOptimizedFalse){
 
  97                                         actionInfo.setReachMode(FlowInfo.UNREACHABLE);
 
 101                         // for computing local var attributes
 
 102                         condIfTrueInitStateIndex =
 
 103                                 currentScope.methodScope().recordInitializationStates(
 
 104                                         postCondInfo.initsWhenTrue());
 
 106                         if (!actionInfo.complainIfUnreachable(action, currentScope, false)) {
 
 107                                 actionInfo = action.analyseCode(currentScope, loopingContext, actionInfo);
 
 110                         // code generation can be optimized when no need to continue in the loop
 
 111                         if (!actionInfo.isReachable() && !loopingContext.initsOnContinue.isReachable()) {
 
 112                                 continueLabel = null;
 
 114                                 // TODO: (philippe) should simplify in one Loop context
 
 115                                 condLoopContext.complainOnFinalAssignmentsInLoop(currentScope, postCondInfo);
 
 116                                 loopingContext.complainOnFinalAssignmentsInLoop(currentScope, actionInfo);
 
 122                 if (isConditionOptimizedTrue) {
 
 123                         mergedInitStateIndex =
 
 124                                 currentScope.methodScope().recordInitializationStates(
 
 125                                         mergedInfo = loopingContext.initsOnBreak);
 
 129                 // end of loop: either condition false or break
 
 131                         postCondInfo.initsWhenFalse().unconditionalInits().mergedWith(
 
 132                                 loopingContext.initsOnBreak);
 
 133                 if (isConditionOptimizedTrue && continueLabel == null){
 
 134                         mergedInfo.setReachMode(FlowInfo.UNREACHABLE);
 
 136                 mergedInitStateIndex =
 
 137                         currentScope.methodScope().recordInitializationStates(mergedInfo);
 
 142          * While code generation
 
 144          * @param currentScope net.sourceforge.phpdt.internal.compiler.lookup.BlockScope
 
 145          * @param codeStream net.sourceforge.phpdt.internal.compiler.codegen.CodeStream
 
 147 //      public void generateCode(BlockScope currentScope, CodeStream codeStream) {
 
 149 //              if ((bits & IsReachableMASK) == 0) {
 
 152 //              int pc = codeStream.position;
 
 153 //              breakLabel.codeStream = codeStream;
 
 155 //              // generate condition
 
 156 //              if (continueLabel == null) {
 
 157 //                      // no need to reverse condition
 
 158 //                      if (condition.constant == NotAConstant) {
 
 159 //                              condition.generateOptimizedBoolean(
 
 167 //                      continueLabel.codeStream = codeStream;
 
 168 //                      if (!(((condition.constant != NotAConstant)
 
 169 //                              && (condition.constant.booleanValue() == true))
 
 170 //                              || (action == null)
 
 171 //                              || action.isEmptyBlock())) {
 
 172 //                              int jumpPC = codeStream.position;
 
 173 //                              codeStream.goto_(continueLabel);
 
 174 //                              codeStream.recordPositionsFrom(jumpPC, condition.sourceStart);
 
 177 //              // generate the action
 
 178 //              Label actionLabel;
 
 179 //              (actionLabel = new Label(codeStream)).place();
 
 180 //              if (action != null) {
 
 181 //                      // Required to fix 1PR0XVS: LFRE:WINNT - Compiler: variable table for method appears incorrect
 
 182 //                      if (condIfTrueInitStateIndex != -1) {
 
 183 //                              // insert all locals initialized inside the condition into the action generated prior to the condition
 
 184 //                              codeStream.addDefinitelyAssignedVariables(
 
 186 //                                      condIfTrueInitStateIndex);
 
 188 //                      action.generateCode(currentScope, codeStream);
 
 189 //                      // May loose some local variable initializations : affecting the local variable attributes
 
 190 //                      if (preCondInitStateIndex != -1) {
 
 191 //                              codeStream.removeNotDefinitelyAssignedVariables(
 
 193 //                                      preCondInitStateIndex);
 
 197 //              // output condition and branch back to the beginning of the repeated action
 
 198 //              if (continueLabel != null) {
 
 199 //                      continueLabel.place();
 
 200 //                      condition.generateOptimizedBoolean(
 
 207 //              breakLabel.place();
 
 209 //              // May loose some local variable initializations : affecting the local variable attributes
 
 210 //              if (mergedInitStateIndex != -1) {
 
 211 //                      codeStream.removeNotDefinitelyAssignedVariables(
 
 213 //                              mergedInitStateIndex);
 
 215 //              codeStream.recordPositionsFrom(pc, this.sourceStart);
 
 218         public void resetStateForCodeGeneration() {
 
 219                 if (this.breakLabel != null) {
 
 220                         this.breakLabel.resetStateForCodeGeneration();
 
 222                 if (this.continueLabel != null) {
 
 223                         this.continueLabel.resetStateForCodeGeneration();
 
 226         public StringBuffer printStatement(int tab, StringBuffer output) {
 
 228                 printIndent(tab, output).append("while ("); //$NON-NLS-1$
 
 229                 condition.printExpression(0, output).append(')');
 
 233                         action.printStatement(tab + 1, output); 
 
 236         public void resolve(BlockScope scope) {
 
 238                 TypeBinding type = condition.resolveTypeExpecting(scope, BooleanBinding);
 
 239                 condition.implicitWidening(type, type);
 
 241                         action.resolve(scope);
 
 244         public String toString(int tab) {
 
 246                 String s = tabString(tab);
 
 247                 s = s + "while (" + condition.toStringExpression() + ")";       //$NON-NLS-1$ //$NON-NLS-2$
 
 249                         s = s + " {} ;"; //$NON-NLS-1$ 
 
 250                 else if (action instanceof Block)
 
 251                         s = s + "\n" + action.toString(tab + 1); //$NON-NLS-1$
 
 253                         s = s + " {\n" + action.toString(tab + 1) + "}"; //$NON-NLS-2$ //$NON-NLS-1$
 
 257         public void traverse(
 
 259                 BlockScope blockScope) {
 
 261                 if (visitor.visit(this, blockScope)) {
 
 262                         condition.traverse(visitor, blockScope);
 
 264                                 action.traverse(visitor, blockScope);
 
 266                 visitor.endVisit(this, blockScope);