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.phpeclipse.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;
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 cst = this.left.optimizedBooleanConstant();
35 boolean isLeftOptimizedTrue = cst != NotAConstant && cst.booleanValue() == true;
36 boolean isLeftOptimizedFalse = cst != NotAConstant && cst.booleanValue() == false;
38 if (isLeftOptimizedTrue) {
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();
54 currentScope.methodScope().recordInitializationStates(rightInfo);
56 int previousMode = rightInfo.reachMode();
57 if (isLeftOptimizedFalse){
58 rightInfo.setReachMode(FlowInfo.UNREACHABLE);
60 rightInfo = right.analyseCode(currentScope, flowContext, rightInfo);
61 FlowInfo trueMergedInfo = rightInfo.initsWhenTrue().copy();
62 rightInfo.setReachMode(previousMode); // reset after trueMergedInfo got extracted
67 leftInfo.initsWhenFalse().copy().unconditionalInits().mergedWith(
68 rightInfo.initsWhenFalse().copy().unconditionalInits()));
69 mergedInitStateIndex =
70 currentScope.methodScope().recordInitializationStates(mergedInfo);
75 * Code generation for a binary operation
77 // public void generateCode(
78 // BlockScope currentScope,
79 // CodeStream codeStream,
80 // boolean valueRequired) {
82 // int pc = codeStream.position;
83 // Label falseLabel, endLabel;
84 // if (constant != Constant.NotAConstant) {
87 // codeStream.generateConstant(constant, implicitConversion);
88 // codeStream.recordPositionsFrom(pc, this.sourceStart);
91 // bits |= OnlyValueRequiredMASK;
92 // generateOptimizedBoolean(
96 // (falseLabel = new Label(codeStream)),
98 // /* improving code gen for such a case: boolean b = i < 0 && false
99 // * since the label has never been used, we have the inlined value on the stack. */
100 // if (falseLabel.hasForwardReferences()) {
101 // if (valueRequired) {
102 // codeStream.iconst_1();
103 // if ((bits & ValueForReturnMASK) != 0) {
104 // codeStream.ireturn();
105 // falseLabel.place();
106 // codeStream.iconst_0();
108 // codeStream.goto_(endLabel = new Label(codeStream));
109 // codeStream.decrStackSize(1);
110 // falseLabel.place();
111 // codeStream.iconst_0();
115 // falseLabel.place();
118 // if (valueRequired) {
119 // codeStream.generateImplicitConversion(implicitConversion);
121 // // reposition the endPC
122 // codeStream.updateLastRecordedEndPC(codeStream.position);
126 * Boolean operator code generation
127 * Optimized operations are: &&
129 // public void generateOptimizedBoolean(
130 // BlockScope currentScope,
131 // CodeStream codeStream,
134 // boolean valueRequired) {
136 // if (constant != Constant.NotAConstant) {
137 // super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
140 // Constant condConst;
141 // if ((condConst = left.optimizedBooleanConstant()) != NotAConstant) {
142 // if (condConst.booleanValue() == true) {
143 // // <something equivalent to true> && x
144 // left.generateOptimizedBoolean(
150 // if (rightInitStateIndex != -1) {
151 // codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
153 // if ((bits & OnlyValueRequiredMASK) != 0) {
154 // right.generateCode(currentScope, codeStream, valueRequired);
156 // right.generateOptimizedBoolean(
164 // // <something equivalent to false> && x
165 // left.generateOptimizedBoolean(
171 // if (valueRequired) {
172 // if ((bits & OnlyValueRequiredMASK) != 0) {
173 // codeStream.iconst_0();
175 // if (falseLabel != null) {
176 // // implicit falling through the TRUE case
177 // codeStream.goto_(falseLabel);
181 // // reposition the endPC
182 // codeStream.updateLastRecordedEndPC(codeStream.position);
184 // if (mergedInitStateIndex != -1) {
185 // codeStream.removeNotDefinitelyAssignedVariables(
187 // mergedInitStateIndex);
191 // if ((condConst = right.optimizedBooleanConstant()) != NotAConstant) {
192 // if (condConst.booleanValue() == true) {
193 // // x && <something equivalent to true>
194 // if ((bits & OnlyValueRequiredMASK) != 0) {
195 // left.generateCode(currentScope, codeStream, valueRequired);
197 // left.generateOptimizedBoolean(
204 // if (rightInitStateIndex != -1) {
205 // codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
207 // right.generateOptimizedBoolean(
214 // // x && <something equivalent to false>
215 // Label internalTrueLabel = new Label(codeStream);
216 // left.generateOptimizedBoolean(
219 // internalTrueLabel, // will be false in the end
222 // if (rightInitStateIndex != -1) {
223 // codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
225 // internalTrueLabel.place();
226 // right.generateOptimizedBoolean(
232 // if (valueRequired) {
233 // if ((bits & OnlyValueRequiredMASK) != 0) {
234 // codeStream.iconst_0();
236 // if (falseLabel != null) {
237 // // implicit falling through the TRUE case
238 // codeStream.goto_(falseLabel);
242 // // reposition the endPC
243 // codeStream.updateLastRecordedEndPC(codeStream.position);
245 // if (mergedInitStateIndex != -1) {
246 // codeStream.removeNotDefinitelyAssignedVariables(
248 // mergedInitStateIndex);
253 // if (falseLabel == null) {
254 // if (trueLabel != null) {
255 // // implicit falling through the FALSE case
256 // Label internalFalseLabel = new Label(codeStream);
257 // left.generateOptimizedBoolean(
261 // internalFalseLabel,
263 // if (rightInitStateIndex != -1) {
264 // codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
266 // right.generateOptimizedBoolean(
272 // internalFalseLabel.place();
275 // // implicit falling through the TRUE case
276 // if (trueLabel == null) {
277 // left.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel, true);
278 // if (rightInitStateIndex != -1) {
279 // codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
281 // right.generateOptimizedBoolean(
288 // // no implicit fall through TRUE/FALSE --> should never occur
291 // if (mergedInitStateIndex != -1) {
292 // codeStream.removeNotDefinitelyAssignedVariables(
294 // mergedInitStateIndex);
298 public boolean isCompactableOperation() {
302 public void traverse(ASTVisitor visitor, BlockScope scope) {
303 if (visitor.visit(this, scope)) {
304 left.traverse(visitor, scope);
305 right.traverse(visitor, scope);
307 visitor.endVisit(this, scope);