be9ecd986ae0d4934d83a6a98d8914afeee917d1
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpeclipse / internal / compiler / ast / AND_AND_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 AND_AND_Expression extends BinaryExpression {
22
23         int rightInitStateIndex = -1;
24         int mergedInitStateIndex = -1;
25
26         public AND_AND_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 (isLeftOptimizedTrue) {
40                         // TRUE && 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                  // 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.initsWhenTrue().unconditionalInits().copy();
54                 rightInitStateIndex =
55                         currentScope.methodScope().recordInitializationStates(rightInfo);
56
57                 int previousMode = rightInfo.reachMode();
58                 if (isLeftOptimizedFalse){
59                         rightInfo.setReachMode(FlowInfo.UNREACHABLE); 
60                 }
61                 rightInfo = right.analyseCode(currentScope, flowContext, rightInfo);
62                 FlowInfo trueMergedInfo = rightInfo.initsWhenTrue().copy();
63                 rightInfo.setReachMode(previousMode); // reset after trueMergedInfo got extracted
64                 
65                 FlowInfo mergedInfo = 
66                         FlowInfo.conditional(
67                                 trueMergedInfo,
68                                 leftInfo.initsWhenFalse().copy().unconditionalInits().mergedWith(
69                                                 rightInfo.initsWhenFalse().copy().unconditionalInits()));
70                 mergedInitStateIndex =
71                         currentScope.methodScope().recordInitializationStates(mergedInfo);
72                 return mergedInfo;
73         }
74
75         /**
76          * Code generation for a binary operation
77          */
78 //      public void generateCode(
79 //              BlockScope currentScope,
80 //              CodeStream codeStream,
81 //              boolean valueRequired) {
82 //                      
83 //              int pc = codeStream.position;
84 //              Label falseLabel, endLabel;
85 //              if (constant != Constant.NotAConstant) {
86 //                      // inlined value
87 //                      if (valueRequired)
88 //                              codeStream.generateConstant(constant, implicitConversion);
89 //                      codeStream.recordPositionsFrom(pc, this.sourceStart);
90 //                      return;
91 //              }
92 //              bits |= OnlyValueRequiredMASK;
93 //              generateOptimizedBoolean(
94 //                      currentScope,
95 //                      codeStream,
96 //                      null,
97 //                      (falseLabel = new Label(codeStream)),
98 //                      valueRequired);
99 //              /* improving code gen for such a case: boolean b = i < 0 && false
100 //               * since the label has never been used, we have the inlined value on the stack. */
101 //              if (falseLabel.hasForwardReferences()) {
102 //                      if (valueRequired) {
103 //                              codeStream.iconst_1();
104 //                              if ((bits & ValueForReturnMASK) != 0) {
105 //                                      codeStream.ireturn();
106 //                                      falseLabel.place();
107 //                                      codeStream.iconst_0();
108 //                              } else {
109 //                                      codeStream.goto_(endLabel = new Label(codeStream));
110 //                                      codeStream.decrStackSize(1);
111 //                                      falseLabel.place();
112 //                                      codeStream.iconst_0();
113 //                                      endLabel.place();
114 //                              }
115 //                      } else {
116 //                              falseLabel.place();
117 //                      }
118 //              }
119 //              if (valueRequired) {
120 //                      codeStream.generateImplicitConversion(implicitConversion);
121 //              }
122 //              // reposition the endPC
123 //              codeStream.updateLastRecordedEndPC(codeStream.position);                
124 //      }
125
126         /**
127          * Boolean operator code generation
128          *      Optimized operations are: &&
129          */
130 //      public void generateOptimizedBoolean(
131 //              BlockScope currentScope,
132 //              CodeStream codeStream,
133 //              Label trueLabel,
134 //              Label falseLabel,
135 //              boolean valueRequired) {
136 //                      
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 (rightInitStateIndex != -1) {
152 //                                      codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
153 //                              }
154 //                              if ((bits & OnlyValueRequiredMASK) != 0) {
155 //                                      right.generateCode(currentScope, codeStream, valueRequired);
156 //                              } else {
157 //                                      right.generateOptimizedBoolean(
158 //                                              currentScope,
159 //                                              codeStream,
160 //                                              trueLabel,
161 //                                              falseLabel,
162 //                                              valueRequired);
163 //                              }
164 //                      } else {
165 //                              // <something equivalent to false> && x
166 //                              left.generateOptimizedBoolean(
167 //                                      currentScope,
168 //                                      codeStream,
169 //                                      trueLabel,
170 //                                      falseLabel,
171 //                                      false);
172 //                              if (valueRequired) {
173 //                                      if ((bits & OnlyValueRequiredMASK) != 0) {
174 //                                              codeStream.iconst_0();
175 //                                      } else {
176 //                                              if (falseLabel != null) {
177 //                                                      // implicit falling through the TRUE case
178 //                                                      codeStream.goto_(falseLabel);
179 //                                              }
180 //                                      }
181 //                              }
182 //                              // reposition the endPC
183 //                              codeStream.updateLastRecordedEndPC(codeStream.position);
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 //                              if ((bits & OnlyValueRequiredMASK) != 0) {
196 //                                      left.generateCode(currentScope, codeStream, valueRequired);
197 //                              } else {
198 //                                      left.generateOptimizedBoolean(
199 //                                              currentScope,
200 //                                              codeStream,
201 //                                              trueLabel,
202 //                                              falseLabel,
203 //                                              valueRequired);
204 //                              }
205 //                              if (rightInitStateIndex != -1) {
206 //                                      codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
207 //                              }
208 //                              right.generateOptimizedBoolean(
209 //                                      currentScope,
210 //                                      codeStream,
211 //                                      trueLabel,
212 //                                      falseLabel,
213 //                                      false);
214 //                      } else {
215 //                              // x && <something equivalent to false>
216 //                              Label internalTrueLabel = new Label(codeStream);
217 //                              left.generateOptimizedBoolean(
218 //                                      currentScope,
219 //                                      codeStream,
220 //                                      internalTrueLabel, // will be false in the end
221 //                                      null,
222 //                                      false);
223 //                              if (rightInitStateIndex != -1) {
224 //                                      codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
225 //                              }
226 //                              internalTrueLabel.place();
227 //                              right.generateOptimizedBoolean(
228 //                                      currentScope,
229 //                                      codeStream,
230 //                                      trueLabel,
231 //                                      falseLabel,
232 //                                      false);
233 //                              if (valueRequired) {
234 //                                      if ((bits & OnlyValueRequiredMASK) != 0) {
235 //                                              codeStream.iconst_0();
236 //                                      } else {
237 //                                              if (falseLabel != null) {
238 //                                                      // implicit falling through the TRUE case
239 //                                                      codeStream.goto_(falseLabel);
240 //                                              }
241 //                                      }
242 //                              }
243 //                              // reposition the endPC
244 //                              codeStream.updateLastRecordedEndPC(codeStream.position);
245 //                      }
246 //                      if (mergedInitStateIndex != -1) {
247 //                              codeStream.removeNotDefinitelyAssignedVariables(
248 //                                      currentScope,
249 //                                      mergedInitStateIndex);
250 //                      }
251 //                      return;
252 //              }
253 //              // default case
254 //              if (falseLabel == null) {
255 //                      if (trueLabel != null) {
256 //                              // implicit falling through the FALSE case
257 //                              Label internalFalseLabel = new Label(codeStream);
258 //                              left.generateOptimizedBoolean(
259 //                                      currentScope,
260 //                                      codeStream,
261 //                                      null,
262 //                                      internalFalseLabel,
263 //                                      true);
264 //                              if (rightInitStateIndex != -1) {
265 //                                      codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
266 //                              }
267 //                              right.generateOptimizedBoolean(
268 //                                      currentScope,
269 //                                      codeStream,
270 //                                      trueLabel,
271 //                                      null,
272 //                                      valueRequired);
273 //                              internalFalseLabel.place();
274 //                      }
275 //              } else {
276 //                      // implicit falling through the TRUE case
277 //                      if (trueLabel == null) {
278 //                              left.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel, true);
279 //                              if (rightInitStateIndex != -1) {
280 //                                      codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
281 //                              }
282 //                              right.generateOptimizedBoolean(
283 //                                      currentScope,
284 //                                      codeStream,
285 //                                      null,
286 //                                      falseLabel,
287 //                                      valueRequired);
288 //                      } else {
289 //                              // no implicit fall through TRUE/FALSE --> should never occur
290 //                      }
291 //              }
292 //              if (mergedInitStateIndex != -1) {
293 //                      codeStream.removeNotDefinitelyAssignedVariables(
294 //                              currentScope,
295 //                              mergedInitStateIndex);
296 //              }
297 //      }
298
299         public boolean isCompactableOperation() {
300                 return false;
301         }
302
303         public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
304                 if (visitor.visit(this, scope)) {
305                         left.traverse(visitor, scope);
306                         right.traverse(visitor, scope);
307                 }
308                 visitor.endVisit(this, scope);
309         }
310 }