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