new version with WorkingCopy Management
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpeclipse / internal / compiler / ast / OR_OR_Expression.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.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.impl.Constant;
18 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
19
20 //dedicated treatment for the ||
21 public class OR_OR_Expression extends BinaryExpression {
22
23         int rightInitStateIndex = -1;
24         int mergedInitStateIndex = -1;
25
26         public OR_OR_Expression(Expression left, Expression right, int operator) {
27                 super(left, right, operator);
28         }
29
30         public FlowInfo analyseCode(
31                 BlockScope currentScope,
32                 FlowContext flowContext,
33                 FlowInfo flowInfo) {
34
35                 Constant cst = this.left.optimizedBooleanConstant();
36                 boolean isLeftOptimizedTrue = cst != NotAConstant && cst.booleanValue() == true;
37                 boolean isLeftOptimizedFalse = cst != NotAConstant && cst.booleanValue() == false;
38
39                 if (isLeftOptimizedFalse) {
40                         // FALSE || anything
41                          // need to be careful of scenario:
42                         //              (x || y) || !z, if passing the left info to the right, it would be swapped by the !
43                         FlowInfo mergedInfo = left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
44                         mergedInfo = right.analyseCode(currentScope, flowContext, mergedInfo);
45                         mergedInitStateIndex =
46                                 currentScope.methodScope().recordInitializationStates(mergedInfo);
47                         return mergedInfo;
48                 }
49
50                 FlowInfo leftInfo = left.analyseCode(currentScope, flowContext, flowInfo);
51         
52                  // need to be careful of scenario:
53                 //              (x || y) || !z, if passing the left info to the right, it would be swapped by the !
54                 FlowInfo rightInfo = leftInfo.initsWhenFalse().unconditionalInits().copy();
55                 rightInitStateIndex =
56                         currentScope.methodScope().recordInitializationStates(rightInfo);
57
58                 int previousMode = rightInfo.reachMode();
59                 if (isLeftOptimizedTrue){
60                         rightInfo.setReachMode(FlowInfo.UNREACHABLE); 
61                 }
62                 rightInfo = right.analyseCode(currentScope, flowContext, rightInfo);
63                 FlowInfo falseMergedInfo = rightInfo.initsWhenFalse().copy();
64                 rightInfo.setReachMode(previousMode); // reset after falseMergedInfo got extracted
65
66                 FlowInfo mergedInfo = FlowInfo.conditional(
67                                         // merging two true initInfos for such a negative case: if ((t && (b = t)) || f) r = b; // b may not have been initialized
68                                         leftInfo.initsWhenTrue().copy().unconditionalInits().mergedWith(
69                                                 rightInfo.initsWhenTrue().copy().unconditionalInits()),
70                                         falseMergedInfo);
71                 mergedInitStateIndex =
72                         currentScope.methodScope().recordInitializationStates(mergedInfo);
73                 return mergedInfo;
74         }
75
76         /**
77          * Code generation for a binary operation
78          *
79          * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
80          * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
81          * @param valueRequired boolean
82          */
83 //      public void generateCode(
84 //              BlockScope currentScope,
85 //              CodeStream codeStream,
86 //              boolean valueRequired) {
87 //              int pc = codeStream.position;
88 //              Label falseLabel, endLabel;
89 //              if (constant != Constant.NotAConstant) {
90 //                      if (valueRequired)
91 //                              codeStream.generateConstant(constant, implicitConversion);
92 //                      codeStream.recordPositionsFrom(pc, this.sourceStart);
93 //                      return;
94 //              }
95 //              bits |= OnlyValueRequiredMASK;
96 //              generateOptimizedBoolean(
97 //                      currentScope,
98 //                      codeStream,
99 //                      null,
100 //                      (falseLabel = new Label(codeStream)),
101 //                      valueRequired);
102 //              /*  improving code gen for such a case:         boolean b = i < 0 || true; 
103 //               * since the label has never been used, we have the inlined value on the stack. */
104 //              if (falseLabel.hasForwardReferences()) {
105 //                      if (valueRequired) {
106 //                              codeStream.iconst_1();
107 //                              if ((bits & ValueForReturnMASK) != 0) {
108 //                                      codeStream.ireturn();
109 //                                      falseLabel.place();
110 //                                      codeStream.iconst_0();
111 //                              } else {
112 //                                      codeStream.goto_(endLabel = new Label(codeStream));
113 //                                      codeStream.decrStackSize(1);
114 //                                      falseLabel.place();
115 //                                      codeStream.iconst_0();
116 //                                      endLabel.place();
117 //                              }
118 //                      } else {
119 //                              falseLabel.place();
120 //                      }
121 //              }
122 //              if (valueRequired) {
123 //                      codeStream.generateImplicitConversion(implicitConversion);
124 //              }
125 //              codeStream.recordPositionsFrom(pc, this.sourceStart);
126 //      }
127 //
128 //      /**
129 //       * Boolean operator code generation
130 //       *      Optimized operations are: ||
131 //       */
132 //      public void generateOptimizedBoolean(
133 //              BlockScope currentScope,
134 //              CodeStream codeStream,
135 //              Label trueLabel,
136 //              Label falseLabel,
137 //              boolean valueRequired) {
138 //              if (constant != Constant.NotAConstant) {
139 //                      super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
140 //                      return;
141 //              }
142 //              Constant condConst;
143 //              if ((condConst = left.optimizedBooleanConstant()) != NotAConstant) {
144 //                      if (condConst.booleanValue() == true) {
145 //                              // <something equivalent to true> || x
146 //                              left.generateOptimizedBoolean(
147 //                                      currentScope,
148 //                                      codeStream,
149 //                                      trueLabel,
150 //                                      falseLabel,
151 //                                      false);
152 //                              if (valueRequired) {
153 //                                      if ((bits & OnlyValueRequiredMASK) != 0) {
154 //                                              codeStream.iconst_1();
155 //                                      } else {
156 //                                              if (trueLabel != null) {
157 //                                                      codeStream.goto_(trueLabel);
158 //                                              }
159 //                                      }
160 //                              }
161 //                              // reposition the endPC
162 //                              codeStream.updateLastRecordedEndPC(codeStream.position);                                        
163 //                      } else {
164 //                              // <something equivalent to false> || x
165 //                              left.generateOptimizedBoolean(
166 //                                      currentScope,
167 //                                      codeStream,
168 //                                      trueLabel,
169 //                                      falseLabel,
170 //                                      false);
171 //                              if (rightInitStateIndex != -1) {
172 //                                      codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
173 //                              }
174 //                              if ((bits & OnlyValueRequiredMASK) != 0) {
175 //                                      right.generateCode(currentScope, codeStream, valueRequired);
176 //                              } else {
177 //                                      right.generateOptimizedBoolean(
178 //                                              currentScope,
179 //                                              codeStream,
180 //                                              trueLabel,
181 //                                              falseLabel,
182 //                                              valueRequired);
183 //                              }
184 //                      }
185 //                      if (mergedInitStateIndex != -1) {
186 //                              codeStream.removeNotDefinitelyAssignedVariables(
187 //                                      currentScope,
188 //                                      mergedInitStateIndex);
189 //                      }
190 //                      return;
191 //              }
192 //              if ((condConst = right.optimizedBooleanConstant()) != NotAConstant) {
193 //                      if (condConst.booleanValue() == true) {
194 //                              // x || <something equivalent to true>
195 //                              Label internalFalseLabel = new Label(codeStream);
196 //                              left.generateOptimizedBoolean(
197 //                                      currentScope,
198 //                                      codeStream,
199 //                                      null,
200 //                                      internalFalseLabel, // will be true in the end
201 //                                      false);
202 //                              if (rightInitStateIndex != -1) {
203 //                                      codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
204 //                              }
205 //                              internalFalseLabel.place();
206 //                              right.generateOptimizedBoolean(
207 //                                      currentScope,
208 //                                      codeStream,
209 //                                      trueLabel,
210 //                                      falseLabel,
211 //                                      false);
212 //                              if (valueRequired) {
213 //                                      if ((bits & OnlyValueRequiredMASK) != 0) {
214 //                                              codeStream.iconst_1();
215 //                                      } else {
216 //                                              if (trueLabel != null) {
217 //                                                      codeStream.goto_(trueLabel);
218 //                                              }
219 //                                      }
220 //                              }
221 //                              // reposition the endPC
222 //                              codeStream.updateLastRecordedEndPC(codeStream.position);                                        
223 //                      } else {
224 //                              // x || <something equivalent to false>
225 //                              if ((bits & OnlyValueRequiredMASK) != 0) {
226 //                                      left.generateCode(currentScope, codeStream, valueRequired);
227 //                              } else {
228 //                                      left.generateOptimizedBoolean(
229 //                                              currentScope,
230 //                                              codeStream,
231 //                                              trueLabel,
232 //                                              falseLabel,
233 //                                              valueRequired);
234 //                              }
235 //                              if (rightInitStateIndex != -1) {
236 //                                      codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
237 //                              }
238 //                              right.generateOptimizedBoolean(
239 //                                      currentScope,
240 //                                      codeStream,
241 //                                      trueLabel,
242 //                                      falseLabel,
243 //                                      false);
244 //                      }
245 //                      if (mergedInitStateIndex != -1) {
246 //                              codeStream.removeNotDefinitelyAssignedVariables(
247 //                                      currentScope,
248 //                                      mergedInitStateIndex);
249 //                      }
250 //                      return;
251 //              }
252 //              // default case
253 //              if (falseLabel == null) {
254 //                      if (trueLabel != null) {
255 //                              // implicit falling through the FALSE case
256 //                              left.generateOptimizedBoolean(currentScope, codeStream, trueLabel, null, true);
257 //                              right.generateOptimizedBoolean(
258 //                                      currentScope,
259 //                                      codeStream,
260 //                                      trueLabel,
261 //                                      null,
262 //                                      valueRequired);
263 //                      }
264 //              } else {
265 //                      // implicit falling through the TRUE case
266 //                      if (trueLabel == null) {
267 //                              Label internalTrueLabel = new Label(codeStream);
268 //                              left.generateOptimizedBoolean(
269 //                                      currentScope,
270 //                                      codeStream,
271 //                                      internalTrueLabel,
272 //                                      null,
273 //                                      true);
274 //                              if (rightInitStateIndex != -1) {
275 //                                      codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
276 //                              }
277 //                              right.generateOptimizedBoolean(
278 //                                      currentScope,
279 //                                      codeStream,
280 //                                      null,
281 //                                      falseLabel,
282 //                                      valueRequired);
283 //                              internalTrueLabel.place();
284 //                      } else {
285 //                              // no implicit fall through TRUE/FALSE --> should never occur
286 //                      }
287 //              }
288 //              if (mergedInitStateIndex != -1) {
289 //                      codeStream.removeNotDefinitelyAssignedVariables(
290 //                              currentScope,
291 //                              mergedInitStateIndex);
292 //              }
293 //      }
294
295         public boolean isCompactableOperation() {
296                 return false;
297         }
298
299         public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
300                 if (visitor.visit(this, scope)) {
301                         left.traverse(visitor, scope);
302                         right.traverse(visitor, scope);
303                 }
304                 visitor.endVisit(this, scope);
305         }
306 }