1 /*******************************************************************************
2 * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v0.5
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v05.html
9 * IBM Corporation - initial API and implementation
10 ******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.ast;
13 import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
14 import net.sourceforge.phpdt.internal.compiler.impl.*;
15 import net.sourceforge.phpdt.internal.compiler.codegen.*;
16 import net.sourceforge.phpdt.internal.compiler.flow.*;
17 import net.sourceforge.phpdt.internal.compiler.lookup.*;
19 //dedicated treatment for the &&
20 public class AND_AND_Expression extends BinaryExpression {
22 int rightInitStateIndex = -1;
23 int mergedInitStateIndex = -1;
25 public AND_AND_Expression(Expression left, Expression right, int operator) {
26 super(left, right, operator);
29 public FlowInfo analyseCode(
30 BlockScope currentScope,
31 FlowContext flowContext,
34 Constant opConstant = left.conditionalConstant();
35 if (opConstant != NotAConstant) {
36 if (opConstant.booleanValue() == true) {
38 // need to be careful of scenario:
39 // (x && y) && !z, if passing the left info to the right, it would be swapped by the !
40 FlowInfo mergedInfo = left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
41 mergedInfo = right.analyseCode(currentScope, flowContext, mergedInfo);
42 mergedInitStateIndex =
43 currentScope.methodScope().recordInitializationStates(mergedInfo);
47 FlowInfo leftInfo = left.analyseCode(currentScope, flowContext, flowInfo);
48 // need to be careful of scenario:
49 // (x && y) && !z, if passing the left info to the right, it would be swapped by the !
50 FlowInfo rightInfo = leftInfo.initsWhenTrue().unconditionalInits().copy();
51 if (opConstant != NotAConstant && opConstant.booleanValue() == false) rightInfo.markAsFakeReachable(true);
54 currentScope.methodScope().recordInitializationStates(rightInfo);
55 rightInfo = right.analyseCode(currentScope, flowContext, rightInfo);
58 rightInfo.initsWhenTrue().copy(),
59 leftInfo.initsWhenFalse().copy().unconditionalInits().mergedWith(
60 rightInfo.initsWhenFalse().copy().unconditionalInits()));
61 mergedInitStateIndex =
62 currentScope.methodScope().recordInitializationStates(mergedInfo);
67 * Code generation for a binary operation
69 public void generateCode(
70 BlockScope currentScope,
71 CodeStream codeStream,
72 boolean valueRequired) {
74 int pc = codeStream.position;
75 Label falseLabel, endLabel;
76 if (constant != Constant.NotAConstant) {
79 codeStream.generateConstant(constant, implicitConversion);
80 codeStream.recordPositionsFrom(pc, this.sourceStart);
83 bits |= OnlyValueRequiredMASK;
84 generateOptimizedBoolean(
88 (falseLabel = new Label(codeStream)),
90 /* improving code gen for such a case: boolean b = i < 0 && false
91 * since the label has never been used, we have the inlined value on the stack. */
92 if (falseLabel.hasForwardReferences()) {
94 codeStream.iconst_1();
95 if ((bits & ValueForReturnMASK) != 0) {
98 codeStream.iconst_0();
100 codeStream.goto_(endLabel = new Label(codeStream));
101 codeStream.decrStackSize(1);
103 codeStream.iconst_0();
111 codeStream.generateImplicitConversion(implicitConversion);
113 codeStream.recordPositionsFrom(pc, this.sourceStart);
117 * Boolean operator code generation
118 * Optimized operations are: &&
120 public void generateOptimizedBoolean(
121 BlockScope currentScope,
122 CodeStream codeStream,
125 boolean valueRequired) {
126 if ((constant != Constant.NotAConstant) && (constant.typeID() == T_boolean)) {
127 super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
130 int pc = codeStream.position;
132 if ((condConst = left.conditionalConstant()) != NotAConstant) {
133 if (condConst.booleanValue() == true) {
134 // <something equivalent to true> && x
135 left.generateOptimizedBoolean(
141 if (rightInitStateIndex != -1) {
142 codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
144 if ((bits & OnlyValueRequiredMASK) != 0) {
145 right.generateCode(currentScope, codeStream, valueRequired);
147 right.generateOptimizedBoolean(
155 // <something equivalent to false> && x
156 left.generateOptimizedBoolean(
163 if ((bits & OnlyValueRequiredMASK) != 0) {
164 codeStream.iconst_0();
166 if (falseLabel != null) {
167 // implicit falling through the TRUE case
168 codeStream.goto_(falseLabel);
173 codeStream.recordPositionsFrom(pc, this.sourceStart);
174 if (mergedInitStateIndex != -1) {
175 codeStream.removeNotDefinitelyAssignedVariables(
177 mergedInitStateIndex);
181 if ((condConst = right.conditionalConstant()) != NotAConstant) {
182 if (condConst.booleanValue() == true) {
183 // x && <something equivalent to true>
184 if ((bits & OnlyValueRequiredMASK) != 0) {
185 left.generateCode(currentScope, codeStream, valueRequired);
187 left.generateOptimizedBoolean(
194 if (rightInitStateIndex != -1) {
195 codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
197 right.generateOptimizedBoolean(
204 // x && <something equivalent to false>
205 left.generateOptimizedBoolean(
211 if (rightInitStateIndex != -1) {
212 codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
214 right.generateOptimizedBoolean(
221 if ((bits & OnlyValueRequiredMASK) != 0) {
222 codeStream.iconst_0();
224 if (falseLabel != null) {
225 // implicit falling through the TRUE case
226 codeStream.goto_(falseLabel);
231 codeStream.recordPositionsFrom(pc, this.sourceStart);
232 if (mergedInitStateIndex != -1) {
233 codeStream.removeNotDefinitelyAssignedVariables(
235 mergedInitStateIndex);
240 if (falseLabel == null) {
241 if (trueLabel != null) {
242 // implicit falling through the FALSE case
243 Label internalFalseLabel = new Label(codeStream);
244 left.generateOptimizedBoolean(
250 if (rightInitStateIndex != -1) {
251 codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
253 right.generateOptimizedBoolean(
259 internalFalseLabel.place();
262 // implicit falling through the TRUE case
263 if (trueLabel == null) {
264 left.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel, true);
265 if (rightInitStateIndex != -1) {
266 codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
268 right.generateOptimizedBoolean(
275 // no implicit fall through TRUE/FALSE --> should never occur
278 codeStream.recordPositionsFrom(pc, this.sourceStart);
279 if (mergedInitStateIndex != -1) {
280 codeStream.removeNotDefinitelyAssignedVariables(
282 mergedInitStateIndex);
286 public boolean isCompactableOperation() {
290 public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
291 if (visitor.visit(this, scope)) {
292 left.traverse(visitor, scope);
293 right.traverse(visitor, scope);
295 visitor.endVisit(this, scope);