+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
package net.sourceforge.phpdt.internal.compiler.ast;
-import java.util.List;
-import java.util.ArrayList;
+import net.sourceforge.phpdt.internal.compiler.ASTVisitor;
+import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
+import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
+import net.sourceforge.phpdt.internal.compiler.impl.Constant;
+import net.sourceforge.phpdt.internal.compiler.lookup.ArrayBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
-/**
- * @author Matthieu Casanova
- */
public class BinaryExpression extends OperatorExpression {
- /** The two expressions. */
- public Expression left,right;
-
- public BinaryExpression(final Expression left,
- final Expression right,
- final int operator) {
- super(operator, left.sourceStart, right.sourceEnd);
- this.left = left;
- this.right = right;
- }
-
- public String toStringExpression() {
- final StringBuffer buff = new StringBuffer(left.toStringExpression());
- buff.append(operatorToString());
- buff.append(right.toStringExpression());
- return buff.toString();
- }
-
- /**
- * Get the variables from outside (parameters, globals ...)
- */
- public void getOutsideVariable(final List list) {
- }
-
- /**
- * get the modified variables.
- */
- public void getModifiedVariable(final List list) {
- left.getModifiedVariable(list);
- right.getModifiedVariable(list);
- }
-
- /**
- * Get the variables used.
- */
- public void getUsedVariable(final List list) {
- left.getUsedVariable(list);
- right.getUsedVariable(list);
- }
+ public Expression left, right;
+ public Constant optimizedBooleanConstant;
+
+ public BinaryExpression(Expression left, Expression right, int operator) {
+
+ this.left = left;
+ this.right = right;
+ this.bits |= operator << OperatorSHIFT; // encode operator
+ this.sourceStart = left.sourceStart;
+ this.sourceEnd = right.sourceEnd;
+ }
+
+ public FlowInfo analyseCode(BlockScope currentScope,
+ FlowContext flowContext, FlowInfo flowInfo) {
+
+ return right.analyseCode(
+ currentScope,
+ flowContext,
+ left.analyseCode(currentScope, flowContext, flowInfo)
+ .unconditionalInits()).unconditionalInits();
+ }
+
+ public void computeConstant(BlockScope scope, int leftId, int rightId) {
+
+ // compute the constant when valid
+ if ((this.left.constant != Constant.NotAConstant)
+ && (this.right.constant != Constant.NotAConstant)) {
+ try {
+ this.constant = Constant.computeConstantOperation(
+ this.left.constant, leftId,
+ (this.bits & OperatorMASK) >> OperatorSHIFT,
+ this.right.constant, rightId);
+ } catch (ArithmeticException e) {
+ this.constant = Constant.NotAConstant;
+ // 1.2 no longer throws an exception at compile-time
+ // scope.problemReporter().compileTimeConstantThrowsArithmeticException(this);
+ }
+ } else {
+ this.constant = Constant.NotAConstant;
+ // add some work for the boolean operators & |
+ // this.optimizedBooleanConstant(
+ // leftId,
+ // (this.bits & OperatorMASK) >> OperatorSHIFT,
+ // rightId);
+ }
+ }
+
+ public Constant optimizedBooleanConstant() {
+
+ return this.optimizedBooleanConstant == null ? this.constant
+ : this.optimizedBooleanConstant;
+ }
+
+ /**
+ * Code generation for a binary operation
+ */
+ // public void generateCode(
+ // BlockScope currentScope,
+ // CodeStream codeStream,
+ // boolean valueRequired) {
+ //
+ // int pc = codeStream.position;
+ // Label falseLabel, endLabel;
+ // if (constant != Constant.NotAConstant) {
+ // if (valueRequired)
+ // codeStream.generateConstant(constant, implicitConversion);
+ // codeStream.recordPositionsFrom(pc, this.sourceStart);
+ // return;
+ // }
+ // bits |= OnlyValueRequiredMASK;
+ // switch ((bits & OperatorMASK) >> OperatorSHIFT) {
+ // case PLUS :
+ // switch (bits & ReturnTypeIDMASK) {
+ // case T_String :
+ // codeStream.generateStringAppend(currentScope, left, right);
+ // if (!valueRequired)
+ // codeStream.pop();
+ // break;
+ // case T_int :
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired)
+ // codeStream.iadd();
+ // break;
+ // case T_long :
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired)
+ // codeStream.ladd();
+ // break;
+ // case T_double :
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired)
+ // codeStream.dadd();
+ // break;
+ // case T_float :
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired)
+ // codeStream.fadd();
+ // break;
+ // }
+ // break;
+ // case MINUS :
+ // switch (bits & ReturnTypeIDMASK) {
+ // case T_int :
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired)
+ // codeStream.isub();
+ // break;
+ // case T_long :
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired)
+ // codeStream.lsub();
+ // break;
+ // case T_double :
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired)
+ // codeStream.dsub();
+ // break;
+ // case T_float :
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired)
+ // codeStream.fsub();
+ // break;
+ // }
+ // break;
+ // case MULTIPLY :
+ // switch (bits & ReturnTypeIDMASK) {
+ // case T_int :
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired)
+ // codeStream.imul();
+ // break;
+ // case T_long :
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired)
+ // codeStream.lmul();
+ // break;
+ // case T_double :
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired)
+ // codeStream.dmul();
+ // break;
+ // case T_float :
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired)
+ // codeStream.fmul();
+ // break;
+ // }
+ // break;
+ // case DIVIDE :
+ // switch (bits & ReturnTypeIDMASK) {
+ // case T_int :
+ // left.generateCode(currentScope, codeStream, true);
+ // right.generateCode(currentScope, codeStream, true);
+ // codeStream.idiv();
+ // if (!valueRequired)
+ // codeStream.pop();
+ // break;
+ // case T_long :
+ // left.generateCode(currentScope, codeStream, true);
+ // right.generateCode(currentScope, codeStream, true);
+ // codeStream.ldiv();
+ // if (!valueRequired)
+ // codeStream.pop2();
+ // break;
+ // case T_double :
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired)
+ // codeStream.ddiv();
+ // break;
+ // case T_float :
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired)
+ // codeStream.fdiv();
+ // break;
+ // }
+ // break;
+ // case REMAINDER :
+ // switch (bits & ReturnTypeIDMASK) {
+ // case T_int :
+ // left.generateCode(currentScope, codeStream, true);
+ // right.generateCode(currentScope, codeStream, true);
+ // codeStream.irem();
+ // if (!valueRequired)
+ // codeStream.pop();
+ // break;
+ // case T_long :
+ // left.generateCode(currentScope, codeStream, true);
+ // right.generateCode(currentScope, codeStream, true);
+ // codeStream.lrem();
+ // if (!valueRequired)
+ // codeStream.pop2();
+ // break;
+ // case T_double :
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired)
+ // codeStream.drem();
+ // break;
+ // case T_float :
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired)
+ // codeStream.frem();
+ // break;
+ // }
+ // break;
+ // case AND :
+ // switch (bits & ReturnTypeIDMASK) {
+ // case T_int :
+ // // 0 & x
+ // if ((left.constant != Constant.NotAConstant)
+ // && (left.constant.typeID() == T_int)
+ // && (left.constant.intValue() == 0)) {
+ // right.generateCode(currentScope, codeStream, false);
+ // if (valueRequired)
+ // codeStream.iconst_0();
+ // } else {
+ // // x & 0
+ // if ((right.constant != Constant.NotAConstant)
+ // && (right.constant.typeID() == T_int)
+ // && (right.constant.intValue() == 0)) {
+ // left.generateCode(currentScope, codeStream, false);
+ // if (valueRequired)
+ // codeStream.iconst_0();
+ // } else {
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired)
+ // codeStream.iand();
+ // }
+ // }
+ // break;
+ // case T_long :
+ // // 0 & x
+ // if ((left.constant != Constant.NotAConstant)
+ // && (left.constant.typeID() == T_long)
+ // && (left.constant.longValue() == 0L)) {
+ // right.generateCode(currentScope, codeStream, false);
+ // if (valueRequired)
+ // codeStream.lconst_0();
+ // } else {
+ // // x & 0
+ // if ((right.constant != Constant.NotAConstant)
+ // && (right.constant.typeID() == T_long)
+ // && (right.constant.longValue() == 0L)) {
+ // left.generateCode(currentScope, codeStream, false);
+ // if (valueRequired)
+ // codeStream.lconst_0();
+ // } else {
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired)
+ // codeStream.land();
+ // }
+ // }
+ // break;
+ // case T_boolean : // logical and
+ // generateOptimizedLogicalAnd(
+ // currentScope,
+ // codeStream,
+ // null,
+ // (falseLabel = new Label(codeStream)),
+ // valueRequired);
+ // /* improving code gen for such a case: boolean b = i < 0 && false;
+ // * since the label has never been used, we have the inlined value on the
+ // stack. */
+ // if (falseLabel.hasForwardReferences()) {
+ // if (valueRequired) {
+ // codeStream.iconst_1();
+ // if ((bits & ValueForReturnMASK) != 0) {
+ // codeStream.ireturn();
+ // falseLabel.place();
+ // codeStream.iconst_0();
+ // } else {
+ // codeStream.goto_(endLabel = new Label(codeStream));
+ // codeStream.decrStackSize(1);
+ // falseLabel.place();
+ // codeStream.iconst_0();
+ // endLabel.place();
+ // }
+ // } else {
+ // falseLabel.place();
+ // }
+ // }
+ // }
+ // break;
+ // case OR :
+ // switch (bits & ReturnTypeIDMASK) {
+ // case T_int :
+ // // 0 | x
+ // if ((left.constant != Constant.NotAConstant)
+ // && (left.constant.typeID() == T_int)
+ // && (left.constant.intValue() == 0)) {
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // } else {
+ // // x | 0
+ // if ((right.constant != Constant.NotAConstant)
+ // && (right.constant.typeID() == T_int)
+ // && (right.constant.intValue() == 0)) {
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // } else {
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired)
+ // codeStream.ior();
+ // }
+ // }
+ // break;
+ // case T_long :
+ // // 0 | x
+ // if ((left.constant != Constant.NotAConstant)
+ // && (left.constant.typeID() == T_long)
+ // && (left.constant.longValue() == 0L)) {
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // } else {
+ // // x | 0
+ // if ((right.constant != Constant.NotAConstant)
+ // && (right.constant.typeID() == T_long)
+ // && (right.constant.longValue() == 0L)) {
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // } else {
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired)
+ // codeStream.lor();
+ // }
+ // }
+ // break;
+ // case T_boolean : // logical or
+ // generateOptimizedLogicalOr(
+ // currentScope,
+ // codeStream,
+ // null,
+ // (falseLabel = new Label(codeStream)),
+ // valueRequired);
+ // /* improving code gen for such a case: boolean b = i < 0 || true;
+ // * since the label has never been used, we have the inlined value on the
+ // stack. */
+ // if (falseLabel.hasForwardReferences()) {
+ // if (valueRequired) {
+ // codeStream.iconst_1();
+ // if ((bits & ValueForReturnMASK) != 0) {
+ // codeStream.ireturn();
+ // falseLabel.place();
+ // codeStream.iconst_0();
+ // } else {
+ // codeStream.goto_(endLabel = new Label(codeStream));
+ // codeStream.decrStackSize(1);
+ // falseLabel.place();
+ // codeStream.iconst_0();
+ // endLabel.place();
+ // }
+ // } else {
+ // falseLabel.place();
+ // }
+ // }
+ // }
+ // break;
+ // case XOR :
+ // switch (bits & ReturnTypeIDMASK) {
+ // case T_int :
+ // // 0 ^ x
+ // if ((left.constant != Constant.NotAConstant)
+ // && (left.constant.typeID() == T_int)
+ // && (left.constant.intValue() == 0)) {
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // } else {
+ // // x ^ 0
+ // if ((right.constant != Constant.NotAConstant)
+ // && (right.constant.typeID() == T_int)
+ // && (right.constant.intValue() == 0)) {
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // } else {
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired)
+ // codeStream.ixor();
+ // }
+ // }
+ // break;
+ // case T_long :
+ // // 0 ^ x
+ // if ((left.constant != Constant.NotAConstant)
+ // && (left.constant.typeID() == T_long)
+ // && (left.constant.longValue() == 0L)) {
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // } else {
+ // // x ^ 0
+ // if ((right.constant != Constant.NotAConstant)
+ // && (right.constant.typeID() == T_long)
+ // && (right.constant.longValue() == 0L)) {
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // } else {
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired)
+ // codeStream.lxor();
+ // }
+ // }
+ // break;
+ // case T_boolean :
+ // generateOptimizedLogicalXor(
+ // currentScope,
+ // codeStream,
+ // null,
+ // (falseLabel = new Label(codeStream)),
+ // valueRequired);
+ // /* improving code gen for such a case: boolean b = i < 0 ^ bool;
+ // * since the label has never been used, we have the inlined value on the
+ // stack. */
+ // if (falseLabel.hasForwardReferences()) {
+ // if (valueRequired) {
+ // codeStream.iconst_1();
+ // if ((bits & ValueForReturnMASK) != 0) {
+ // codeStream.ireturn();
+ // falseLabel.place();
+ // codeStream.iconst_0();
+ // } else {
+ // codeStream.goto_(endLabel = new Label(codeStream));
+ // codeStream.decrStackSize(1);
+ // falseLabel.place();
+ // codeStream.iconst_0();
+ // endLabel.place();
+ // }
+ // } else {
+ // falseLabel.place();
+ // }
+ // }
+ // }
+ // break;
+ // case LEFT_SHIFT :
+ // switch (bits & ReturnTypeIDMASK) {
+ // case T_int :
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired)
+ // codeStream.ishl();
+ // break;
+ // case T_long :
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired)
+ // codeStream.lshl();
+ // }
+ // break;
+ // case RIGHT_SHIFT :
+ // switch (bits & ReturnTypeIDMASK) {
+ // case T_int :
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired)
+ // codeStream.ishr();
+ // break;
+ // case T_long :
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired)
+ // codeStream.lshr();
+ // }
+ // break;
+ // case UNSIGNED_RIGHT_SHIFT :
+ // switch (bits & ReturnTypeIDMASK) {
+ // case T_int :
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired)
+ // codeStream.iushr();
+ // break;
+ // case T_long :
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired)
+ // codeStream.lushr();
+ // }
+ // break;
+ // case GREATER :
+ // generateOptimizedGreaterThan(
+ // currentScope,
+ // codeStream,
+ // null,
+ // (falseLabel = new Label(codeStream)),
+ // valueRequired);
+ // if (valueRequired) {
+ // codeStream.iconst_1();
+ // if ((bits & ValueForReturnMASK) != 0) {
+ // codeStream.ireturn();
+ // falseLabel.place();
+ // codeStream.iconst_0();
+ // } else {
+ // codeStream.goto_(endLabel = new Label(codeStream));
+ // codeStream.decrStackSize(1);
+ // falseLabel.place();
+ // codeStream.iconst_0();
+ // endLabel.place();
+ // }
+ // }
+ // break;
+ // case GREATER_EQUAL :
+ // generateOptimizedGreaterThanOrEqual(
+ // currentScope,
+ // codeStream,
+ // null,
+ // (falseLabel = new Label(codeStream)),
+ // valueRequired);
+ // if (valueRequired) {
+ // codeStream.iconst_1();
+ // if ((bits & ValueForReturnMASK) != 0) {
+ // codeStream.ireturn();
+ // falseLabel.place();
+ // codeStream.iconst_0();
+ // } else {
+ // codeStream.goto_(endLabel = new Label(codeStream));
+ // codeStream.decrStackSize(1);
+ // falseLabel.place();
+ // codeStream.iconst_0();
+ // endLabel.place();
+ // }
+ // }
+ // break;
+ // case LESS :
+ // generateOptimizedLessThan(
+ // currentScope,
+ // codeStream,
+ // null,
+ // (falseLabel = new Label(codeStream)),
+ // valueRequired);
+ // if (valueRequired) {
+ // codeStream.iconst_1();
+ // if ((bits & ValueForReturnMASK) != 0) {
+ // codeStream.ireturn();
+ // falseLabel.place();
+ // codeStream.iconst_0();
+ // } else {
+ // codeStream.goto_(endLabel = new Label(codeStream));
+ // codeStream.decrStackSize(1);
+ // falseLabel.place();
+ // codeStream.iconst_0();
+ // endLabel.place();
+ // }
+ // }
+ // break;
+ // case LESS_EQUAL :
+ // generateOptimizedLessThanOrEqual(
+ // currentScope,
+ // codeStream,
+ // null,
+ // (falseLabel = new Label(codeStream)),
+ // valueRequired);
+ // if (valueRequired) {
+ // codeStream.iconst_1();
+ // if ((bits & ValueForReturnMASK) != 0) {
+ // codeStream.ireturn();
+ // falseLabel.place();
+ // codeStream.iconst_0();
+ // } else {
+ // codeStream.goto_(endLabel = new Label(codeStream));
+ // codeStream.decrStackSize(1);
+ // falseLabel.place();
+ // codeStream.iconst_0();
+ // endLabel.place();
+ // }
+ // }
+ // }
+ // if (valueRequired) {
+ // codeStream.generateImplicitConversion(implicitConversion);
+ // }
+ // codeStream.recordPositionsFrom(pc, this.sourceStart);
+ // }
+ /**
+ * Boolean operator code generation Optimized operations are: <, <=, >, >=, &, |, ^
+ */
+ // public void generateOptimizedBoolean(
+ // BlockScope currentScope,
+ // CodeStream codeStream,
+ // Label trueLabel,
+ // Label falseLabel,
+ // boolean valueRequired) {
+ //
+ // if ((constant != Constant.NotAConstant) && (constant.typeID() ==
+ // T_boolean)) {
+ // super.generateOptimizedBoolean(
+ // currentScope,
+ // codeStream,
+ // trueLabel,
+ // falseLabel,
+ // valueRequired);
+ // return;
+ // }
+ // switch ((bits & OperatorMASK) >> OperatorSHIFT) {
+ // case LESS :
+ // generateOptimizedLessThan(
+ // currentScope,
+ // codeStream,
+ // trueLabel,
+ // falseLabel,
+ // valueRequired);
+ // return;
+ // case LESS_EQUAL :
+ // generateOptimizedLessThanOrEqual(
+ // currentScope,
+ // codeStream,
+ // trueLabel,
+ // falseLabel,
+ // valueRequired);
+ // return;
+ // case GREATER :
+ // generateOptimizedGreaterThan(
+ // currentScope,
+ // codeStream,
+ // trueLabel,
+ // falseLabel,
+ // valueRequired);
+ // return;
+ // case GREATER_EQUAL :
+ // generateOptimizedGreaterThanOrEqual(
+ // currentScope,
+ // codeStream,
+ // trueLabel,
+ // falseLabel,
+ // valueRequired);
+ // return;
+ // case AND :
+ // generateOptimizedLogicalAnd(
+ // currentScope,
+ // codeStream,
+ // trueLabel,
+ // falseLabel,
+ // valueRequired);
+ // return;
+ // case OR :
+ // generateOptimizedLogicalOr(
+ // currentScope,
+ // codeStream,
+ // trueLabel,
+ // falseLabel,
+ // valueRequired);
+ // return;
+ // case XOR :
+ // generateOptimizedLogicalXor(
+ // currentScope,
+ // codeStream,
+ // trueLabel,
+ // falseLabel,
+ // valueRequired);
+ // return;
+ // }
+ // super.generateOptimizedBoolean(
+ // currentScope,
+ // codeStream,
+ // trueLabel,
+ // falseLabel,
+ // valueRequired);
+ // }
+ //
+ // /**
+ // * Boolean generation for >
+ // */
+ // public void generateOptimizedGreaterThan(
+ // BlockScope currentScope,
+ // CodeStream codeStream,
+ // Label trueLabel,
+ // Label falseLabel,
+ // boolean valueRequired) {
+ //
+ // int promotedTypeID = left.implicitConversion >> 4;
+ // // both sides got promoted in the same way
+ // if (promotedTypeID == T_int) {
+ // // 0 > x
+ // if ((left.constant != NotAConstant) && (left.constant.intValue() == 0)) {
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired) {
+ // if (falseLabel == null) {
+ // if (trueLabel != null) {
+ // // implicitly falling through the FALSE case
+ // codeStream.iflt(trueLabel);
+ // }
+ // } else {
+ // if (trueLabel == null) {
+ // // implicitly falling through the TRUE case
+ // codeStream.ifge(falseLabel);
+ // } else {
+ // // no implicit fall through TRUE/FALSE --> should never occur
+ // }
+ // }
+ // }
+ // // reposition the endPC
+ // codeStream.updateLastRecordedEndPC(codeStream.position);
+ // return;
+ // }
+ // // x > 0
+ // if ((right.constant != NotAConstant) && (right.constant.intValue() == 0))
+ // {
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired) {
+ // if (falseLabel == null) {
+ // if (trueLabel != null) {
+ // // implicitly falling through the FALSE case
+ // codeStream.ifgt(trueLabel);
+ // }
+ // } else {
+ // if (trueLabel == null) {
+ // // implicitly falling through the TRUE case
+ // codeStream.ifle(falseLabel);
+ // } else {
+ // // no implicit fall through TRUE/FALSE --> should never occur
+ // }
+ // }
+ // }
+ // // reposition the endPC
+ // codeStream.updateLastRecordedEndPC(codeStream.position);
+ // return;
+ // }
+ // }
+ // // default comparison
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired) {
+ // if (falseLabel == null) {
+ // if (trueLabel != null) {
+ // // implicit falling through the FALSE case
+ // switch (promotedTypeID) {
+ // case T_int :
+ // codeStream.if_icmpgt(trueLabel);
+ // break;
+ // case T_float :
+ // codeStream.fcmpl();
+ // codeStream.ifgt(trueLabel);
+ // break;
+ // case T_long :
+ // codeStream.lcmp();
+ // codeStream.ifgt(trueLabel);
+ // break;
+ // case T_double :
+ // codeStream.dcmpl();
+ // codeStream.ifgt(trueLabel);
+ // }
+ // // reposition the endPC
+ // codeStream.updateLastRecordedEndPC(codeStream.position);
+ // return;
+ // }
+ // } else {
+ // if (trueLabel == null) {
+ // // implicit falling through the TRUE case
+ // switch (promotedTypeID) {
+ // case T_int :
+ // codeStream.if_icmple(falseLabel);
+ // break;
+ // case T_float :
+ // codeStream.fcmpl();
+ // codeStream.ifle(falseLabel);
+ // break;
+ // case T_long :
+ // codeStream.lcmp();
+ // codeStream.ifle(falseLabel);
+ // break;
+ // case T_double :
+ // codeStream.dcmpl();
+ // codeStream.ifle(falseLabel);
+ // }
+ // // reposition the endPC
+ // codeStream.updateLastRecordedEndPC(codeStream.position);
+ // return;
+ // } else {
+ // // no implicit fall through TRUE/FALSE --> should never occur
+ // }
+ // }
+ // }
+ // }
+ /**
+ * Boolean generation for >=
+ */
+ // public void generateOptimizedGreaterThanOrEqual(
+ // BlockScope currentScope,
+ // CodeStream codeStream,
+ // Label trueLabel,
+ // Label falseLabel,
+ // boolean valueRequired) {
+ //
+ // int promotedTypeID = left.implicitConversion >> 4;
+ // // both sides got promoted in the same way
+ // if (promotedTypeID == T_int) {
+ // // 0 >= x
+ // if ((left.constant != NotAConstant) && (left.constant.intValue() == 0)) {
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired) {
+ // if (falseLabel == null) {
+ // if (trueLabel != null) {
+ // // implicitly falling through the FALSE case
+ // codeStream.ifle(trueLabel);
+ // }
+ // } else {
+ // if (trueLabel == null) {
+ // // implicitly falling through the TRUE case
+ // codeStream.ifgt(falseLabel);
+ // } else {
+ // // no implicit fall through TRUE/FALSE --> should never occur
+ // }
+ // }
+ // }
+ // // reposition the endPC
+ // codeStream.updateLastRecordedEndPC(codeStream.position);
+ // return;
+ // }
+ // // x >= 0
+ // if ((right.constant != NotAConstant) && (right.constant.intValue() == 0))
+ // {
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired) {
+ // if (falseLabel == null) {
+ // if (trueLabel != null) {
+ // // implicitly falling through the FALSE case
+ // codeStream.ifge(trueLabel);
+ // }
+ // } else {
+ // if (trueLabel == null) {
+ // // implicitly falling through the TRUE case
+ // codeStream.iflt(falseLabel);
+ // } else {
+ // // no implicit fall through TRUE/FALSE --> should never occur
+ // }
+ // }
+ // }
+ // // reposition the endPC
+ // codeStream.updateLastRecordedEndPC(codeStream.position);
+ // return;
+ // }
+ // }
+ // // default comparison
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired) {
+ // if (falseLabel == null) {
+ // if (trueLabel != null) {
+ // // implicit falling through the FALSE case
+ // switch (promotedTypeID) {
+ // case T_int :
+ // codeStream.if_icmpge(trueLabel);
+ // break;
+ // case T_float :
+ // codeStream.fcmpl();
+ // codeStream.ifge(trueLabel);
+ // break;
+ // case T_long :
+ // codeStream.lcmp();
+ // codeStream.ifge(trueLabel);
+ // break;
+ // case T_double :
+ // codeStream.dcmpl();
+ // codeStream.ifge(trueLabel);
+ // }
+ // // reposition the endPC
+ // codeStream.updateLastRecordedEndPC(codeStream.position);
+ // return;
+ // }
+ // } else {
+ // if (trueLabel == null) {
+ // // implicit falling through the TRUE case
+ // switch (promotedTypeID) {
+ // case T_int :
+ // codeStream.if_icmplt(falseLabel);
+ // break;
+ // case T_float :
+ // codeStream.fcmpl();
+ // codeStream.iflt(falseLabel);
+ // break;
+ // case T_long :
+ // codeStream.lcmp();
+ // codeStream.iflt(falseLabel);
+ // break;
+ // case T_double :
+ // codeStream.dcmpl();
+ // codeStream.iflt(falseLabel);
+ // }
+ // // reposition the endPC
+ // codeStream.updateLastRecordedEndPC(codeStream.position);
+ // return;
+ // } else {
+ // // no implicit fall through TRUE/FALSE --> should never occur
+ // }
+ // }
+ // }
+ // }
+ //
+ // /**
+ // * Boolean generation for <
+ // */
+ // public void generateOptimizedLessThan(
+ // BlockScope currentScope,
+ // CodeStream codeStream,
+ // Label trueLabel,
+ // Label falseLabel,
+ // boolean valueRequired) {
+ //
+ // int promotedTypeID = left.implicitConversion >> 4;
+ // // both sides got promoted in the same way
+ // if (promotedTypeID == T_int) {
+ // // 0 < x
+ // if ((left.constant != NotAConstant) && (left.constant.intValue() == 0)) {
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired) {
+ // if (falseLabel == null) {
+ // if (trueLabel != null) {
+ // // implicitly falling through the FALSE case
+ // codeStream.ifgt(trueLabel);
+ // }
+ // } else {
+ // if (trueLabel == null) {
+ // // implicitly falling through the TRUE case
+ // codeStream.ifle(falseLabel);
+ // } else {
+ // // no implicit fall through TRUE/FALSE --> should never occur
+ // }
+ // }
+ // }
+ // codeStream.updateLastRecordedEndPC(codeStream.position);
+ // return;
+ // }
+ // // x < 0
+ // if ((right.constant != NotAConstant) && (right.constant.intValue() == 0))
+ // {
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired) {
+ // if (falseLabel == null) {
+ // if (trueLabel != null) {
+ // // implicitly falling through the FALSE case
+ // codeStream.iflt(trueLabel);
+ // }
+ // } else {
+ // if (trueLabel == null) {
+ // // implicitly falling through the TRUE case
+ // codeStream.ifge(falseLabel);
+ // } else {
+ // // no implicit fall through TRUE/FALSE --> should never occur
+ // }
+ // }
+ // }
+ // codeStream.updateLastRecordedEndPC(codeStream.position);
+ // return;
+ // }
+ // }
+ // // default comparison
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired) {
+ // if (falseLabel == null) {
+ // if (trueLabel != null) {
+ // // implicit falling through the FALSE case
+ // switch (promotedTypeID) {
+ // case T_int :
+ // codeStream.if_icmplt(trueLabel);
+ // break;
+ // case T_float :
+ // codeStream.fcmpg();
+ // codeStream.iflt(trueLabel);
+ // break;
+ // case T_long :
+ // codeStream.lcmp();
+ // codeStream.iflt(trueLabel);
+ // break;
+ // case T_double :
+ // codeStream.dcmpg();
+ // codeStream.iflt(trueLabel);
+ // }
+ // codeStream.updateLastRecordedEndPC(codeStream.position);
+ // return;
+ // }
+ // } else {
+ // if (trueLabel == null) {
+ // // implicit falling through the TRUE case
+ // switch (promotedTypeID) {
+ // case T_int :
+ // codeStream.if_icmpge(falseLabel);
+ // break;
+ // case T_float :
+ // codeStream.fcmpg();
+ // codeStream.ifge(falseLabel);
+ // break;
+ // case T_long :
+ // codeStream.lcmp();
+ // codeStream.ifge(falseLabel);
+ // break;
+ // case T_double :
+ // codeStream.dcmpg();
+ // codeStream.ifge(falseLabel);
+ // }
+ // codeStream.updateLastRecordedEndPC(codeStream.position);
+ // return;
+ // } else {
+ // // no implicit fall through TRUE/FALSE --> should never occur
+ // }
+ // }
+ // }
+ // }
+ //
+ // /**
+ // * Boolean generation for <=
+ // */
+ // public void generateOptimizedLessThanOrEqual(
+ // BlockScope currentScope,
+ // CodeStream codeStream,
+ // Label trueLabel,
+ // Label falseLabel,
+ // boolean valueRequired) {
+ //
+ // int promotedTypeID = left.implicitConversion >> 4;
+ // // both sides got promoted in the same way
+ // if (promotedTypeID == T_int) {
+ // // 0 <= x
+ // if ((left.constant != NotAConstant) && (left.constant.intValue() == 0)) {
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired) {
+ // if (falseLabel == null) {
+ // if (trueLabel != null) {
+ // // implicitly falling through the FALSE case
+ // codeStream.ifge(trueLabel);
+ // }
+ // } else {
+ // if (trueLabel == null) {
+ // // implicitly falling through the TRUE case
+ // codeStream.iflt(falseLabel);
+ // } else {
+ // // no implicit fall through TRUE/FALSE --> should never occur
+ // }
+ // }
+ // }
+ // // reposition the endPC
+ // codeStream.updateLastRecordedEndPC(codeStream.position);
+ // return;
+ // }
+ // // x <= 0
+ // if ((right.constant != NotAConstant) && (right.constant.intValue() == 0))
+ // {
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired) {
+ // if (falseLabel == null) {
+ // if (trueLabel != null) {
+ // // implicitly falling through the FALSE case
+ // codeStream.ifle(trueLabel);
+ // }
+ // } else {
+ // if (trueLabel == null) {
+ // // implicitly falling through the TRUE case
+ // codeStream.ifgt(falseLabel);
+ // } else {
+ // // no implicit fall through TRUE/FALSE --> should never occur
+ // }
+ // }
+ // }
+ // // reposition the endPC
+ // codeStream.updateLastRecordedEndPC(codeStream.position);
+ // return;
+ // }
+ // }
+ // // default comparison
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired) {
+ // if (falseLabel == null) {
+ // if (trueLabel != null) {
+ // // implicit falling through the FALSE case
+ // switch (promotedTypeID) {
+ // case T_int :
+ // codeStream.if_icmple(trueLabel);
+ // break;
+ // case T_float :
+ // codeStream.fcmpg();
+ // codeStream.ifle(trueLabel);
+ // break;
+ // case T_long :
+ // codeStream.lcmp();
+ // codeStream.ifle(trueLabel);
+ // break;
+ // case T_double :
+ // codeStream.dcmpg();
+ // codeStream.ifle(trueLabel);
+ // }
+ // // reposition the endPC
+ // codeStream.updateLastRecordedEndPC(codeStream.position);
+ // return;
+ // }
+ // } else {
+ // if (trueLabel == null) {
+ // // implicit falling through the TRUE case
+ // switch (promotedTypeID) {
+ // case T_int :
+ // codeStream.if_icmpgt(falseLabel);
+ // break;
+ // case T_float :
+ // codeStream.fcmpg();
+ // codeStream.ifgt(falseLabel);
+ // break;
+ // case T_long :
+ // codeStream.lcmp();
+ // codeStream.ifgt(falseLabel);
+ // break;
+ // case T_double :
+ // codeStream.dcmpg();
+ // codeStream.ifgt(falseLabel);
+ // }
+ // // reposition the endPC
+ // codeStream.updateLastRecordedEndPC(codeStream.position);
+ // return;
+ // } else {
+ // // no implicit fall through TRUE/FALSE --> should never occur
+ // }
+ // }
+ // }
+ // }
+ //
+ // /**
+ // * Boolean generation for &
+ // */
+ // public void generateOptimizedLogicalAnd(
+ // BlockScope currentScope,
+ // CodeStream codeStream,
+ // Label trueLabel,
+ // Label falseLabel,
+ // boolean valueRequired) {
+ //
+ // Constant condConst;
+ // if ((left.implicitConversion & 0xF) == T_boolean) {
+ // if ((condConst = left.optimizedBooleanConstant()) != NotAConstant) {
+ // if (condConst.booleanValue() == true) {
+ // // <something equivalent to true> & x
+ // left.generateOptimizedBoolean(
+ // currentScope,
+ // codeStream,
+ // trueLabel,
+ // falseLabel,
+ // false);
+ // if ((bits & OnlyValueRequiredMASK) != 0) {
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // } else {
+ // right.generateOptimizedBoolean(
+ // currentScope,
+ // codeStream,
+ // trueLabel,
+ // falseLabel,
+ // valueRequired);
+ // }
+ // } else {
+ // // <something equivalent to false> & x
+ // left.generateOptimizedBoolean(
+ // currentScope,
+ // codeStream,
+ // trueLabel,
+ // falseLabel,
+ // false);
+ // right.generateOptimizedBoolean(
+ // currentScope,
+ // codeStream,
+ // trueLabel,
+ // falseLabel,
+ // false);
+ // if (valueRequired) {
+ // if ((bits & OnlyValueRequiredMASK) != 0) {
+ // codeStream.iconst_0();
+ // } else {
+ // if (falseLabel != null) {
+ // // implicit falling through the TRUE case
+ // codeStream.goto_(falseLabel);
+ // }
+ // }
+ // }
+ // // reposition the endPC
+ // codeStream.updateLastRecordedEndPC(codeStream.position);
+ // }
+ // return;
+ // }
+ // if ((condConst = right.optimizedBooleanConstant()) != NotAConstant) {
+ // if (condConst.booleanValue() == true) {
+ // // x & <something equivalent to true>
+ // if ((bits & OnlyValueRequiredMASK) != 0) {
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // } else {
+ // left.generateOptimizedBoolean(
+ // currentScope,
+ // codeStream,
+ // trueLabel,
+ // falseLabel,
+ // valueRequired);
+ // }
+ // right.generateOptimizedBoolean(
+ // currentScope,
+ // codeStream,
+ // trueLabel,
+ // falseLabel,
+ // false);
+ // } else {
+ // // x & <something equivalent to false>
+ // left.generateOptimizedBoolean(
+ // currentScope,
+ // codeStream,
+ // trueLabel,
+ // falseLabel,
+ // false);
+ // right.generateOptimizedBoolean(
+ // currentScope,
+ // codeStream,
+ // trueLabel,
+ // falseLabel,
+ // false);
+ // if (valueRequired) {
+ // if ((bits & OnlyValueRequiredMASK) != 0) {
+ // codeStream.iconst_0();
+ // } else {
+ // if (falseLabel != null) {
+ // // implicit falling through the TRUE case
+ // codeStream.goto_(falseLabel);
+ // }
+ // }
+ // }
+ // // reposition the endPC
+ // codeStream.updateLastRecordedEndPC(codeStream.position);
+ // }
+ // return;
+ // }
+ // }
+ // // default case
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired) {
+ // codeStream.iand();
+ // if ((bits & OnlyValueRequiredMASK) == 0) {
+ // if (falseLabel == null) {
+ // if (trueLabel != null) {
+ // // implicit falling through the FALSE case
+ // codeStream.ifne(trueLabel);
+ // }
+ // } else {
+ // // implicit falling through the TRUE case
+ // if (trueLabel == null) {
+ // codeStream.ifeq(falseLabel);
+ // } else {
+ // // no implicit fall through TRUE/FALSE --> should never occur
+ // }
+ // }
+ // }
+ // }
+ // // reposition the endPC
+ // codeStream.updateLastRecordedEndPC(codeStream.position);
+ // }
+ //
+ // /**
+ // * Boolean generation for |
+ // */
+ // public void generateOptimizedLogicalOr(
+ // BlockScope currentScope,
+ // CodeStream codeStream,
+ // Label trueLabel,
+ // Label falseLabel,
+ // boolean valueRequired) {
+ //
+ // Constant condConst;
+ // if ((left.implicitConversion & 0xF) == T_boolean) {
+ // if ((condConst = left.optimizedBooleanConstant()) != NotAConstant) {
+ // if (condConst.booleanValue() == true) {
+ // // <something equivalent to true> | x
+ // left.generateOptimizedBoolean(
+ // currentScope,
+ // codeStream,
+ // trueLabel,
+ // falseLabel,
+ // false);
+ // right.generateOptimizedBoolean(
+ // currentScope,
+ // codeStream,
+ // trueLabel,
+ // falseLabel,
+ // false);
+ // if (valueRequired) {
+ // if ((bits & OnlyValueRequiredMASK) != 0) {
+ // codeStream.iconst_1();
+ // } else {
+ // if (trueLabel != null) {
+ // codeStream.goto_(trueLabel);
+ // }
+ // }
+ // }
+ // // reposition the endPC
+ // codeStream.updateLastRecordedEndPC(codeStream.position);
+ // } else {
+ // // <something equivalent to false> | x
+ // left.generateOptimizedBoolean(
+ // currentScope,
+ // codeStream,
+ // trueLabel,
+ // falseLabel,
+ // false);
+ // if ((bits & OnlyValueRequiredMASK) != 0) {
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // } else {
+ // right.generateOptimizedBoolean(
+ // currentScope,
+ // codeStream,
+ // trueLabel,
+ // falseLabel,
+ // valueRequired);
+ // }
+ // }
+ // return;
+ // }
+ // if ((condConst = right.optimizedBooleanConstant()) != NotAConstant) {
+ // if (condConst.booleanValue() == true) {
+ // // x | <something equivalent to true>
+ // left.generateOptimizedBoolean(
+ // currentScope,
+ // codeStream,
+ // trueLabel,
+ // falseLabel,
+ // false);
+ // right.generateOptimizedBoolean(
+ // currentScope,
+ // codeStream,
+ // trueLabel,
+ // falseLabel,
+ // false);
+ // if (valueRequired) {
+ // if ((bits & OnlyValueRequiredMASK) != 0) {
+ // codeStream.iconst_1();
+ // } else {
+ // if (trueLabel != null) {
+ // codeStream.goto_(trueLabel);
+ // }
+ // }
+ // }
+ // // reposition the endPC
+ // codeStream.updateLastRecordedEndPC(codeStream.position);
+ // } else {
+ // // x | <something equivalent to false>
+ // if ((bits & OnlyValueRequiredMASK) != 0) {
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // } else {
+ // left.generateOptimizedBoolean(
+ // currentScope,
+ // codeStream,
+ // trueLabel,
+ // falseLabel,
+ // valueRequired);
+ // }
+ // right.generateOptimizedBoolean(
+ // currentScope,
+ // codeStream,
+ // trueLabel,
+ // falseLabel,
+ // false);
+ // }
+ // return;
+ // }
+ // }
+ // // default case
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired) {
+ // codeStream.ior();
+ // if ((bits & OnlyValueRequiredMASK) == 0) {
+ // if (falseLabel == null) {
+ // if (trueLabel != null) {
+ // // implicit falling through the FALSE case
+ // codeStream.ifne(trueLabel);
+ // }
+ // } else {
+ // // implicit falling through the TRUE case
+ // if (trueLabel == null) {
+ // codeStream.ifeq(falseLabel);
+ // } else {
+ // // no implicit fall through TRUE/FALSE --> should never occur
+ // }
+ // }
+ // }
+ // }
+ // // reposition the endPC
+ // codeStream.updateLastRecordedEndPC(codeStream.position);
+ // }
+ //
+ // /**
+ // * Boolean generation for ^
+ // */
+ // public void generateOptimizedLogicalXor(
+ // BlockScope currentScope,
+ // CodeStream codeStream,
+ // Label trueLabel,
+ // Label falseLabel,
+ // boolean valueRequired) {
+ //
+ // Constant condConst;
+ // if ((left.implicitConversion & 0xF) == T_boolean) {
+ // if ((condConst = left.optimizedBooleanConstant()) != NotAConstant) {
+ // if (condConst.booleanValue() == true) {
+ // // <something equivalent to true> ^ x
+ // left.generateOptimizedBoolean(
+ // currentScope,
+ // codeStream,
+ // trueLabel,
+ // falseLabel,
+ // false);
+ // right.generateOptimizedBoolean(
+ // currentScope,
+ // codeStream,
+ // falseLabel,
+ // trueLabel,
+ // valueRequired);
+ // } else {
+ // // <something equivalent to false> ^ x
+ // left.generateOptimizedBoolean(
+ // currentScope,
+ // codeStream,
+ // trueLabel,
+ // falseLabel,
+ // false);
+ // if ((bits & OnlyValueRequiredMASK) != 0) {
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // } else {
+ // right.generateOptimizedBoolean(
+ // currentScope,
+ // codeStream,
+ // trueLabel,
+ // falseLabel,
+ // valueRequired);
+ // }
+ // }
+ // return;
+ // }
+ // if ((condConst = right.optimizedBooleanConstant()) != NotAConstant) {
+ // if (condConst.booleanValue() == true) {
+ // // x ^ <something equivalent to true>
+ // left.generateOptimizedBoolean(
+ // currentScope,
+ // codeStream,
+ // falseLabel,
+ // trueLabel,
+ // valueRequired);
+ // right.generateOptimizedBoolean(
+ // currentScope,
+ // codeStream,
+ // trueLabel,
+ // falseLabel,
+ // false);
+ // } else {
+ // // x ^ <something equivalent to false>
+ // if ((bits & OnlyValueRequiredMASK) != 0) {
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // } else {
+ // left.generateOptimizedBoolean(
+ // currentScope,
+ // codeStream,
+ // trueLabel,
+ // falseLabel,
+ // valueRequired);
+ // }
+ // right.generateOptimizedBoolean(
+ // currentScope,
+ // codeStream,
+ // trueLabel,
+ // falseLabel,
+ // false);
+ // }
+ // return;
+ // }
+ // }
+ // // default case
+ // left.generateCode(currentScope, codeStream, valueRequired);
+ // right.generateCode(currentScope, codeStream, valueRequired);
+ // if (valueRequired) {
+ // codeStream.ixor();
+ // if ((bits & OnlyValueRequiredMASK) == 0) {
+ // if (falseLabel == null) {
+ // if (trueLabel != null) {
+ // // implicit falling through the FALSE case
+ // codeStream.ifne(trueLabel);
+ // }
+ // } else {
+ // // implicit falling through the TRUE case
+ // if (trueLabel == null) {
+ // codeStream.ifeq(falseLabel);
+ // } else {
+ // // no implicit fall through TRUE/FALSE --> should never occur
+ // }
+ // }
+ // }
+ // }
+ // // reposition the endPC
+ // codeStream.updateLastRecordedEndPC(codeStream.position);
+ // }
+ //
+ // public void generateOptimizedStringBuffer(
+ // BlockScope blockScope,
+ // CodeStream codeStream,
+ // int typeID) {
+ //
+ // /* In the case trying to make a string concatenation, there is no need to
+ // create a new
+ // * string buffer, thus use a lower-level API for code generation involving
+ // only the
+ // * appending of arguments to the existing StringBuffer
+ // */
+ //
+ // if ((((bits & OperatorMASK) >> OperatorSHIFT) == PLUS)
+ // && ((bits & ReturnTypeIDMASK) == T_String)) {
+ // if (constant != NotAConstant) {
+ // codeStream.generateConstant(constant, implicitConversion);
+ // codeStream.invokeStringBufferAppendForType(implicitConversion & 0xF);
+ // } else {
+ // int pc = codeStream.position;
+ // left.generateOptimizedStringBuffer(
+ // blockScope,
+ // codeStream,
+ // left.implicitConversion & 0xF);
+ // codeStream.recordPositionsFrom(pc, left.sourceStart);
+ // pc = codeStream.position;
+ // right.generateOptimizedStringBuffer(
+ // blockScope,
+ // codeStream,
+ // right.implicitConversion & 0xF);
+ // codeStream.recordPositionsFrom(pc, right.sourceStart);
+ // }
+ // } else {
+ // super.generateOptimizedStringBuffer(blockScope, codeStream, typeID);
+ // }
+ // }
+ //
+ // public void generateOptimizedStringBufferCreation(
+ // BlockScope blockScope,
+ // CodeStream codeStream,
+ // int typeID) {
+ //
+ // /* In the case trying to make a string concatenation, there is no need to
+ // create a new
+ // * string buffer, thus use a lower-level API for code generation involving
+ // only the
+ // * appending of arguments to the existing StringBuffer
+ // */
+ //
+ // if ((((bits & OperatorMASK) >> OperatorSHIFT) == PLUS)
+ // && ((bits & ReturnTypeIDMASK) == T_String)) {
+ // if (constant != NotAConstant) {
+ // codeStream.newStringBuffer(); // new: java.lang.StringBuffer
+ // codeStream.dup();
+ // codeStream.ldc(constant.stringValue());
+ // codeStream.invokeStringBufferStringConstructor();
+ // // invokespecial: java.lang.StringBuffer.<init>(Ljava.lang.String;)V
+ // } else {
+ // int pc = codeStream.position;
+ // left.generateOptimizedStringBufferCreation(
+ // blockScope,
+ // codeStream,
+ // left.implicitConversion & 0xF);
+ // codeStream.recordPositionsFrom(pc, left.sourceStart);
+ // pc = codeStream.position;
+ // right.generateOptimizedStringBuffer(
+ // blockScope,
+ // codeStream,
+ // right.implicitConversion & 0xF);
+ // codeStream.recordPositionsFrom(pc, right.sourceStart);
+ // }
+ // } else {
+ // super.generateOptimizedStringBufferCreation(blockScope, codeStream,
+ // typeID);
+ // }
+ // }
+ //
+ // public boolean isCompactableOperation() {
+ //
+ // return true;
+ // }
+ //
+ // public void optimizedBooleanConstant(int leftId, int operator, int
+ // rightId) {
+ //
+ // switch (operator) {
+ // case AND :
+ // if ((leftId != T_boolean) || (rightId != T_boolean))
+ // return;
+ // case AND_AND :
+ // Constant cst;
+ // if ((cst = left.optimizedBooleanConstant()) != NotAConstant) {
+ // if (cst.booleanValue() == false) { // left is equivalent to false
+ // optimizedBooleanConstant = cst; // constant(false)
+ // return;
+ // } else { //left is equivalent to true
+ // if ((cst = right.optimizedBooleanConstant()) != NotAConstant) {
+ // optimizedBooleanConstant = cst;
+ // // the conditional result is equivalent to the right conditional value
+ // }
+ // return;
+ // }
+ // }
+ // if ((cst = right.optimizedBooleanConstant()) != NotAConstant) {
+ // if (cst.booleanValue() == false) { // right is equivalent to false
+ // optimizedBooleanConstant = cst; // constant(false)
+ // }
+ // }
+ // return;
+ // case OR :
+ // if ((leftId != T_boolean) || (rightId != T_boolean))
+ // return;
+ // case OR_OR :
+ // if ((cst = left.optimizedBooleanConstant()) != NotAConstant) {
+ // if (cst.booleanValue() == true) { // left is equivalent to true
+ // optimizedBooleanConstant = cst; // constant(true)
+ // return;
+ // } else { //left is equivalent to false
+ // if ((cst = right.optimizedBooleanConstant()) != NotAConstant) {
+ // optimizedBooleanConstant = cst;
+ // }
+ // return;
+ // }
+ // }
+ // if ((cst = right.optimizedBooleanConstant()) != NotAConstant) {
+ // if (cst.booleanValue() == true) { // right is equivalent to true
+ // optimizedBooleanConstant = cst; // constant(true)
+ // }
+ // }
+ // }
+ // }
+ public StringBuffer printExpressionNoParenthesis(int indent,
+ StringBuffer output) {
+
+ left.printExpression(indent, output).append(' ').append(
+ operatorToString()).append(' ');
+ return right.printExpression(0, output);
+ }
+
+ public TypeBinding resolveType(BlockScope scope) {
+
+ // use the id of the type to navigate into the table
+ TypeBinding leftTb = left.resolveType(scope);
+ TypeBinding rightTb = right.resolveType(scope);
+ if (leftTb == null || rightTb == null) {
+ constant = Constant.NotAConstant;
+ return null;
+ }
+ int leftId = leftTb.id;
+ int rightId = rightTb.id;
+ if (leftId > 15 || rightId > 15) { // must convert String + Object ||
+ // Object + String
+ if (leftId == T_String) {
+ rightId = T_Object;
+ } else if (rightId == T_String) {
+ leftId = T_Object;
+ } else {
+ constant = Constant.NotAConstant;
+ scope.problemReporter().invalidOperator(this, leftTb, rightTb);
+ return null;
+ }
+ }
+ if (((bits & OperatorMASK) >> OperatorSHIFT) == PLUS) {
+ if (leftId == T_String
+ && rightTb.isArrayType()
+ && ((ArrayBinding) rightTb).elementsType(scope) == CharBinding)
+ scope
+ .problemReporter()
+ .signalNoImplicitStringConversionForCharArrayExpression(
+ right);
+ else if (rightId == T_String
+ && leftTb.isArrayType()
+ && ((ArrayBinding) leftTb).elementsType(scope) == CharBinding)
+ scope
+ .problemReporter()
+ .signalNoImplicitStringConversionForCharArrayExpression(
+ left);
+ }
+
+ // the code is an int
+ // (cast) left Op (cast) rigth --> result
+ // 0000 0000 0000 0000 0000
+ // <<16 <<12 <<8 <<4 <<0
+
+ // Don't test for result = 0. If it is zero, some more work is done.
+ // On the one hand when it is not zero (correct code) we avoid doing the
+ // test
+ int result = ResolveTypeTables[(bits & OperatorMASK) >> OperatorSHIFT][(leftId << 4)
+ + rightId];
+ left.implicitConversion = result >>> 12;
+ right.implicitConversion = (result >>> 4) & 0x000FF;
+
+ bits |= result & 0xF;
+ switch (result & 0xF) { // record the current ReturnTypeID
+ // only switch on possible result type.....
+ case T_boolean:
+ this.resolvedType = BooleanBinding;
+ break;
+ case T_byte:
+ this.resolvedType = ByteBinding;
+ break;
+ case T_char:
+ this.resolvedType = CharBinding;
+ break;
+ case T_double:
+ this.resolvedType = DoubleBinding;
+ break;
+ case T_float:
+ this.resolvedType = FloatBinding;
+ break;
+ case T_int:
+ this.resolvedType = IntBinding;
+ break;
+ case T_long:
+ this.resolvedType = LongBinding;
+ break;
+ case T_String:
+ this.resolvedType = scope.getJavaLangString();
+ break;
+ default: // error........
+ constant = Constant.NotAConstant;
+ scope.problemReporter().invalidOperator(this, leftTb, rightTb);
+ return null;
+ }
+
+ // compute the constant when valid
+ computeConstant(scope, leftId, rightId);
+ return this.resolvedType;
+ }
+
+ public String toStringExpressionNoParenthesis() {
+
+ return left.toStringExpression() + " " + //$NON-NLS-1$
+ operatorToString() + " " + //$NON-NLS-1$
+ right.toStringExpression();
+ }
+
+ public void traverse(ASTVisitor visitor, BlockScope scope) {
+
+ if (visitor.visit(this, scope)) {
+ left.traverse(visitor, scope);
+ right.traverse(visitor, scope);
+ }
+ visitor.endVisit(this, scope);
+ }
}