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.codegen.CodeStream;
15 import net.sourceforge.phpdt.internal.compiler.codegen.Label;
16 import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
17 import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
18 import net.sourceforge.phpdt.internal.compiler.impl.Constant;
19 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
21 //dedicated treatment for the &&
22 public class AND_AND_Expression extends BinaryExpression {
24 int rightInitStateIndex = -1;
25 int mergedInitStateIndex = -1;
27 public AND_AND_Expression(Expression left, Expression right, int operator) {
28 super(left, right, operator);
31 public FlowInfo analyseCode(
32 BlockScope currentScope,
33 FlowContext flowContext,
36 Constant opConstant = left.conditionalConstant();
37 if (opConstant != NotAConstant) {
38 if (opConstant.booleanValue() == true) {
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);
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 if (opConstant != NotAConstant && opConstant.booleanValue() == false) rightInfo.markAsFakeReachable(true);
56 currentScope.methodScope().recordInitializationStates(rightInfo);
57 rightInfo = right.analyseCode(currentScope, flowContext, rightInfo);
60 rightInfo.initsWhenTrue().copy(),
61 leftInfo.initsWhenFalse().copy().unconditionalInits().mergedWith(
62 rightInfo.initsWhenFalse().copy().unconditionalInits()));
63 mergedInitStateIndex =
64 currentScope.methodScope().recordInitializationStates(mergedInfo);
69 * Code generation for a binary operation
71 public void generateCode(
72 BlockScope currentScope,
73 CodeStream codeStream,
74 boolean valueRequired) {
76 int pc = codeStream.position;
77 Label falseLabel, endLabel;
78 if (constant != Constant.NotAConstant) {
81 codeStream.generateConstant(constant, implicitConversion);
82 codeStream.recordPositionsFrom(pc, this.sourceStart);
85 bits |= OnlyValueRequiredMASK;
86 generateOptimizedBoolean(
90 (falseLabel = new Label(codeStream)),
92 /* improving code gen for such a case: boolean b = i < 0 && false
93 * since the label has never been used, we have the inlined value on the stack. */
94 if (falseLabel.hasForwardReferences()) {
96 codeStream.iconst_1();
97 if ((bits & ValueForReturnMASK) != 0) {
100 codeStream.iconst_0();
102 codeStream.goto_(endLabel = new Label(codeStream));
103 codeStream.decrStackSize(1);
105 codeStream.iconst_0();
113 codeStream.generateImplicitConversion(implicitConversion);
115 codeStream.recordPositionsFrom(pc, this.sourceStart);
119 * Boolean operator code generation
120 * Optimized operations are: &&
122 public void generateOptimizedBoolean(
123 BlockScope currentScope,
124 CodeStream codeStream,
127 boolean valueRequired) {
128 if ((constant != Constant.NotAConstant) && (constant.typeID() == T_boolean)) {
129 super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
132 int pc = codeStream.position;
134 if ((condConst = left.conditionalConstant()) != NotAConstant) {
135 if (condConst.booleanValue() == true) {
136 // <something equivalent to true> && x
137 left.generateOptimizedBoolean(
143 if (rightInitStateIndex != -1) {
144 codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
146 if ((bits & OnlyValueRequiredMASK) != 0) {
147 right.generateCode(currentScope, codeStream, valueRequired);
149 right.generateOptimizedBoolean(
157 // <something equivalent to false> && x
158 left.generateOptimizedBoolean(
165 if ((bits & OnlyValueRequiredMASK) != 0) {
166 codeStream.iconst_0();
168 if (falseLabel != null) {
169 // implicit falling through the TRUE case
170 codeStream.goto_(falseLabel);
175 codeStream.recordPositionsFrom(pc, this.sourceStart);
176 if (mergedInitStateIndex != -1) {
177 codeStream.removeNotDefinitelyAssignedVariables(
179 mergedInitStateIndex);
183 if ((condConst = right.conditionalConstant()) != NotAConstant) {
184 if (condConst.booleanValue() == true) {
185 // x && <something equivalent to true>
186 if ((bits & OnlyValueRequiredMASK) != 0) {
187 left.generateCode(currentScope, codeStream, valueRequired);
189 left.generateOptimizedBoolean(
196 if (rightInitStateIndex != -1) {
197 codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
199 right.generateOptimizedBoolean(
206 // x && <something equivalent to false>
207 left.generateOptimizedBoolean(
213 if (rightInitStateIndex != -1) {
214 codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
216 right.generateOptimizedBoolean(
223 if ((bits & OnlyValueRequiredMASK) != 0) {
224 codeStream.iconst_0();
226 if (falseLabel != null) {
227 // implicit falling through the TRUE case
228 codeStream.goto_(falseLabel);
233 codeStream.recordPositionsFrom(pc, this.sourceStart);
234 if (mergedInitStateIndex != -1) {
235 codeStream.removeNotDefinitelyAssignedVariables(
237 mergedInitStateIndex);
242 if (falseLabel == null) {
243 if (trueLabel != null) {
244 // implicit falling through the FALSE case
245 Label internalFalseLabel = new Label(codeStream);
246 left.generateOptimizedBoolean(
252 if (rightInitStateIndex != -1) {
253 codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
255 right.generateOptimizedBoolean(
261 internalFalseLabel.place();
264 // implicit falling through the TRUE case
265 if (trueLabel == null) {
266 left.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel, true);
267 if (rightInitStateIndex != -1) {
268 codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
270 right.generateOptimizedBoolean(
277 // no implicit fall through TRUE/FALSE --> should never occur
280 codeStream.recordPositionsFrom(pc, this.sourceStart);
281 if (mergedInitStateIndex != -1) {
282 codeStream.removeNotDefinitelyAssignedVariables(
284 mergedInitStateIndex);
288 public boolean isCompactableOperation() {
292 public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
293 if (visitor.visit(this, scope)) {
294 left.traverse(visitor, scope);
295 right.traverse(visitor, scope);
297 visitor.endVisit(this, scope);