d76577b9341d81e5d94bcecc31c68cc685d56da8
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpeclipse / internal / compiler / ast / IfStatement.java
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
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpeclipse.internal.compiler.ast;
12
13 import net.sourceforge.phpdt.internal.compiler.ASTVisitor;
14 import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
15 import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
16 import net.sourceforge.phpdt.internal.compiler.impl.Constant;
17 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
18 import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
19
20 public class IfStatement extends Statement {
21         
22         //this class represents the case of only one statement in 
23         //either else and/or then branches.
24
25         public Expression condition;
26         public Statement thenStatement;
27         public Statement elseStatement;
28         public Expression[] elseifConditions;
29         public Statement[] elseifStatements;
30         public boolean checkUnreachable;
31         boolean thenExit;
32         
33
34         // for local variables table attributes
35         int thenInitStateIndex = -1;
36         int elseInitStateIndex = -1;
37         int mergedInitStateIndex = -1;
38
39         public IfStatement(
40                 Expression condition,
41                 Statement thenStatement,
42                 int s,
43                 int e) {
44
45                 this.condition = condition;
46                 this.thenStatement = thenStatement;
47                 sourceStart = s;
48                 sourceEnd = e;
49                 checkUnreachable = true;
50         }
51
52         public IfStatement(
53                 Expression condition,
54                 Statement thenStatement,
55                 Statement elseStatement,
56                 int s,
57                 int e) {
58
59                 this.condition = condition;
60                 this.thenStatement = thenStatement;
61                 this.elseStatement = elseStatement;
62                 sourceEnd = e;
63                 sourceStart = s;
64                 checkUnreachable = true;
65         }
66
67         public FlowInfo analyseCode(
68                 BlockScope currentScope,
69                 FlowContext flowContext,
70                 FlowInfo flowInfo) {
71
72                 // process the condition
73                 flowInfo = condition.analyseCode(currentScope, flowContext, flowInfo);
74
75                 Constant cst = this.condition.optimizedBooleanConstant();
76                 boolean isConditionOptimizedTrue = cst != NotAConstant && cst.booleanValue() == true;
77                 boolean isConditionOptimizedFalse = cst != NotAConstant && cst.booleanValue() == false;
78                 
79                 // process the THEN part
80                 FlowInfo thenFlowInfo = flowInfo.initsWhenTrue().copy();
81                 if (isConditionOptimizedFalse) {
82                         thenFlowInfo.setReachMode(FlowInfo.UNREACHABLE); 
83                 }
84                 if (this.thenStatement != null) {
85                         // Save info for code gen
86                         thenInitStateIndex =
87                                 currentScope.methodScope().recordInitializationStates(thenFlowInfo);
88                         if (!thenFlowInfo.complainIfUnreachable(thenStatement, currentScope, false)) {
89                                 thenFlowInfo =
90                                         thenStatement.analyseCode(currentScope, flowContext, thenFlowInfo);
91                         }
92                 };
93                 // optimizing the jump around the ELSE part
94                 this.thenExit = !thenFlowInfo.isReachable();
95
96                 // process the ELSE part
97                 FlowInfo elseFlowInfo = flowInfo.initsWhenFalse().copy();
98                 if (isConditionOptimizedTrue) {
99                         elseFlowInfo.setReachMode(FlowInfo.UNREACHABLE); 
100                 }
101                 if (this.elseStatement != null) {
102                         // Save info for code gen
103                         elseInitStateIndex =
104                                 currentScope.methodScope().recordInitializationStates(elseFlowInfo);
105                         if (!elseFlowInfo.complainIfUnreachable(elseStatement, currentScope, false)) {
106                                 elseFlowInfo =
107                                         elseStatement.analyseCode(currentScope, flowContext, elseFlowInfo);
108                         }
109                 }
110
111                 boolean elseExit = !elseFlowInfo.isReachable();
112                 
113                 // merge THEN & ELSE initializations
114                 FlowInfo mergedInfo;
115 //              if (isConditionOptimizedTrue){
116 //                      if (!this.thenExit) {
117 //                              mergedInfo = thenFlowInfo;
118 //                      } else {
119 //                              mergedInfo = elseFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
120 //                      }
121 //
122 //              } else if (isConditionOptimizedFalse) {
123 //                      if (!elseExit) {
124 //                              mergedInfo = elseFlowInfo;
125 //                      } else {
126 //                              mergedInfo = thenFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
127 //                      }
128 //
129 //              } else {
130 //                      mergedInfo = thenFlowInfo.mergedWith(elseFlowInfo.unconditionalInits());
131 //              }
132                 if (isConditionOptimizedTrue){
133                         if (!this.thenExit) {
134                                 mergedInfo = thenFlowInfo.addPotentialInitializationsFrom(elseFlowInfo);
135                         } else {
136                                 mergedInfo = elseFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
137                         }
138
139                 } else if (isConditionOptimizedFalse) {
140                         if (!elseExit) {
141                                 mergedInfo = elseFlowInfo.addPotentialInitializationsFrom(thenFlowInfo);
142                         } else {
143                                 mergedInfo = thenFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
144                         }
145
146                 } else {
147                         mergedInfo = thenFlowInfo.mergedWith(elseFlowInfo.unconditionalInits());
148                 }
149
150                 mergedInitStateIndex =
151                         currentScope.methodScope().recordInitializationStates(mergedInfo);
152                 return mergedInfo;
153         }
154
155         /**
156          * If code generation
157          *
158          * @param currentScope net.sourceforge.phpdt.internal.compiler.lookup.BlockScope
159          * @param codeStream net.sourceforge.phpdt.internal.compiler.codegen.CodeStream
160          */
161 //      public void generateCode(BlockScope currentScope, CodeStream codeStream) {
162 //
163 //              if ((this.bits & IsReachableMASK) == 0) {
164 //                      return;
165 //              }
166 //              int pc = codeStream.position;
167 //              Label endifLabel = new Label(codeStream);
168 //
169 //              // optimizing the then/else part code gen
170 //              Constant cst;
171 //              boolean hasThenPart = 
172 //                      !(((cst = this.condition.optimizedBooleanConstant()) != NotAConstant
173 //                                      && cst.booleanValue() == false)
174 //                              || this.thenStatement == null
175 //                              || this.thenStatement.isEmptyBlock());
176 //              boolean hasElsePart =
177 //                      !((cst != NotAConstant && cst.booleanValue() == true)
178 //                              || this.elseStatement == null
179 //                              || this.elseStatement.isEmptyBlock());
180 //
181 //              if (hasThenPart) {
182 //                      Label falseLabel;
183 //                      // generate boolean condition
184 //                      this.condition.generateOptimizedBoolean(
185 //                              currentScope,
186 //                              codeStream,
187 //                              null,
188 //                              (falseLabel = new Label(codeStream)),
189 //                              true);
190 //                      // May loose some local variable initializations : affecting the local variable attributes
191 //                      if (thenInitStateIndex != -1) {
192 //                              codeStream.removeNotDefinitelyAssignedVariables(
193 //                                      currentScope,
194 //                                      thenInitStateIndex);
195 //                              codeStream.addDefinitelyAssignedVariables(currentScope, thenInitStateIndex);
196 //                      }
197 //                      // generate then statement
198 //                      this.thenStatement.generateCode(currentScope, codeStream);
199 //                      // jump around the else statement
200 //                      if (hasElsePart && !thenExit) {
201 //                              this.thenStatement.branchChainTo(endifLabel);
202 //                              int position = codeStream.position;
203 //                              codeStream.goto_(endifLabel);
204 //                              codeStream.updateLastRecordedEndPC(position);
205 //                              //goto is tagged as part of the thenAction block
206 //                      }
207 //                      falseLabel.place();
208 //              } else {
209 //                      if (hasElsePart) {
210 //                              // generate boolean condition
211 //                              this.condition.generateOptimizedBoolean(
212 //                                      currentScope,
213 //                                      codeStream,
214 //                                      endifLabel,
215 //                                      null,
216 //                                      true);
217 //                      } else {
218 //                              // generate condition side-effects
219 //                              this.condition.generateCode(currentScope, codeStream, false);
220 //                              codeStream.recordPositionsFrom(pc, this.sourceStart);
221 //                      }
222 //              }
223 //              // generate else statement
224 //              if (hasElsePart) {
225 //                      // May loose some local variable initializations : affecting the local variable attributes
226 //                      if (elseInitStateIndex != -1) {
227 //                              codeStream.removeNotDefinitelyAssignedVariables(
228 //                                      currentScope,
229 //                                      elseInitStateIndex);
230 //                              codeStream.addDefinitelyAssignedVariables(currentScope, elseInitStateIndex);
231 //                      }
232 //                      this.elseStatement.generateCode(currentScope, codeStream);
233 //              }
234 //              endifLabel.place();
235 //              // May loose some local variable initializations : affecting the local variable attributes
236 //              if (mergedInitStateIndex != -1) {
237 //                      codeStream.removeNotDefinitelyAssignedVariables(
238 //                              currentScope,
239 //                              mergedInitStateIndex);
240 //              }
241 //              codeStream.recordPositionsFrom(pc, this.sourceStart);
242 //      }
243         public StringBuffer printStatement(int indent, StringBuffer output) {
244
245                 printIndent(indent, output).append("if ("); //$NON-NLS-1$
246                 condition.printExpression(0, output).append(")\n");     //$NON-NLS-1$ 
247                 thenStatement.printStatement(indent + 2, output);
248                 if (elseStatement != null) {
249                         output.append('\n');
250                         printIndent(indent, output);
251                         output.append("else\n"); //$NON-NLS-1$
252                         elseStatement.printStatement(indent + 2, output);
253                 }
254                 return output;
255         }
256         public void resolve(BlockScope scope) {
257
258                 TypeBinding type = condition.resolveTypeExpecting(scope, BooleanBinding);
259                 condition.implicitWidening(type, type);
260                 if (thenStatement != null)
261                         thenStatement.resolve(scope);
262                 if (elseStatement != null)
263                         elseStatement.resolve(scope);
264         }
265
266         public String toString(int tab) {
267
268                 String inFront, s = tabString(tab);
269                 inFront = s;
270                 s = s + "if (" + condition.toStringExpression() + ") \n";       //$NON-NLS-1$ //$NON-NLS-2$
271                 s = s + thenStatement.toString(tab + 2) + ";"; //$NON-NLS-1$
272                 if (elseStatement != null)
273                         s = s + "\n" + inFront + "else\n" + elseStatement.toString(tab + 2) + ";"; //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-3$
274                 return s;
275         }
276
277         public void traverse(
278             ASTVisitor visitor,
279                 BlockScope blockScope) {
280
281                 if (visitor.visit(this, blockScope)) {
282                         condition.traverse(visitor, blockScope);
283                         if (thenStatement != null)
284                                 thenStatement.traverse(visitor, blockScope);
285                         if (elseStatement != null)
286                                 elseStatement.traverse(visitor, blockScope);
287                 }
288                 visitor.endVisit(this, blockScope);
289         }
290 }