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