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
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.ast;
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;
19 // dedicated treatment for the &&
20 public class AND_AND_Expression extends BinaryExpression {
22 int rightInitStateIndex = -1;
24 int mergedInitStateIndex = -1;
26 public AND_AND_Expression(Expression left, Expression right, int operator) {
27 super(left, right, operator);
30 public FlowInfo analyseCode(BlockScope currentScope,
31 FlowContext flowContext, FlowInfo flowInfo) {
33 Constant cst = this.left.optimizedBooleanConstant();
34 boolean isLeftOptimizedTrue = cst != NotAConstant
35 && cst.booleanValue() == true;
36 boolean isLeftOptimizedFalse = cst != NotAConstant
37 && cst.booleanValue() == false;
39 if (isLeftOptimizedTrue) {
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,
48 mergedInitStateIndex = currentScope.methodScope()
49 .recordInitializationStates(mergedInfo);
53 FlowInfo leftInfo = left.analyseCode(currentScope, flowContext,
55 // need to be careful of scenario:
56 // (x && y) && !z, if passing the left info to the right, it would be
58 FlowInfo rightInfo = leftInfo.initsWhenTrue().unconditionalInits()
60 rightInitStateIndex = currentScope.methodScope()
61 .recordInitializationStates(rightInfo);
63 int previousMode = rightInfo.reachMode();
64 if (isLeftOptimizedFalse) {
65 rightInfo.setReachMode(FlowInfo.UNREACHABLE);
67 rightInfo = right.analyseCode(currentScope, flowContext, rightInfo);
68 FlowInfo trueMergedInfo = rightInfo.initsWhenTrue().copy();
69 rightInfo.setReachMode(previousMode); // reset after trueMergedInfo
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);
83 * Code generation for a binary operation
85 // public void generateCode(
86 // BlockScope currentScope,
87 // CodeStream codeStream,
88 // boolean valueRequired) {
90 // int pc = codeStream.position;
91 // Label falseLabel, endLabel;
92 // if (constant != Constant.NotAConstant) {
95 // codeStream.generateConstant(constant, implicitConversion);
96 // codeStream.recordPositionsFrom(pc, this.sourceStart);
99 // bits |= OnlyValueRequiredMASK;
100 // generateOptimizedBoolean(
104 // (falseLabel = new Label(codeStream)),
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
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();
117 // codeStream.goto_(endLabel = new Label(codeStream));
118 // codeStream.decrStackSize(1);
119 // falseLabel.place();
120 // codeStream.iconst_0();
124 // falseLabel.place();
127 // if (valueRequired) {
128 // codeStream.generateImplicitConversion(implicitConversion);
130 // // reposition the endPC
131 // codeStream.updateLastRecordedEndPC(codeStream.position);
134 * Boolean operator code generation Optimized operations are: &&
136 // public void generateOptimizedBoolean(
137 // BlockScope currentScope,
138 // CodeStream codeStream,
141 // boolean valueRequired) {
143 // if (constant != Constant.NotAConstant) {
144 // super.generateOptimizedBoolean(currentScope, codeStream, trueLabel,
145 // falseLabel, valueRequired);
148 // Constant condConst;
149 // if ((condConst = left.optimizedBooleanConstant()) != NotAConstant) {
150 // if (condConst.booleanValue() == true) {
151 // // <something equivalent to true> && x
152 // left.generateOptimizedBoolean(
158 // if (rightInitStateIndex != -1) {
159 // codeStream.addDefinitelyAssignedVariables(currentScope,
160 // rightInitStateIndex);
162 // if ((bits & OnlyValueRequiredMASK) != 0) {
163 // right.generateCode(currentScope, codeStream, valueRequired);
165 // right.generateOptimizedBoolean(
173 // // <something equivalent to false> && x
174 // left.generateOptimizedBoolean(
180 // if (valueRequired) {
181 // if ((bits & OnlyValueRequiredMASK) != 0) {
182 // codeStream.iconst_0();
184 // if (falseLabel != null) {
185 // // implicit falling through the TRUE case
186 // codeStream.goto_(falseLabel);
190 // // reposition the endPC
191 // codeStream.updateLastRecordedEndPC(codeStream.position);
193 // if (mergedInitStateIndex != -1) {
194 // codeStream.removeNotDefinitelyAssignedVariables(
196 // mergedInitStateIndex);
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);
206 // left.generateOptimizedBoolean(
213 // if (rightInitStateIndex != -1) {
214 // codeStream.addDefinitelyAssignedVariables(currentScope,
215 // rightInitStateIndex);
217 // right.generateOptimizedBoolean(
224 // // x && <something equivalent to false>
225 // Label internalTrueLabel = new Label(codeStream);
226 // left.generateOptimizedBoolean(
229 // internalTrueLabel, // will be false in the end
232 // if (rightInitStateIndex != -1) {
233 // codeStream.addDefinitelyAssignedVariables(currentScope,
234 // rightInitStateIndex);
236 // internalTrueLabel.place();
237 // right.generateOptimizedBoolean(
243 // if (valueRequired) {
244 // if ((bits & OnlyValueRequiredMASK) != 0) {
245 // codeStream.iconst_0();
247 // if (falseLabel != null) {
248 // // implicit falling through the TRUE case
249 // codeStream.goto_(falseLabel);
253 // // reposition the endPC
254 // codeStream.updateLastRecordedEndPC(codeStream.position);
256 // if (mergedInitStateIndex != -1) {
257 // codeStream.removeNotDefinitelyAssignedVariables(
259 // mergedInitStateIndex);
264 // if (falseLabel == null) {
265 // if (trueLabel != null) {
266 // // implicit falling through the FALSE case
267 // Label internalFalseLabel = new Label(codeStream);
268 // left.generateOptimizedBoolean(
272 // internalFalseLabel,
274 // if (rightInitStateIndex != -1) {
275 // codeStream.addDefinitelyAssignedVariables(currentScope,
276 // rightInitStateIndex);
278 // right.generateOptimizedBoolean(
284 // internalFalseLabel.place();
287 // // implicit falling through the TRUE case
288 // if (trueLabel == null) {
289 // left.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel,
291 // if (rightInitStateIndex != -1) {
292 // codeStream.addDefinitelyAssignedVariables(currentScope,
293 // rightInitStateIndex);
295 // right.generateOptimizedBoolean(
302 // // no implicit fall through TRUE/FALSE --> should never occur
305 // if (mergedInitStateIndex != -1) {
306 // codeStream.removeNotDefinitelyAssignedVariables(
308 // mergedInitStateIndex);
311 public boolean isCompactableOperation() {
315 public void traverse(ASTVisitor visitor, BlockScope scope) {
316 if (visitor.visit(this, scope)) {
317 left.traverse(visitor, scope);
318 right.traverse(visitor, scope);
320 visitor.endVisit(this, scope);