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 OR_OR_Expression extends BinaryExpression {
24 int rightInitStateIndex = -1;
25 int mergedInitStateIndex = -1;
27 public OR_OR_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() == false) {
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, rightInfo;
50 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 rightInfo = leftInfo.initsWhenFalse().unconditionalInits().copy();
55 if (opConstant != NotAConstant && opConstant.booleanValue() == true) rightInfo.markAsFakeReachable(true);
58 currentScope.methodScope().recordInitializationStates(rightInfo);
59 rightInfo = right.analyseCode(currentScope, flowContext, rightInfo);
60 FlowInfo mergedInfo = FlowInfo.conditional(
61 // merging two true initInfos for such a negative case: if ((t && (b = t)) || f) r = b; // b may not have been initialized
62 leftInfo.initsWhenTrue().copy().unconditionalInits().mergedWith(
63 rightInfo.initsWhenTrue().copy().unconditionalInits()),
64 rightInfo.initsWhenFalse().copy());
65 mergedInitStateIndex =
66 currentScope.methodScope().recordInitializationStates(mergedInfo);
71 * Code generation for a binary operation
73 * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
74 * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
75 * @param valueRequired boolean
77 public void generateCode(
78 BlockScope currentScope,
79 CodeStream codeStream,
80 boolean valueRequired) {
81 int pc = codeStream.position;
82 Label falseLabel, endLabel;
83 if (constant != Constant.NotAConstant) {
85 codeStream.generateConstant(constant, implicitConversion);
86 codeStream.recordPositionsFrom(pc, this.sourceStart);
89 bits |= OnlyValueRequiredMASK;
90 generateOptimizedBoolean(
94 (falseLabel = new Label(codeStream)),
96 /* improving code gen for such a case: boolean b = i < 0 || true;
97 * since the label has never been used, we have the inlined value on the stack. */
98 if (falseLabel.hasForwardReferences()) {
100 codeStream.iconst_1();
101 if ((bits & ValueForReturnMASK) != 0) {
102 codeStream.ireturn();
104 codeStream.iconst_0();
106 codeStream.goto_(endLabel = new Label(codeStream));
107 codeStream.decrStackSize(1);
109 codeStream.iconst_0();
117 codeStream.generateImplicitConversion(implicitConversion);
119 codeStream.recordPositionsFrom(pc, this.sourceStart);
123 * Boolean operator code generation
124 * Optimized operations are: ||
126 public void generateOptimizedBoolean(
127 BlockScope currentScope,
128 CodeStream codeStream,
131 boolean valueRequired) {
132 if ((constant != Constant.NotAConstant) && (constant.typeID() == T_boolean)) {
133 super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
136 int pc = codeStream.position;
138 if ((condConst = left.conditionalConstant()) != NotAConstant) {
139 if (condConst.booleanValue() == true) {
140 // <something equivalent to true> || x
141 left.generateOptimizedBoolean(
148 if ((bits & OnlyValueRequiredMASK) != 0) {
149 codeStream.iconst_1();
151 if (trueLabel != null) {
152 codeStream.goto_(trueLabel);
157 // <something equivalent to false> || x
158 left.generateOptimizedBoolean(
164 if (rightInitStateIndex != -1) {
165 codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
167 if ((bits & OnlyValueRequiredMASK) != 0) {
168 right.generateCode(currentScope, codeStream, valueRequired);
170 right.generateOptimizedBoolean(
178 codeStream.recordPositionsFrom(pc, this.sourceStart);
179 if (mergedInitStateIndex != -1) {
180 codeStream.removeNotDefinitelyAssignedVariables(
182 mergedInitStateIndex);
186 if ((condConst = right.conditionalConstant()) != NotAConstant) {
187 if (condConst.booleanValue() == true) {
188 // x || <something equivalent to true>
189 left.generateOptimizedBoolean(
195 if (rightInitStateIndex != -1) {
196 codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
198 right.generateOptimizedBoolean(
205 if ((bits & OnlyValueRequiredMASK) != 0) {
206 codeStream.iconst_1();
208 if (trueLabel != null) {
209 codeStream.goto_(trueLabel);
214 // x || <something equivalent to false>
215 if ((bits & OnlyValueRequiredMASK) != 0) {
216 left.generateCode(currentScope, codeStream, valueRequired);
218 left.generateOptimizedBoolean(
225 if (rightInitStateIndex != -1) {
226 codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
228 right.generateOptimizedBoolean(
235 codeStream.recordPositionsFrom(pc, this.sourceStart);
236 if (mergedInitStateIndex != -1) {
237 codeStream.removeNotDefinitelyAssignedVariables(
239 mergedInitStateIndex);
244 if (falseLabel == null) {
245 if (trueLabel != null) {
246 // implicit falling through the FALSE case
247 left.generateOptimizedBoolean(currentScope, codeStream, trueLabel, null, true);
248 right.generateOptimizedBoolean(
256 // implicit falling through the TRUE case
257 if (trueLabel == null) {
258 Label internalTrueLabel = new Label(codeStream);
259 left.generateOptimizedBoolean(
265 if (rightInitStateIndex != -1) {
266 codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
268 right.generateOptimizedBoolean(
274 internalTrueLabel.place();
276 // no implicit fall through TRUE/FALSE --> should never occur
279 codeStream.recordPositionsFrom(pc, this.sourceStart);
280 if (mergedInitStateIndex != -1) {
281 codeStream.removeNotDefinitelyAssignedVariables(
283 mergedInitStateIndex);
287 public boolean isCompactableOperation() {
291 public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
292 if (visitor.visit(this, scope)) {
293 left.traverse(visitor, scope);
294 right.traverse(visitor, scope);
296 visitor.endVisit(this, scope);