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