X-Git-Url: http://secure.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/BinaryExpression.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/BinaryExpression.java index 7488cb8..ce506cb 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/BinaryExpression.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/BinaryExpression.java @@ -1,70 +1,1754 @@ +/******************************************************************************* + * 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 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; -/** - * a binary expression is a combination of two expressions with an operator. - * - * @author Matthieu Casanova - */ -public final class BinaryExpression extends OperatorExpression { - - /** The left expression. */ - private final Expression left; - /** The right expression. */ - private final Expression right; - - /** - * Create a binary expression. - * - * @param left the left expression - * @param right the right expression - * @param operator an operator taken in the {@link OperatorExpression} interface - */ - 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 String leftString = left.toStringExpression(); - final String operatorString = operatorToString(); - final String rightString = right.toStringExpression(); - final StringBuffer buff = new StringBuffer(leftString.length() + operatorString.length() + rightString.length()); - buff.append(leftString); - buff.append(operatorString); - buff.append(rightString); - return buff.toString(); - } - - /** - * Get the variables from outside (parameters, globals ...) - * - * @param list the list where we will put variables - */ - public void getOutsideVariable(final List list) {} - - /** - * get the modified variables. - * - * @param list the list where we will put variables - */ - public void getModifiedVariable(final List list) { - left.getModifiedVariable(list); - right.getModifiedVariable(list); - } - - /** - * Get the variables used. - * - * @param list the list where we will put variables - */ - public void getUsedVariable(final List list) { - left.getUsedVariable(list); - right.getUsedVariable(list); - } +public class BinaryExpression extends OperatorExpression { + + 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) { +// // & 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 { +// // & 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 & +// 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 & +// 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) { +// // | 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 { +// // | 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 | +// 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 | +// 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) { +// // ^ x +// left.generateOptimizedBoolean( +// currentScope, +// codeStream, +// trueLabel, +// falseLabel, +// false); +// right.generateOptimizedBoolean( +// currentScope, +// codeStream, +// falseLabel, +// trueLabel, +// valueRequired); +// } else { +// // ^ 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 ^ +// left.generateOptimizedBoolean( +// currentScope, +// codeStream, +// falseLabel, +// trueLabel, +// valueRequired); +// right.generateOptimizedBoolean( +// currentScope, +// codeStream, +// trueLabel, +// falseLabel, +// false); +// } else { +// // x ^ +// 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.(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); + } }