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.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;
 
  24         int mergedInitStateIndex = -1;
 
  26         public AND_AND_Expression(Expression left, Expression right, int operator) {
 
  27                 super(left, right, operator);
 
  30         public FlowInfo analyseCode(BlockScope currentScope,
 
  31                         FlowContext flowContext, FlowInfo flowInfo) {
 
  33                 Constant cst = this.left.optimizedBooleanConstant();
 
  34                 boolean isLeftOptimizedTrue = cst != NotAConstant
 
  35                                 && cst.booleanValue() == true;
 
  36                 boolean isLeftOptimizedFalse = cst != NotAConstant
 
  37                                 && cst.booleanValue() == false;
 
  39                 if (isLeftOptimizedTrue) {
 
  41                         // need to be careful of scenario:
 
  42                         // (x && y) && !z, if passing the left info to the right, it would
 
  43                         // be swapped by the !
 
  44                         FlowInfo mergedInfo = left.analyseCode(currentScope, flowContext,
 
  45                                         flowInfo).unconditionalInits();
 
  46                         mergedInfo = right.analyseCode(currentScope, flowContext,
 
  48                         mergedInitStateIndex = currentScope.methodScope()
 
  49                                         .recordInitializationStates(mergedInfo);
 
  53                 FlowInfo leftInfo = left.analyseCode(currentScope, flowContext,
 
  55                 // need to be careful of scenario:
 
  56                 // (x && y) && !z, if passing the left info to the right, it would be
 
  58                 FlowInfo rightInfo = leftInfo.initsWhenTrue().unconditionalInits()
 
  60                 rightInitStateIndex = currentScope.methodScope()
 
  61                                 .recordInitializationStates(rightInfo);
 
  63                 int previousMode = rightInfo.reachMode();
 
  64                 if (isLeftOptimizedFalse) {
 
  65                         rightInfo.setReachMode(FlowInfo.UNREACHABLE);
 
  67                 rightInfo = right.analyseCode(currentScope, flowContext, rightInfo);
 
  68                 FlowInfo trueMergedInfo = rightInfo.initsWhenTrue().copy();
 
  69                 rightInfo.setReachMode(previousMode); // reset after trueMergedInfo
 
  72                 FlowInfo mergedInfo = FlowInfo
 
  73                                 .conditional(trueMergedInfo, leftInfo.initsWhenFalse().copy()
 
  74                                                 .unconditionalInits().mergedWith(
 
  75                                                                 rightInfo.initsWhenFalse().copy()
 
  76                                                                                 .unconditionalInits()));
 
  77                 mergedInitStateIndex = currentScope.methodScope()
 
  78                                 .recordInitializationStates(mergedInfo);
 
  83          * Code generation for a binary operation
 
  85         // public void generateCode(
 
  86         // BlockScope currentScope,
 
  87         // CodeStream codeStream,
 
  88         // boolean valueRequired) {
 
  90         // int pc = codeStream.position;
 
  91         // Label falseLabel, endLabel;
 
  92         // if (constant != Constant.NotAConstant) {
 
  95         // codeStream.generateConstant(constant, implicitConversion);
 
  96         // codeStream.recordPositionsFrom(pc, this.sourceStart);
 
  99         // bits |= OnlyValueRequiredMASK;
 
 100         // generateOptimizedBoolean(
 
 104         // (falseLabel = new Label(codeStream)),
 
 106         // /* improving code gen for such a case: boolean b = i < 0 && false
 
 107         // * since the label has never been used, we have the inlined value on the
 
 109         // if (falseLabel.hasForwardReferences()) {
 
 110         // if (valueRequired) {
 
 111         // codeStream.iconst_1();
 
 112         // if ((bits & ValueForReturnMASK) != 0) {
 
 113         // codeStream.ireturn();
 
 114         // falseLabel.place();
 
 115         // codeStream.iconst_0();
 
 117         // codeStream.goto_(endLabel = new Label(codeStream));
 
 118         // codeStream.decrStackSize(1);
 
 119         // falseLabel.place();
 
 120         // codeStream.iconst_0();
 
 124         // falseLabel.place();
 
 127         // if (valueRequired) {
 
 128         // codeStream.generateImplicitConversion(implicitConversion);
 
 130         // // reposition the endPC
 
 131         // codeStream.updateLastRecordedEndPC(codeStream.position);
 
 134          * Boolean operator code generation Optimized operations are: &&
 
 136         // public void generateOptimizedBoolean(
 
 137         // BlockScope currentScope,
 
 138         // CodeStream codeStream,
 
 141         // boolean valueRequired) {
 
 143         // if (constant != Constant.NotAConstant) {
 
 144         // super.generateOptimizedBoolean(currentScope, codeStream, trueLabel,
 
 145         // falseLabel, valueRequired);
 
 148         // Constant condConst;
 
 149         // if ((condConst = left.optimizedBooleanConstant()) != NotAConstant) {
 
 150         // if (condConst.booleanValue() == true) {
 
 151         // // <something equivalent to true> && x
 
 152         // left.generateOptimizedBoolean(
 
 158         // if (rightInitStateIndex != -1) {
 
 159         // codeStream.addDefinitelyAssignedVariables(currentScope,
 
 160         // rightInitStateIndex);
 
 162         // if ((bits & OnlyValueRequiredMASK) != 0) {
 
 163         // right.generateCode(currentScope, codeStream, valueRequired);
 
 165         // right.generateOptimizedBoolean(
 
 173         // // <something equivalent to false> && x
 
 174         // left.generateOptimizedBoolean(
 
 180         // if (valueRequired) {
 
 181         // if ((bits & OnlyValueRequiredMASK) != 0) {
 
 182         // codeStream.iconst_0();
 
 184         // if (falseLabel != null) {
 
 185         // // implicit falling through the TRUE case
 
 186         // codeStream.goto_(falseLabel);
 
 190         // // reposition the endPC
 
 191         // codeStream.updateLastRecordedEndPC(codeStream.position);
 
 193         // if (mergedInitStateIndex != -1) {
 
 194         // codeStream.removeNotDefinitelyAssignedVariables(
 
 196         // mergedInitStateIndex);
 
 200         // if ((condConst = right.optimizedBooleanConstant()) != NotAConstant) {
 
 201         // if (condConst.booleanValue() == true) {
 
 202         // // x && <something equivalent to true>
 
 203         // if ((bits & OnlyValueRequiredMASK) != 0) {
 
 204         // left.generateCode(currentScope, codeStream, valueRequired);
 
 206         // left.generateOptimizedBoolean(
 
 213         // if (rightInitStateIndex != -1) {
 
 214         // codeStream.addDefinitelyAssignedVariables(currentScope,
 
 215         // rightInitStateIndex);
 
 217         // right.generateOptimizedBoolean(
 
 224         // // x && <something equivalent to false>
 
 225         // Label internalTrueLabel = new Label(codeStream);
 
 226         // left.generateOptimizedBoolean(
 
 229         // internalTrueLabel, // will be false in the end
 
 232         // if (rightInitStateIndex != -1) {
 
 233         // codeStream.addDefinitelyAssignedVariables(currentScope,
 
 234         // rightInitStateIndex);
 
 236         // internalTrueLabel.place();
 
 237         // right.generateOptimizedBoolean(
 
 243         // if (valueRequired) {
 
 244         // if ((bits & OnlyValueRequiredMASK) != 0) {
 
 245         // codeStream.iconst_0();
 
 247         // if (falseLabel != null) {
 
 248         // // implicit falling through the TRUE case
 
 249         // codeStream.goto_(falseLabel);
 
 253         // // reposition the endPC
 
 254         // codeStream.updateLastRecordedEndPC(codeStream.position);
 
 256         // if (mergedInitStateIndex != -1) {
 
 257         // codeStream.removeNotDefinitelyAssignedVariables(
 
 259         // mergedInitStateIndex);
 
 264         // if (falseLabel == null) {
 
 265         // if (trueLabel != null) {
 
 266         // // implicit falling through the FALSE case
 
 267         // Label internalFalseLabel = new Label(codeStream);
 
 268         // left.generateOptimizedBoolean(
 
 272         // internalFalseLabel,
 
 274         // if (rightInitStateIndex != -1) {
 
 275         // codeStream.addDefinitelyAssignedVariables(currentScope,
 
 276         // rightInitStateIndex);
 
 278         // right.generateOptimizedBoolean(
 
 284         // internalFalseLabel.place();
 
 287         // // implicit falling through the TRUE case
 
 288         // if (trueLabel == null) {
 
 289         // left.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel,
 
 291         // if (rightInitStateIndex != -1) {
 
 292         // codeStream.addDefinitelyAssignedVariables(currentScope,
 
 293         // rightInitStateIndex);
 
 295         // right.generateOptimizedBoolean(
 
 302         // // no implicit fall through TRUE/FALSE --> should never occur
 
 305         // if (mergedInitStateIndex != -1) {
 
 306         // codeStream.removeNotDefinitelyAssignedVariables(
 
 308         // mergedInitStateIndex);
 
 311         public boolean isCompactableOperation() {
 
 315         public void traverse(ASTVisitor visitor, BlockScope scope) {
 
 316                 if (visitor.visit(this, scope)) {
 
 317                         left.traverse(visitor, scope);
 
 318                         right.traverse(visitor, scope);
 
 320                 visitor.endVisit(this, scope);