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 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                 preCondInitStateIndex =
 
  49                         currentScope.methodScope().recordInitializationStates(flowInfo);
 
  50                 LoopingFlowContext condLoopContext;
 
  51                 FlowInfo postCondInfo =
 
  52                         condition.analyseCode(
 
  55                                         new LoopingFlowContext(flowContext, this, null, null, currentScope)),
 
  58                 LoopingFlowContext loopingContext;
 
  59                 if ((action == null) || action.isEmptyBlock()) {
 
  60                         condLoopContext.complainOnFinalAssignmentsInLoop(currentScope, postCondInfo);
 
  61                         if ((condition.constant != NotAConstant)
 
  62                                 && (condition.constant.booleanValue() == true)) {
 
  63                                 return FlowInfo.DeadEnd;
 
  65                                 FlowInfo mergedInfo = postCondInfo.initsWhenFalse().unconditionalInits();
 
  66                                 mergedInitStateIndex =
 
  67                                         currentScope.methodScope().recordInitializationStates(mergedInfo);
 
  71                         // in case the condition was inlined to false, record the fact that there is no way to reach any 
 
  72                         // statement inside the looping action
 
  74                                 new LoopingFlowContext(
 
  81                                 ((condition.constant != Constant.NotAConstant)
 
  82                                         && (condition.constant.booleanValue() == false))
 
  84                                         : postCondInfo.initsWhenTrue().copy();
 
  86                         // for computing local var attributes
 
  87                         condIfTrueInitStateIndex =
 
  88                                 currentScope.methodScope().recordInitializationStates(
 
  89                                         postCondInfo.initsWhenTrue());
 
  91                         if (!actionInfo.complainIfUnreachable(action, currentScope)) {
 
  92                                 actionInfo = action.analyseCode(currentScope, loopingContext, actionInfo);
 
  95                         // code generation can be optimized when no need to continue in the loop
 
  96                         if (((actionInfo == FlowInfo.DeadEnd) || actionInfo.isFakeReachable())
 
  97                                 && ((loopingContext.initsOnContinue == FlowInfo.DeadEnd)
 
  98                                         || loopingContext.initsOnContinue.isFakeReachable())) {
 
 101                                 condLoopContext.complainOnFinalAssignmentsInLoop(currentScope, postCondInfo);
 
 102                                 loopingContext.complainOnFinalAssignmentsInLoop(currentScope, actionInfo);
 
 108                 if ((condition.constant != Constant.NotAConstant)
 
 109                         && (condition.constant.booleanValue() == true)) {
 
 110                         mergedInitStateIndex =
 
 111                                 currentScope.methodScope().recordInitializationStates(
 
 112                                         mergedInfo = loopingContext.initsOnBreak);
 
 116                 // end of loop: either condition false or break
 
 118                         postCondInfo.initsWhenFalse().unconditionalInits().mergedWith(
 
 119                                 loopingContext.initsOnBreak);
 
 120                 mergedInitStateIndex =
 
 121                         currentScope.methodScope().recordInitializationStates(mergedInfo);
 
 126          * While code generation
 
 128          * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
 
 129          * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
 
 131         public void generateCode(BlockScope currentScope, CodeStream codeStream) {
 
 133                 if ((bits & IsReachableMASK) == 0) {
 
 136                 int pc = codeStream.position;
 
 137                 breakLabel.codeStream = codeStream;
 
 139                 // generate condition
 
 140                 if (continueLabel == null) {
 
 141                         // no need to reverse condition
 
 142                         if (condition.constant == NotAConstant) {
 
 143                                 condition.generateOptimizedBoolean(
 
 151                         continueLabel.codeStream = codeStream;
 
 152                         if (!(((condition.constant != NotAConstant)
 
 153                                 && (condition.constant.booleanValue() == true))
 
 155                                 || action.isEmptyBlock())) {
 
 156                                 int jumpPC = codeStream.position;
 
 157                                 codeStream.goto_(continueLabel);
 
 158                                 codeStream.recordPositionsFrom(jumpPC, condition.sourceStart);
 
 161                 // generate the action
 
 163                 (actionLabel = new Label(codeStream)).place();
 
 164                 if (action != null) {
 
 165                         // Required to fix 1PR0XVS: LFRE:WINNT - Compiler: variable table for method appears incorrect
 
 166                         if (condIfTrueInitStateIndex != -1) {
 
 167                                 // insert all locals initialized inside the condition into the action generated prior to the condition
 
 168                                 codeStream.addDefinitelyAssignedVariables(
 
 170                                         condIfTrueInitStateIndex);
 
 172                         action.generateCode(currentScope, codeStream);
 
 173                         // May loose some local variable initializations : affecting the local variable attributes
 
 174                         if (preCondInitStateIndex != -1) {
 
 175                                 codeStream.removeNotDefinitelyAssignedVariables(
 
 177                                         preCondInitStateIndex);
 
 181                 // output condition and branch back to the beginning of the repeated action
 
 182                 if (continueLabel != null) {
 
 183                         continueLabel.place();
 
 184                         condition.generateOptimizedBoolean(
 
 193                 // May loose some local variable initializations : affecting the local variable attributes
 
 194                 if (mergedInitStateIndex != -1) {
 
 195                         codeStream.removeNotDefinitelyAssignedVariables(
 
 197                                 mergedInitStateIndex);
 
 199                 codeStream.recordPositionsFrom(pc, this.sourceStart);
 
 202         public void resetStateForCodeGeneration() {
 
 204                 this.breakLabel.resetStateForCodeGeneration();
 
 205                 this.continueLabel.resetStateForCodeGeneration();
 
 208         public void resolve(BlockScope scope) {
 
 210                 TypeBinding type = condition.resolveTypeExpecting(scope, BooleanBinding);
 
 211                 condition.implicitWidening(type, type);
 
 213                         action.resolve(scope);
 
 216         public String toString(int tab) {
 
 218                 String s = tabString(tab);
 
 219                 s = s + "while (" + condition.toStringExpression() + ")";       //$NON-NLS-1$ //$NON-NLS-2$
 
 221                         s = s + " {} ;"; //$NON-NLS-1$ 
 
 222                 else if (action instanceof Block)
 
 223                         s = s + "\n" + action.toString(tab + 1); //$NON-NLS-1$
 
 225                         s = s + " {\n" + action.toString(tab + 1) + "}"; //$NON-NLS-2$ //$NON-NLS-1$
 
 229         public void traverse(
 
 230                 IAbstractSyntaxTreeVisitor visitor,
 
 231                 BlockScope blockScope) {
 
 233                 if (visitor.visit(this, blockScope)) {
 
 234                         condition.traverse(visitor, blockScope);
 
 236                                 action.traverse(visitor, blockScope);
 
 238                 visitor.endVisit(this, blockScope);