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