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.core.compiler.ITerminalSymbols.TokenName;
14 import net.sourceforge.phpdt.internal.compiler.ASTVisitor;
15 import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
16 import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
17 import net.sourceforge.phpdt.internal.compiler.impl.Constant;
18 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
20 // dedicated treatment for the &&
21 public class AND_AND_Expression extends BinaryExpression {
23 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(BlockScope currentScope,
32 FlowContext flowContext, FlowInfo flowInfo) {
34 Constant cst = this.left.optimizedBooleanConstant();
35 boolean isLeftOptimizedTrue = cst != NotAConstant
36 && cst.booleanValue() == true;
37 boolean isLeftOptimizedFalse = cst != NotAConstant
38 && cst.booleanValue() == false;
40 if (isLeftOptimizedTrue) {
42 // need to be careful of scenario:
43 // (x && y) && !z, if passing the left info to the right, it would
44 // be swapped by the !
45 FlowInfo mergedInfo = left.analyseCode(currentScope, flowContext,
46 flowInfo).unconditionalInits();
47 mergedInfo = right.analyseCode(currentScope, flowContext,
49 mergedInitStateIndex = currentScope.methodScope()
50 .recordInitializationStates(mergedInfo);
54 FlowInfo leftInfo = left.analyseCode(currentScope, flowContext,
56 // need to be careful of scenario:
57 // (x && y) && !z, if passing the left info to the right, it would be
59 FlowInfo rightInfo = leftInfo.initsWhenTrue().unconditionalInits()
61 rightInitStateIndex = currentScope.methodScope()
62 .recordInitializationStates(rightInfo);
64 int previousMode = rightInfo.reachMode();
65 if (isLeftOptimizedFalse) {
66 rightInfo.setReachMode(FlowInfo.UNREACHABLE);
68 rightInfo = right.analyseCode(currentScope, flowContext, rightInfo);
69 FlowInfo trueMergedInfo = rightInfo.initsWhenTrue().copy();
70 rightInfo.setReachMode(previousMode); // reset after trueMergedInfo
73 FlowInfo mergedInfo = FlowInfo
74 .conditional(trueMergedInfo, leftInfo.initsWhenFalse().copy()
75 .unconditionalInits().mergedWith(
76 rightInfo.initsWhenFalse().copy()
77 .unconditionalInits()));
78 mergedInitStateIndex = currentScope.methodScope()
79 .recordInitializationStates(mergedInfo);
84 * Code generation for a binary operation
86 // public void generateCode(
87 // BlockScope currentScope,
88 // CodeStream codeStream,
89 // boolean valueRequired) {
91 // int pc = codeStream.position;
92 // Label falseLabel, endLabel;
93 // if (constant != Constant.NotAConstant) {
96 // codeStream.generateConstant(constant, implicitConversion);
97 // codeStream.recordPositionsFrom(pc, this.sourceStart);
100 // bits |= OnlyValueRequiredMASK;
101 // generateOptimizedBoolean(
105 // (falseLabel = new Label(codeStream)),
107 // /* improving code gen for such a case: boolean b = i < 0 && false
108 // * since the label has never been used, we have the inlined value on the
110 // if (falseLabel.hasForwardReferences()) {
111 // if (valueRequired) {
112 // codeStream.iconst_1();
113 // if ((bits & ValueForReturnMASK) != 0) {
114 // codeStream.ireturn();
115 // falseLabel.place();
116 // codeStream.iconst_0();
118 // codeStream.goto_(endLabel = new Label(codeStream));
119 // codeStream.decrStackSize(1);
120 // falseLabel.place();
121 // codeStream.iconst_0();
125 // falseLabel.place();
128 // if (valueRequired) {
129 // codeStream.generateImplicitConversion(implicitConversion);
131 // // reposition the endPC
132 // codeStream.updateLastRecordedEndPC(codeStream.position);
135 * Boolean operator code generation Optimized operations are: &&
137 // public void generateOptimizedBoolean(
138 // BlockScope currentScope,
139 // CodeStream codeStream,
142 // boolean valueRequired) {
144 // if (constant != Constant.NotAConstant) {
145 // super.generateOptimizedBoolean(currentScope, codeStream, trueLabel,
146 // falseLabel, valueRequired);
149 // Constant condConst;
150 // if ((condConst = left.optimizedBooleanConstant()) != NotAConstant) {
151 // if (condConst.booleanValue() == true) {
152 // // <something equivalent to true> && x
153 // left.generateOptimizedBoolean(
159 // if (rightInitStateIndex != -1) {
160 // codeStream.addDefinitelyAssignedVariables(currentScope,
161 // rightInitStateIndex);
163 // if ((bits & OnlyValueRequiredMASK) != 0) {
164 // right.generateCode(currentScope, codeStream, valueRequired);
166 // right.generateOptimizedBoolean(
174 // // <something equivalent to false> && x
175 // left.generateOptimizedBoolean(
181 // if (valueRequired) {
182 // if ((bits & OnlyValueRequiredMASK) != 0) {
183 // codeStream.iconst_0();
185 // if (falseLabel != null) {
186 // // implicit falling through the TRUE case
187 // codeStream.goto_(falseLabel);
191 // // reposition the endPC
192 // codeStream.updateLastRecordedEndPC(codeStream.position);
194 // if (mergedInitStateIndex != -1) {
195 // codeStream.removeNotDefinitelyAssignedVariables(
197 // mergedInitStateIndex);
201 // if ((condConst = right.optimizedBooleanConstant()) != NotAConstant) {
202 // if (condConst.booleanValue() == true) {
203 // // x && <something equivalent to true>
204 // if ((bits & OnlyValueRequiredMASK) != 0) {
205 // left.generateCode(currentScope, codeStream, valueRequired);
207 // left.generateOptimizedBoolean(
214 // if (rightInitStateIndex != -1) {
215 // codeStream.addDefinitelyAssignedVariables(currentScope,
216 // rightInitStateIndex);
218 // right.generateOptimizedBoolean(
225 // // x && <something equivalent to false>
226 // Label internalTrueLabel = new Label(codeStream);
227 // left.generateOptimizedBoolean(
230 // internalTrueLabel, // will be false in the end
233 // if (rightInitStateIndex != -1) {
234 // codeStream.addDefinitelyAssignedVariables(currentScope,
235 // rightInitStateIndex);
237 // internalTrueLabel.place();
238 // right.generateOptimizedBoolean(
244 // if (valueRequired) {
245 // if ((bits & OnlyValueRequiredMASK) != 0) {
246 // codeStream.iconst_0();
248 // if (falseLabel != null) {
249 // // implicit falling through the TRUE case
250 // codeStream.goto_(falseLabel);
254 // // reposition the endPC
255 // codeStream.updateLastRecordedEndPC(codeStream.position);
257 // if (mergedInitStateIndex != -1) {
258 // codeStream.removeNotDefinitelyAssignedVariables(
260 // mergedInitStateIndex);
265 // if (falseLabel == null) {
266 // if (trueLabel != null) {
267 // // implicit falling through the FALSE case
268 // Label internalFalseLabel = new Label(codeStream);
269 // left.generateOptimizedBoolean(
273 // internalFalseLabel,
275 // if (rightInitStateIndex != -1) {
276 // codeStream.addDefinitelyAssignedVariables(currentScope,
277 // rightInitStateIndex);
279 // right.generateOptimizedBoolean(
285 // internalFalseLabel.place();
288 // // implicit falling through the TRUE case
289 // if (trueLabel == null) {
290 // left.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel,
292 // if (rightInitStateIndex != -1) {
293 // codeStream.addDefinitelyAssignedVariables(currentScope,
294 // rightInitStateIndex);
296 // right.generateOptimizedBoolean(
303 // // no implicit fall through TRUE/FALSE --> should never occur
306 // if (mergedInitStateIndex != -1) {
307 // codeStream.removeNotDefinitelyAssignedVariables(
309 // mergedInitStateIndex);
312 public boolean isCompactableOperation() {
316 public void traverse(ASTVisitor visitor, BlockScope scope) {
317 if (visitor.visit(this, scope)) {
318 left.traverse(visitor, scope);
319 right.traverse(visitor, scope);
321 visitor.endVisit(this, scope);