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.IAbstractSyntaxTreeVisitor;
14 import net.sourceforge.phpdt.internal.compiler.codegen.Label;
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 OR_OR_Expression extends BinaryExpression {
23 int rightInitStateIndex = -1;
24 int mergedInitStateIndex = -1;
26 public OR_OR_Expression(Expression left, Expression right, int operator) {
27 super(left, right, operator);
30 public FlowInfo analyseCode(
31 BlockScope currentScope,
32 FlowContext flowContext,
35 Constant cst = this.left.optimizedBooleanConstant();
36 boolean isLeftOptimizedTrue = cst != NotAConstant && cst.booleanValue() == true;
37 boolean isLeftOptimizedFalse = cst != NotAConstant && cst.booleanValue() == false;
39 if (isLeftOptimizedFalse) {
41 // need to be careful of scenario:
42 // (x || y) || !z, if passing the left info to the right, it would be swapped by the !
43 FlowInfo mergedInfo = left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
44 mergedInfo = right.analyseCode(currentScope, flowContext, mergedInfo);
45 mergedInitStateIndex =
46 currentScope.methodScope().recordInitializationStates(mergedInfo);
50 FlowInfo leftInfo = left.analyseCode(currentScope, flowContext, flowInfo);
52 // need to be careful of scenario:
53 // (x || y) || !z, if passing the left info to the right, it would be swapped by the !
54 FlowInfo rightInfo = leftInfo.initsWhenFalse().unconditionalInits().copy();
56 currentScope.methodScope().recordInitializationStates(rightInfo);
58 int previousMode = rightInfo.reachMode();
59 if (isLeftOptimizedTrue){
60 rightInfo.setReachMode(FlowInfo.UNREACHABLE);
62 rightInfo = right.analyseCode(currentScope, flowContext, rightInfo);
63 FlowInfo falseMergedInfo = rightInfo.initsWhenFalse().copy();
64 rightInfo.setReachMode(previousMode); // reset after falseMergedInfo got extracted
66 FlowInfo mergedInfo = FlowInfo.conditional(
67 // merging two true initInfos for such a negative case: if ((t && (b = t)) || f) r = b; // b may not have been initialized
68 leftInfo.initsWhenTrue().copy().unconditionalInits().mergedWith(
69 rightInfo.initsWhenTrue().copy().unconditionalInits()),
71 mergedInitStateIndex =
72 currentScope.methodScope().recordInitializationStates(mergedInfo);
77 * Code generation for a binary operation
79 * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
80 * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
81 * @param valueRequired boolean
83 // public void generateCode(
84 // BlockScope currentScope,
85 // CodeStream codeStream,
86 // boolean valueRequired) {
87 // int pc = codeStream.position;
88 // Label falseLabel, endLabel;
89 // if (constant != Constant.NotAConstant) {
91 // codeStream.generateConstant(constant, implicitConversion);
92 // codeStream.recordPositionsFrom(pc, this.sourceStart);
95 // bits |= OnlyValueRequiredMASK;
96 // generateOptimizedBoolean(
100 // (falseLabel = new Label(codeStream)),
102 // /* improving code gen for such a case: boolean b = i < 0 || true;
103 // * since the label has never been used, we have the inlined value on the stack. */
104 // if (falseLabel.hasForwardReferences()) {
105 // if (valueRequired) {
106 // codeStream.iconst_1();
107 // if ((bits & ValueForReturnMASK) != 0) {
108 // codeStream.ireturn();
109 // falseLabel.place();
110 // codeStream.iconst_0();
112 // codeStream.goto_(endLabel = new Label(codeStream));
113 // codeStream.decrStackSize(1);
114 // falseLabel.place();
115 // codeStream.iconst_0();
119 // falseLabel.place();
122 // if (valueRequired) {
123 // codeStream.generateImplicitConversion(implicitConversion);
125 // codeStream.recordPositionsFrom(pc, this.sourceStart);
129 // * Boolean operator code generation
130 // * Optimized operations are: ||
132 // public void generateOptimizedBoolean(
133 // BlockScope currentScope,
134 // CodeStream codeStream,
137 // boolean valueRequired) {
138 // if (constant != Constant.NotAConstant) {
139 // super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
142 // Constant condConst;
143 // if ((condConst = left.optimizedBooleanConstant()) != NotAConstant) {
144 // if (condConst.booleanValue() == true) {
145 // // <something equivalent to true> || x
146 // left.generateOptimizedBoolean(
152 // if (valueRequired) {
153 // if ((bits & OnlyValueRequiredMASK) != 0) {
154 // codeStream.iconst_1();
156 // if (trueLabel != null) {
157 // codeStream.goto_(trueLabel);
161 // // reposition the endPC
162 // codeStream.updateLastRecordedEndPC(codeStream.position);
164 // // <something equivalent to false> || x
165 // left.generateOptimizedBoolean(
171 // if (rightInitStateIndex != -1) {
172 // codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
174 // if ((bits & OnlyValueRequiredMASK) != 0) {
175 // right.generateCode(currentScope, codeStream, valueRequired);
177 // right.generateOptimizedBoolean(
185 // if (mergedInitStateIndex != -1) {
186 // codeStream.removeNotDefinitelyAssignedVariables(
188 // mergedInitStateIndex);
192 // if ((condConst = right.optimizedBooleanConstant()) != NotAConstant) {
193 // if (condConst.booleanValue() == true) {
194 // // x || <something equivalent to true>
195 // Label internalFalseLabel = new Label(codeStream);
196 // left.generateOptimizedBoolean(
200 // internalFalseLabel, // will be true in the end
202 // if (rightInitStateIndex != -1) {
203 // codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
205 // internalFalseLabel.place();
206 // right.generateOptimizedBoolean(
212 // if (valueRequired) {
213 // if ((bits & OnlyValueRequiredMASK) != 0) {
214 // codeStream.iconst_1();
216 // if (trueLabel != null) {
217 // codeStream.goto_(trueLabel);
221 // // reposition the endPC
222 // codeStream.updateLastRecordedEndPC(codeStream.position);
224 // // x || <something equivalent to false>
225 // if ((bits & OnlyValueRequiredMASK) != 0) {
226 // left.generateCode(currentScope, codeStream, valueRequired);
228 // left.generateOptimizedBoolean(
235 // if (rightInitStateIndex != -1) {
236 // codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
238 // right.generateOptimizedBoolean(
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 // left.generateOptimizedBoolean(currentScope, codeStream, trueLabel, null, true);
257 // right.generateOptimizedBoolean(
265 // // implicit falling through the TRUE case
266 // if (trueLabel == null) {
267 // Label internalTrueLabel = new Label(codeStream);
268 // left.generateOptimizedBoolean(
271 // internalTrueLabel,
274 // if (rightInitStateIndex != -1) {
275 // codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
277 // right.generateOptimizedBoolean(
283 // internalTrueLabel.place();
285 // // no implicit fall through TRUE/FALSE --> should never occur
288 // if (mergedInitStateIndex != -1) {
289 // codeStream.removeNotDefinitelyAssignedVariables(
291 // mergedInitStateIndex);
295 public boolean isCompactableOperation() {
299 public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
300 if (visitor.visit(this, scope)) {
301 left.traverse(visitor, scope);
302 right.traverse(visitor, scope);
304 visitor.endVisit(this, scope);