Refactored packagename to net.sourceforge.phpdt.internal.compiler.ast
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / ast / IfStatement.java
index 2c11637..7959ba7 100644 (file)
@@ -1,20 +1,21 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials 
- * are made available under the terms of the Common Public License v0.5 
+ * are made available under the terms of the Common Public License v1.0
  * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v05.html
+ * http://www.eclipse.org/legal/cpl-v10.html
  * 
  * Contributors:
  *     IBM Corporation - initial API and implementation
- ******************************************************************************/
+ *******************************************************************************/
 package net.sourceforge.phpdt.internal.compiler.ast;
 
-import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
-import net.sourceforge.phpdt.internal.compiler.impl.*;
-import net.sourceforge.phpdt.internal.compiler.codegen.*;
-import net.sourceforge.phpdt.internal.compiler.flow.*;
-import net.sourceforge.phpdt.internal.compiler.lookup.*;
+import net.sourceforge.phpdt.internal.compiler.ASTVisitor;
+import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
+import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
+import net.sourceforge.phpdt.internal.compiler.impl.Constant;
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
 
 public class IfStatement extends Statement {
        
@@ -24,8 +25,11 @@ public class IfStatement extends Statement {
        public Expression condition;
        public Statement thenStatement;
        public Statement elseStatement;
-
+       public Expression[] elseifConditions;
+       public Statement[] elseifStatements;
+       public boolean checkUnreachable;
        boolean thenExit;
+       
 
        // for local variables table attributes
        int thenInitStateIndex = -1;
@@ -42,6 +46,7 @@ public class IfStatement extends Statement {
                this.thenStatement = thenStatement;
                sourceStart = s;
                sourceEnd = e;
+               checkUnreachable = true;
        }
 
        public IfStatement(
@@ -56,6 +61,7 @@ public class IfStatement extends Statement {
                this.elseStatement = elseStatement;
                sourceEnd = e;
                sourceStart = s;
+               checkUnreachable = true;
        }
 
        public FlowInfo analyseCode(
@@ -63,86 +69,84 @@ public class IfStatement extends Statement {
                FlowContext flowContext,
                FlowInfo flowInfo) {
 
-               FlowInfo thenFlowInfo, elseFlowInfo;
-
                // process the condition
                flowInfo = condition.analyseCode(currentScope, flowContext, flowInfo);
 
+               Constant cst = this.condition.optimizedBooleanConstant();
+               boolean isConditionOptimizedTrue = cst != NotAConstant && cst.booleanValue() == true;
+               boolean isConditionOptimizedFalse = cst != NotAConstant && cst.booleanValue() == false;
+               
                // process the THEN part
-               if (thenStatement == null) {
-                       thenFlowInfo = flowInfo.initsWhenTrue();
-               } else {
-                       Constant cst;
-                       thenFlowInfo =
-                               ((((cst = condition.constant) != NotAConstant)
-                                       && (cst.booleanValue() == false))
-                                       || (((cst = condition.conditionalConstant()) != NotAConstant)
-                                               && (cst.booleanValue() == false)))
-                                       ? (flowInfo.initsWhenTrue().copy().markAsFakeReachable(true))
-                                       : flowInfo.initsWhenTrue().copy();
+               FlowInfo thenFlowInfo = flowInfo.initsWhenTrue().copy();
+               if (isConditionOptimizedFalse) {
+                       thenFlowInfo.setReachMode(FlowInfo.UNREACHABLE); 
+               }
+               if (this.thenStatement != null) {
                        // Save info for code gen
                        thenInitStateIndex =
                                currentScope.methodScope().recordInitializationStates(thenFlowInfo);
-                       if (!thenFlowInfo.complainIfUnreachable(thenStatement, currentScope)) {
+                       if (!thenFlowInfo.complainIfUnreachable(thenStatement, currentScope, false)) {
                                thenFlowInfo =
                                        thenStatement.analyseCode(currentScope, flowContext, thenFlowInfo);
                        }
                };
                // optimizing the jump around the ELSE part
-               thenExit = (thenFlowInfo == FlowInfo.DeadEnd) || thenFlowInfo.isFakeReachable();
+               this.thenExit = !thenFlowInfo.isReachable();
 
                // process the ELSE part
-               if (elseStatement == null) {
-                       elseFlowInfo = flowInfo.initsWhenFalse();
-               } else {
-                       Constant cst;
-                       elseFlowInfo =
-                               ((((cst = condition.constant) != NotAConstant) && (cst.booleanValue() == true))
-                                       || (((cst = condition.conditionalConstant()) != NotAConstant)
-                                               && (cst.booleanValue() == true)))
-                                       ? (flowInfo.initsWhenFalse().copy().markAsFakeReachable(true))
-                                       : flowInfo.initsWhenFalse().copy();
+               FlowInfo elseFlowInfo = flowInfo.initsWhenFalse().copy();
+               if (isConditionOptimizedTrue) {
+                       elseFlowInfo.setReachMode(FlowInfo.UNREACHABLE); 
+               }
+               if (this.elseStatement != null) {
                        // Save info for code gen
                        elseInitStateIndex =
                                currentScope.methodScope().recordInitializationStates(elseFlowInfo);
-                       if (!elseFlowInfo.complainIfUnreachable(elseStatement, currentScope)) {
+                       if (!elseFlowInfo.complainIfUnreachable(elseStatement, currentScope, false)) {
                                elseFlowInfo =
                                        elseStatement.analyseCode(currentScope, flowContext, elseFlowInfo);
                        }
                }
 
+               boolean elseExit = !elseFlowInfo.isReachable();
+               
                // merge THEN & ELSE initializations
                FlowInfo mergedInfo;
-               if ((condition.constant != NotAConstant)
-                       && (condition.constant.booleanValue() == true)) {
-                       // IF (TRUE)
-                       if (thenExit) {
-                               mergedInfo = elseFlowInfo.markAsFakeReachable(true);
-                               mergedInitStateIndex =
-                                       currentScope.methodScope().recordInitializationStates(mergedInfo);
-                               return mergedInfo;
+//             if (isConditionOptimizedTrue){
+//                     if (!this.thenExit) {
+//                             mergedInfo = thenFlowInfo;
+//                     } else {
+//                             mergedInfo = elseFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
+//                     }
+//
+//             } else if (isConditionOptimizedFalse) {
+//                     if (!elseExit) {
+//                             mergedInfo = elseFlowInfo;
+//                     } else {
+//                             mergedInfo = thenFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
+//                     }
+//
+//             } else {
+//                     mergedInfo = thenFlowInfo.mergedWith(elseFlowInfo.unconditionalInits());
+//             }
+               if (isConditionOptimizedTrue){
+                       if (!this.thenExit) {
+                               mergedInfo = thenFlowInfo.addPotentialInitializationsFrom(elseFlowInfo);
                        } else {
-                               mergedInitStateIndex =
-                                       currentScope.methodScope().recordInitializationStates(thenFlowInfo);
-                               return thenFlowInfo;
+                               mergedInfo = elseFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
                        }
-               } else {
-                       // IF (FALSE)
-                       if ((condition.constant != NotAConstant)
-                               && (condition.constant.booleanValue() == false)) {
-                               if (elseFlowInfo.isDeadEnd()) {
-                                       mergedInfo = thenFlowInfo.markAsFakeReachable(true);
-                                       mergedInitStateIndex =
-                                               currentScope.methodScope().recordInitializationStates(mergedInfo);
-                                       return mergedInfo;
-                               } else {
-                                       mergedInitStateIndex =
-                                               currentScope.methodScope().recordInitializationStates(elseFlowInfo);
-                                       return elseFlowInfo;
-                               }
+
+               } else if (isConditionOptimizedFalse) {
+                       if (!elseExit) {
+                               mergedInfo = elseFlowInfo.addPotentialInitializationsFrom(thenFlowInfo);
+                       } else {
+                               mergedInfo = thenFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
                        }
+
+               } else {
+                       mergedInfo = thenFlowInfo.mergedWith(elseFlowInfo.unconditionalInits());
                }
-               mergedInfo = thenFlowInfo.mergedWith(elseFlowInfo.unconditionalInits());
+
                mergedInitStateIndex =
                        currentScope.methodScope().recordInitializationStates(mergedInfo);
                return mergedInfo;
@@ -151,96 +155,104 @@ public class IfStatement extends Statement {
        /**
         * If code generation
         *
-        * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
-        * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+        * @param currentScope net.sourceforge.phpdt.internal.compiler.lookup.BlockScope
+        * @param codeStream net.sourceforge.phpdt.internal.compiler.codegen.CodeStream
         */
-       public void generateCode(BlockScope currentScope, CodeStream codeStream) {
+//     public void generateCode(BlockScope currentScope, CodeStream codeStream) {
+//
+//             if ((this.bits & IsReachableMASK) == 0) {
+//                     return;
+//             }
+//             int pc = codeStream.position;
+//             Label endifLabel = new Label(codeStream);
+//
+//             // optimizing the then/else part code gen
+//             Constant cst;
+//             boolean hasThenPart = 
+//                     !(((cst = this.condition.optimizedBooleanConstant()) != NotAConstant
+//                                     && cst.booleanValue() == false)
+//                             || this.thenStatement == null
+//                             || this.thenStatement.isEmptyBlock());
+//             boolean hasElsePart =
+//                     !((cst != NotAConstant && cst.booleanValue() == true)
+//                             || this.elseStatement == null
+//                             || this.elseStatement.isEmptyBlock());
+//
+//             if (hasThenPart) {
+//                     Label falseLabel;
+//                     // generate boolean condition
+//                     this.condition.generateOptimizedBoolean(
+//                             currentScope,
+//                             codeStream,
+//                             null,
+//                             (falseLabel = new Label(codeStream)),
+//                             true);
+//                     // May loose some local variable initializations : affecting the local variable attributes
+//                     if (thenInitStateIndex != -1) {
+//                             codeStream.removeNotDefinitelyAssignedVariables(
+//                                     currentScope,
+//                                     thenInitStateIndex);
+//                             codeStream.addDefinitelyAssignedVariables(currentScope, thenInitStateIndex);
+//                     }
+//                     // generate then statement
+//                     this.thenStatement.generateCode(currentScope, codeStream);
+//                     // jump around the else statement
+//                     if (hasElsePart && !thenExit) {
+//                             this.thenStatement.branchChainTo(endifLabel);
+//                             int position = codeStream.position;
+//                             codeStream.goto_(endifLabel);
+//                             codeStream.updateLastRecordedEndPC(position);
+//                             //goto is tagged as part of the thenAction block
+//                     }
+//                     falseLabel.place();
+//             } else {
+//                     if (hasElsePart) {
+//                             // generate boolean condition
+//                             this.condition.generateOptimizedBoolean(
+//                                     currentScope,
+//                                     codeStream,
+//                                     endifLabel,
+//                                     null,
+//                                     true);
+//                     } else {
+//                             // generate condition side-effects
+//                             this.condition.generateCode(currentScope, codeStream, false);
+//                             codeStream.recordPositionsFrom(pc, this.sourceStart);
+//                     }
+//             }
+//             // generate else statement
+//             if (hasElsePart) {
+//                     // May loose some local variable initializations : affecting the local variable attributes
+//                     if (elseInitStateIndex != -1) {
+//                             codeStream.removeNotDefinitelyAssignedVariables(
+//                                     currentScope,
+//                                     elseInitStateIndex);
+//                             codeStream.addDefinitelyAssignedVariables(currentScope, elseInitStateIndex);
+//                     }
+//                     this.elseStatement.generateCode(currentScope, codeStream);
+//             }
+//             endifLabel.place();
+//             // May loose some local variable initializations : affecting the local variable attributes
+//             if (mergedInitStateIndex != -1) {
+//                     codeStream.removeNotDefinitelyAssignedVariables(
+//                             currentScope,
+//                             mergedInitStateIndex);
+//             }
+//             codeStream.recordPositionsFrom(pc, this.sourceStart);
+//     }
+       public StringBuffer printStatement(int indent, StringBuffer output) {
 
-               if ((bits & IsReachableMASK) == 0) {
-                       return;
+               printIndent(indent, output).append("if ("); //$NON-NLS-1$
+               condition.printExpression(0, output).append(")\n");     //$NON-NLS-1$ 
+               thenStatement.printStatement(indent + 2, output);
+               if (elseStatement != null) {
+                       output.append('\n');
+                       printIndent(indent, output);
+                       output.append("else\n"); //$NON-NLS-1$
+                       elseStatement.printStatement(indent + 2, output);
                }
-               int pc = codeStream.position;
-               Label endifLabel = new Label(codeStream);
-
-               // optimizing the then/else part code gen
-               Constant cst, condCst;
-               boolean hasThenPart =
-                       !((((cst = condition.constant) != NotAConstant)
-                               && (cst.booleanValue() == false))
-                               || (thenStatement == null)
-                               || (thenStatement.isEmptyBlock())
-                               || (((condCst = condition.conditionalConstant()) != NotAConstant)
-                                       && (condCst.booleanValue() == false)));
-               boolean hasElsePart =
-                       !(((cst != NotAConstant) && (cst.booleanValue() == true))
-                               || (elseStatement == null)
-                               || (elseStatement.isEmptyBlock())
-                               || (((condCst = condition.conditionalConstant()) != NotAConstant)
-                                       && (condCst.booleanValue() == true)));
-
-               if (hasThenPart) {
-                       Label falseLabel;
-                       // generate boolean condition
-                       condition.generateOptimizedBoolean(
-                               currentScope,
-                               codeStream,
-                               null,
-                               (falseLabel = new Label(codeStream)),
-                               true);
-                       // May loose some local variable initializations : affecting the local variable attributes
-                       if (thenInitStateIndex != -1) {
-                               codeStream.removeNotDefinitelyAssignedVariables(
-                                       currentScope,
-                                       thenInitStateIndex);
-                               codeStream.addDefinitelyAssignedVariables(currentScope, thenInitStateIndex);
-                       }
-                       // generate then statement
-                       thenStatement.generateCode(currentScope, codeStream);
-                       // jump around the else statement
-                       if (hasElsePart && !thenExit) {
-                               thenStatement.branchChainTo(endifLabel);
-                               int position = codeStream.position;
-                               codeStream.goto_(endifLabel);
-                               codeStream.updateLastRecordedEndPC(position);
-                               //goto is tagged as part of the thenAction block
-                       }
-                       falseLabel.place();
-               } else {
-                       if (hasElsePart) {
-                               // generate boolean condition
-                               condition.generateOptimizedBoolean(
-                                       currentScope,
-                                       codeStream,
-                                       endifLabel,
-                                       null,
-                                       true);
-                       } else {
-                               // generate condition side-effects
-                               condition.generateCode(currentScope, codeStream, false);
-                               codeStream.recordPositionsFrom(pc, this.sourceStart);
-                       }
-               }
-               // generate else statement
-               if (hasElsePart) {
-                       // May loose some local variable initializations : affecting the local variable attributes
-                       if (elseInitStateIndex != -1) {
-                               codeStream.removeNotDefinitelyAssignedVariables(
-                                       currentScope,
-                                       elseInitStateIndex);
-                               codeStream.addDefinitelyAssignedVariables(currentScope, elseInitStateIndex);
-                       }
-                       elseStatement.generateCode(currentScope, codeStream);
-               }
-               endifLabel.place();
-               // May loose some local variable initializations : affecting the local variable attributes
-               if (mergedInitStateIndex != -1) {
-                       codeStream.removeNotDefinitelyAssignedVariables(
-                               currentScope,
-                               mergedInitStateIndex);
-               }
-               codeStream.recordPositionsFrom(pc, this.sourceStart);
+               return output;
        }
-
        public void resolve(BlockScope scope) {
 
                TypeBinding type = condition.resolveTypeExpecting(scope, BooleanBinding);
@@ -263,7 +275,7 @@ public class IfStatement extends Statement {
        }
 
        public void traverse(
-               IAbstractSyntaxTreeVisitor visitor,
+           ASTVisitor visitor,
                BlockScope blockScope) {
 
                if (visitor.visit(this, blockScope)) {
@@ -275,4 +287,4 @@ public class IfStatement extends Statement {
                }
                visitor.endVisit(this, blockScope);
        }
-}
\ No newline at end of file
+}