X-Git-Url: http://git.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/EqualExpression.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/EqualExpression.java index 3788b65..be26c14 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/EqualExpression.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/EqualExpression.java @@ -10,6 +10,7 @@ *******************************************************************************/ package net.sourceforge.phpdt.internal.compiler.ast; +import net.sourceforge.phpdt.core.compiler.ITerminalSymbols.TokenName; import net.sourceforge.phpdt.internal.compiler.ASTVisitor; import net.sourceforge.phpdt.internal.compiler.flow.FlowContext; import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo; @@ -23,538 +24,614 @@ import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding; public class EqualExpression extends BinaryExpression { -public EqualExpression(Expression left, Expression right,int operator) { - super(left,right,operator); -} -public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { - if (((bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) { - if ((left.constant != NotAConstant) && (left.constant.typeID() == T_boolean)) { - if (left.constant.booleanValue()) { // true == anything - // this is equivalent to the right argument inits - return right.analyseCode(currentScope, flowContext, flowInfo); - } else { // false == anything - // this is equivalent to the right argument inits negated - return right.analyseCode(currentScope, flowContext, flowInfo).asNegatedCondition(); + public EqualExpression(Expression left, Expression right, int operator) { + super (left, right, operator); + } + + public FlowInfo analyseCode(BlockScope currentScope, + FlowContext flowContext, FlowInfo flowInfo) { + if (((bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) { + if ((left.constant != NotAConstant) + && (left.constant.typeID() == T_boolean)) { + if (left.constant.booleanValue()) { // true == anything + // this is equivalent to the right argument inits + return right.analyseCode(currentScope, flowContext, + flowInfo); + } else { // false == anything + // this is equivalent to the right argument inits negated + return right.analyseCode(currentScope, flowContext, + flowInfo).asNegatedCondition(); + } } - } - if ((right.constant != NotAConstant) && (right.constant.typeID() == T_boolean)) { - if (right.constant.booleanValue()) { // anything == true - // this is equivalent to the right argument inits - return left.analyseCode(currentScope, flowContext, flowInfo); - } else { // anything == false - // this is equivalent to the right argument inits negated - return left.analyseCode(currentScope, flowContext, flowInfo).asNegatedCondition(); + if ((right.constant != NotAConstant) + && (right.constant.typeID() == T_boolean)) { + if (right.constant.booleanValue()) { // anything == true + // this is equivalent to the right argument inits + return left + .analyseCode(currentScope, flowContext, flowInfo); + } else { // anything == false + // this is equivalent to the right argument inits negated + return left + .analyseCode(currentScope, flowContext, flowInfo) + .asNegatedCondition(); + } } - } - return right.analyseCode( - currentScope, flowContext, - left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits()).unconditionalInits(); - } else { //NOT_EQUAL : - if ((left.constant != NotAConstant) && (left.constant.typeID() == T_boolean)) { - if (!left.constant.booleanValue()) { // false != anything - // this is equivalent to the right argument inits - return right.analyseCode(currentScope, flowContext, flowInfo); - } else { // true != anything - // this is equivalent to the right argument inits negated - return right.analyseCode(currentScope, flowContext, flowInfo).asNegatedCondition(); + return right.analyseCode( + currentScope, + flowContext, + left.analyseCode(currentScope, flowContext, flowInfo) + .unconditionalInits()).unconditionalInits(); + } else { // NOT_EQUAL : + if ((left.constant != NotAConstant) + && (left.constant.typeID() == T_boolean)) { + if (!left.constant.booleanValue()) { // false != anything + // this is equivalent to the right argument inits + return right.analyseCode(currentScope, flowContext, + flowInfo); + } else { // true != anything + // this is equivalent to the right argument inits negated + return right.analyseCode(currentScope, flowContext, + flowInfo).asNegatedCondition(); + } } - } - if ((right.constant != NotAConstant) && (right.constant.typeID() == T_boolean)) { - if (!right.constant.booleanValue()) { // anything != false - // this is equivalent to the right argument inits - return left.analyseCode(currentScope, flowContext, flowInfo); - } else { // anything != true - // this is equivalent to the right argument inits negated - return left.analyseCode(currentScope, flowContext, flowInfo).asNegatedCondition(); + if ((right.constant != NotAConstant) + && (right.constant.typeID() == T_boolean)) { + if (!right.constant.booleanValue()) { // anything != false + // this is equivalent to the right argument inits + return left + .analyseCode(currentScope, flowContext, flowInfo); + } else { // anything != true + // this is equivalent to the right argument inits negated + return left + .analyseCode(currentScope, flowContext, flowInfo) + .asNegatedCondition(); + } } + return right.analyseCode( + currentScope, + flowContext, + left.analyseCode(currentScope, flowContext, flowInfo) + .unconditionalInits()).asNegatedCondition() + .unconditionalInits(); } - return right.analyseCode( - currentScope, flowContext, - left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits()).asNegatedCondition().unconditionalInits(); } -} -public final boolean areTypesCastCompatible(BlockScope scope, TypeBinding castType, TypeBinding expressionType) { - //see specifications 5.5 - //A more complete version of this method is provided on - //CastExpression (it deals with constant and need runtime checkcast) - if (castType == expressionType) return true; + public final boolean areTypesCastCompatible(BlockScope scope, + TypeBinding castType, TypeBinding expressionType) { + // see specifications 5.5 + // A more complete version of this method is provided on + // CastExpression (it deals with constant and need runtime checkcast) - //========ARRAY=============== - if (expressionType.isArrayType()) { - if (castType.isArrayType()) { //------- (castTb.isArray) expressionTb.isArray ----------- - TypeBinding expressionEltType = ((ArrayBinding) expressionType).elementsType(scope); - if (expressionEltType.isBaseType()) - // <---stop the recursion------- - return ((ArrayBinding) castType).elementsType(scope) == expressionEltType; - //recursivly on the elts... - return areTypesCastCompatible(scope, ((ArrayBinding) castType).elementsType(scope), expressionEltType); - } - if (castType.isBaseType()) { - return false; - } - if (castType.isClass()) { //------(castTb.isClass) expressionTb.isArray --------------- - if (scope.isJavaLangObject(castType)) - return true; - return false; - } - if (castType.isInterface()) { //------- (castTb.isInterface) expressionTb.isArray ----------- - if (scope.isJavaLangCloneable(castType) || scope.isJavaIoSerializable(castType)) { - return true; + if (castType == expressionType) + return true; + + // ========ARRAY=============== + if (expressionType.isArrayType()) { + if (castType.isArrayType()) { // ------- (castTb.isArray) + // expressionTb.isArray ----------- + TypeBinding expressionEltType = ((ArrayBinding) expressionType) + .elementsType(scope); + if (expressionEltType.isBaseType()) + // <---stop the recursion------- + return ((ArrayBinding) castType).elementsType(scope) == expressionEltType; + // recursivly on the elts... + return areTypesCastCompatible(scope, ((ArrayBinding) castType) + .elementsType(scope), expressionEltType); + } + if (castType.isBaseType()) { + return false; + } + if (castType.isClass()) { // ------(castTb.isClass) + // expressionTb.isArray --------------- + if (scope.isJavaLangObject(castType)) + return true; + return false; } + if (castType.isInterface()) { // ------- (castTb.isInterface) + // expressionTb.isArray ----------- + if (scope.isJavaLangCloneable(castType) + || scope.isJavaIoSerializable(castType)) { + return true; + } + return false; + } + return false; } - return false; - } - - //------------(castType) null-------------- - if (expressionType == NullBinding) { - return !castType.isBaseType(); - } - - //========BASETYPE============== - if (expressionType.isBaseType()) { - return false; - } - - - //========REFERENCE TYPE=================== - - if (expressionType.isClass()) { - if (castType.isArrayType()) { // ---- (castTb.isArray) expressionTb.isClass ------- - if (scope.isJavaLangObject(expressionType)) - return true; + // ------------(castType) null-------------- + if (expressionType == NullBinding) { + return !castType.isBaseType(); } - if (castType.isBaseType()) { + + // ========BASETYPE============== + if (expressionType.isBaseType()) { return false; } - if (castType.isClass()) { // ----- (castTb.isClass) expressionTb.isClass ------ - if (expressionType.isCompatibleWith(castType)) - return true; - else { - if (castType.isCompatibleWith(expressionType)) { + + // ========REFERENCE TYPE=================== + + if (expressionType.isClass()) { + if (castType.isArrayType()) { // ---- (castTb.isArray) + // expressionTb.isClass ------- + if (scope.isJavaLangObject(expressionType)) return true; - } + } + if (castType.isBaseType()) { return false; } - } - if (castType.isInterface()) { // ----- (castTb.isInterface) expressionTb.isClass ------- - if (((ReferenceBinding) expressionType).isFinal()) { //no subclass for expressionTb, thus compile-time check is valid + if (castType.isClass()) { // ----- (castTb.isClass) + // expressionTb.isClass ------ if (expressionType.isCompatibleWith(castType)) return true; - return false; - } else { - return true; + else { + if (castType.isCompatibleWith(expressionType)) { + return true; + } + return false; + } } - } - - return false; - } - if (expressionType.isInterface()) { - if (castType.isArrayType()) { // ----- (castTb.isArray) expressionTb.isInterface ------ - if (scope.isJavaLangCloneable(expressionType) || scope.isJavaIoSerializable(expressionType)) - //potential runtime error - { - return true; + if (castType.isInterface()) { // ----- (castTb.isInterface) + // expressionTb.isClass ------- + if (((ReferenceBinding) expressionType).isFinal()) { // no + // subclass + // for + // expressionTb, + // thus + // compile-time + // check + // is + // valid + if (expressionType.isCompatibleWith(castType)) + return true; + return false; + } else { + return true; + } } + return false; } - if (castType.isBaseType()) { - return false; - } - if (castType.isClass()) { // ----- (castTb.isClass) expressionTb.isInterface -------- - if (scope.isJavaLangObject(castType)) - return true; - if (((ReferenceBinding) castType).isFinal()) { //no subclass for castTb, thus compile-time check is valid - if (castType.isCompatibleWith(expressionType)) { + if (expressionType.isInterface()) { + if (castType.isArrayType()) { // ----- (castTb.isArray) + // expressionTb.isInterface ------ + if (scope.isJavaLangCloneable(expressionType) + || scope.isJavaIoSerializable(expressionType)) + // potential runtime error + { return true; } return false; } - return true; - } - if (castType.isInterface()) { // ----- (castTb.isInterface) expressionTb.isInterface ------- - if (Scope.compareTypes(castType, expressionType) == NotRelated) { - MethodBinding[] castTbMethods = ((ReferenceBinding) castType).methods(); - int castTbMethodsLength = castTbMethods.length; - MethodBinding[] expressionTbMethods = ((ReferenceBinding) expressionType).methods(); - int expressionTbMethodsLength = expressionTbMethods.length; - for (int i = 0; i < castTbMethodsLength; i++) { - for (int j = 0; j < expressionTbMethodsLength; j++) { - if (castTbMethods[i].selector == expressionTbMethods[j].selector) { - if (castTbMethods[i].returnType != expressionTbMethods[j].returnType) { - if (castTbMethods[i].areParametersEqual(expressionTbMethods[j])) { - return false; + if (castType.isBaseType()) { + return false; + } + if (castType.isClass()) { // ----- (castTb.isClass) + // expressionTb.isInterface -------- + if (scope.isJavaLangObject(castType)) + return true; + if (((ReferenceBinding) castType).isFinal()) { // no subclass + // for castTb, + // thus + // compile-time + // check is + // valid + if (castType.isCompatibleWith(expressionType)) { + return true; + } + return false; + } + return true; + } + if (castType.isInterface()) { // ----- (castTb.isInterface) + // expressionTb.isInterface ------- + if (Scope.compareTypes(castType, expressionType) == NotRelated) { + MethodBinding[] castTbMethods = ((ReferenceBinding) castType) + .methods(); + int castTbMethodsLength = castTbMethods.length; + MethodBinding[] expressionTbMethods = ((ReferenceBinding) expressionType) + .methods(); + int expressionTbMethodsLength = expressionTbMethods.length; + for (int i = 0; i < castTbMethodsLength; i++) { + for (int j = 0; j < expressionTbMethodsLength; j++) { + if (castTbMethods[i].selector == expressionTbMethods[j].selector) { + if (castTbMethods[i].returnType != expressionTbMethods[j].returnType) { + if (castTbMethods[i] + .areParametersEqual(expressionTbMethods[j])) { + return false; + } } } } } } + return true; } - return true; + + return false; } return false; } - return false; -} -public final void computeConstant(TypeBinding leftType, TypeBinding rightType) { - if ((this.left.constant != NotAConstant) && (this.right.constant != NotAConstant)) { - this.constant = - Constant.computeConstantOperationEQUAL_EQUAL( - left.constant, - leftType.id, - EQUAL_EQUAL, - right.constant, - rightType.id); - if (((this.bits & OperatorMASK) >> OperatorSHIFT) == NOT_EQUAL) - constant = Constant.fromValue(!constant.booleanValue()); - } else { - this.constant = NotAConstant; - // no optimization for null == null + public final void computeConstant(TypeBinding leftType, + TypeBinding rightType) { + if ((this.left.constant != NotAConstant) + && (this.right.constant != NotAConstant)) { + this.constant = Constant.computeConstantOperationEQUAL_EQUAL( + left.constant, leftType.id, EQUAL_EQUAL, right.constant, + rightType.id); + if (((this.bits & OperatorMASK) >> OperatorSHIFT) == NOT_EQUAL) + constant = Constant.fromValue(!constant.booleanValue()); + } else { + this.constant = NotAConstant; + // no optimization for null == null + } } -} -/** - * Normal == or != code generation. - * - * @param currentScope net.sourceforge.phpdt.internal.compiler.lookup.BlockScope - * @param codeStream net.sourceforge.phpdt.internal.compiler.codegen.CodeStream - * @param valueRequired boolean - */ -//public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { -// -// if (constant != NotAConstant) { -// int pc = codeStream.position; -// if (valueRequired) -// codeStream.generateConstant(constant, implicitConversion); -// codeStream.recordPositionsFrom(pc, this.sourceStart); -// return; -// } -// Label falseLabel; -// bits |= OnlyValueRequiredMASK; -// generateOptimizedBoolean( -// currentScope, -// codeStream, -// null, -// falseLabel = new Label(codeStream), -// valueRequired); -// if (falseLabel.hasForwardReferences()) { -// if (valueRequired){ -// // comparison is TRUE -// codeStream.iconst_1(); -// if ((bits & ValueForReturnMASK) != 0){ -// codeStream.ireturn(); -// // comparison is FALSE -// falseLabel.place(); -// codeStream.iconst_0(); -// } else { -// Label endLabel = new Label(codeStream); -// codeStream.goto_(endLabel); -// codeStream.decrStackSize(1); -// // comparison is FALSE -// falseLabel.place(); -// codeStream.iconst_0(); -// endLabel.place(); -// } -// } else { -// falseLabel.place(); -// } -// } -//} -/** - * Boolean operator code generation - * Optimized operations are: == and != - */ -//public void generateOptimizedBoolean(BlockScope currentScope, CodeStream codeStream, Label trueLabel, Label falseLabel, boolean valueRequired) { -// -// if (constant != Constant.NotAConstant) { -// super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired); -// return; -// } -// if (((bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) { -// if ((left.implicitConversion & 0xF) /*compile-time*/ == T_boolean) { -// generateOptimizedBooleanEqual(currentScope, codeStream, trueLabel, falseLabel, valueRequired); -// } else { -// generateOptimizedNonBooleanEqual(currentScope, codeStream, trueLabel, falseLabel, valueRequired); -// } -// } else { -// if ((left.implicitConversion & 0xF) /*compile-time*/ == T_boolean) { -// generateOptimizedBooleanEqual(currentScope, codeStream, falseLabel, trueLabel, valueRequired); -// } else { -// generateOptimizedNonBooleanEqual(currentScope, codeStream, falseLabel, trueLabel, valueRequired); -// } -// } -//} -/** - * Boolean generation for == with boolean operands - * - * Note this code does not optimize conditional constants !!!! - */ -//public void generateOptimizedBooleanEqual(BlockScope currentScope, CodeStream codeStream, Label trueLabel, Label falseLabel, boolean valueRequired) { -// -// // optimized cases: true == x, false == x -// if (left.constant != NotAConstant) { -// boolean inline = left.constant.booleanValue(); -// right.generateOptimizedBoolean(currentScope, codeStream, (inline ? trueLabel : falseLabel), (inline ? falseLabel : trueLabel), valueRequired); -// return; -// } // optimized cases: x == true, x == false -// if (right.constant != NotAConstant) { -// boolean inline = right.constant.booleanValue(); -// left.generateOptimizedBoolean(currentScope, codeStream, (inline ? trueLabel : falseLabel), (inline ? falseLabel : trueLabel), valueRequired); -// return; -// } -// // default case -// left.generateCode(currentScope, codeStream, valueRequired); -// right.generateCode(currentScope, codeStream, valueRequired); -// if (valueRequired) { -// if (falseLabel == null) { -// if (trueLabel != null) { -// // implicit falling through the FALSE case -// codeStream.if_icmpeq(trueLabel); -// } -// } else { -// // implicit falling through the TRUE case -// if (trueLabel == null) { -// codeStream.if_icmpne(falseLabel); -// } else { -// // no implicit fall through TRUE/FALSE --> should never occur -// } -// } -// } -// // reposition the endPC -// codeStream.updateLastRecordedEndPC(codeStream.position); -//} -///** -// * Boolean generation for == with non-boolean operands -// * -// */ -//public void generateOptimizedNonBooleanEqual(BlockScope currentScope, CodeStream codeStream, Label trueLabel, Label falseLabel, boolean valueRequired) { -// -// int pc = codeStream.position; -// Constant inline; -// if ((inline = right.constant) != NotAConstant) { -// // optimized case: x == 0 -// if (((left.implicitConversion >> 4) == T_int) && (inline.intValue() == 0)) { -// left.generateCode(currentScope, codeStream, valueRequired); -// if (valueRequired) { -// if (falseLabel == null) { -// if (trueLabel != null) { -// // implicit falling through the FALSE case -// codeStream.ifeq(trueLabel); -// } -// } else { -// // implicit falling through the TRUE case -// if (trueLabel == null) { -// codeStream.ifne(falseLabel); -// } else { -// // no implicit fall through TRUE/FALSE --> should never occur -// } -// } -// } -// codeStream.recordPositionsFrom(pc, this.sourceStart); -// return; -// } -// } -// if ((inline = left.constant) != NotAConstant) { -// // optimized case: 0 == x -// if (((left.implicitConversion >> 4) == T_int) -// && (inline.intValue() == 0)) { -// right.generateCode(currentScope, codeStream, valueRequired); -// if (valueRequired) { -// if (falseLabel == null) { -// if (trueLabel != null) { -// // implicit falling through the FALSE case -// codeStream.ifeq(trueLabel); -// } -// } else { -// // implicit falling through the TRUE case -// if (trueLabel == null) { -// codeStream.ifne(falseLabel); -// } else { -// // no implicit fall through TRUE/FALSE --> should never occur -// } -// } -// } -// codeStream.recordPositionsFrom(pc, this.sourceStart); -// return; -// } -// } -// // null cases -// // optimized case: x == null -// if (right instanceof NullLiteral) { -// if (left instanceof NullLiteral) { -// // null == null -// if (valueRequired) { -// if ((bits & OnlyValueRequiredMASK) != 0) { -// if (((bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) { -// codeStream.iconst_1(); -// } else { -// codeStream.iconst_0(); -// } -// } else { -// if (falseLabel == null) { -// // implicit falling through the FALSE case -// if (trueLabel != null) { -// codeStream.goto_(trueLabel); -// } -// } -// } -// } -// } else { -// left.generateCode(currentScope, codeStream, valueRequired); -// if (valueRequired) { -// if (falseLabel == null) { -// if (trueLabel != null) { -// // implicit falling through the FALSE case -// codeStream.ifnull(trueLabel); -// } -// } else { -// // implicit falling through the TRUE case -// if (trueLabel == null) { -// codeStream.ifnonnull(falseLabel); -// } else { -// // no implicit fall through TRUE/FALSE --> should never occur -// } -// } -// } -// } -// codeStream.recordPositionsFrom(pc, this.sourceStart); -// return; -// } else if (left instanceof NullLiteral) { // optimized case: null == x -// right.generateCode(currentScope, codeStream, valueRequired); -// if (valueRequired) { -// if (falseLabel == null) { -// if (trueLabel != null) { -// // implicit falling through the FALSE case -// codeStream.ifnull(trueLabel); -// } -// } else { -// // implicit falling through the TRUE case -// if (trueLabel == null) { -// codeStream.ifnonnull(falseLabel); -// } else { -// // no implicit fall through TRUE/FALSE --> should never occur -// } -// } -// } -// codeStream.recordPositionsFrom(pc, this.sourceStart); -// return; -// } -// -// // default case -// 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 (left.implicitConversion >> 4) { // operand runtime type -// case T_int : -// codeStream.if_icmpeq(trueLabel); -// break; -// case T_float : -// codeStream.fcmpl(); -// codeStream.ifeq(trueLabel); -// break; -// case T_long : -// codeStream.lcmp(); -// codeStream.ifeq(trueLabel); -// break; -// case T_double : -// codeStream.dcmpl(); -// codeStream.ifeq(trueLabel); -// break; -// default : -// codeStream.if_acmpeq(trueLabel); -// } -// } -// } else { -// // implicit falling through the TRUE case -// if (trueLabel == null) { -// switch (left.implicitConversion >> 4) { // operand runtime type -// case T_int : -// codeStream.if_icmpne(falseLabel); -// break; -// case T_float : -// codeStream.fcmpl(); -// codeStream.ifne(falseLabel); -// break; -// case T_long : -// codeStream.lcmp(); -// codeStream.ifne(falseLabel); -// break; -// case T_double : -// codeStream.dcmpl(); -// codeStream.ifne(falseLabel); -// break; -// default : -// codeStream.if_acmpne(falseLabel); -// } -// } else { -// // no implicit fall through TRUE/FALSE --> should never occur -// } -// } -// } -// codeStream.recordPositionsFrom(pc, this.sourceStart); -//} -public boolean isCompactableOperation() { - return false; -} -public TypeBinding resolveType(BlockScope scope) { - // always return BooleanBinding - TypeBinding leftType = left.resolveType(scope); - TypeBinding rightType = right.resolveType(scope); - if (leftType == null || rightType == null){ - constant = NotAConstant; - return null; + + /** + * Normal == or != code generation. + * + * @param currentScope + * net.sourceforge.phpdt.internal.compiler.lookup.BlockScope + * @param codeStream + * net.sourceforge.phpdt.internal.compiler.codegen.CodeStream + * @param valueRequired + * boolean + */ + // public void generateCode(BlockScope currentScope, CodeStream codeStream, + // boolean valueRequired) { + // + // if (constant != NotAConstant) { + // int pc = codeStream.position; + // if (valueRequired) + // codeStream.generateConstant(constant, implicitConversion); + // codeStream.recordPositionsFrom(pc, this.sourceStart); + // return; + // } + // Label falseLabel; + // bits |= OnlyValueRequiredMASK; + // generateOptimizedBoolean( + // currentScope, + // codeStream, + // null, + // falseLabel = new Label(codeStream), + // valueRequired); + // if (falseLabel.hasForwardReferences()) { + // if (valueRequired){ + // // comparison is TRUE + // codeStream.iconst_1(); + // if ((bits & ValueForReturnMASK) != 0){ + // codeStream.ireturn(); + // // comparison is FALSE + // falseLabel.place(); + // codeStream.iconst_0(); + // } else { + // Label endLabel = new Label(codeStream); + // codeStream.goto_(endLabel); + // codeStream.decrStackSize(1); + // // comparison is FALSE + // falseLabel.place(); + // codeStream.iconst_0(); + // endLabel.place(); + // } + // } else { + // falseLabel.place(); + // } + // } + // } + /** + * Boolean operator code generation Optimized operations are: == and != + */ + // public void generateOptimizedBoolean(BlockScope currentScope, CodeStream + // codeStream, Label trueLabel, Label falseLabel, boolean valueRequired) { + // + // if (constant != Constant.NotAConstant) { + // super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, + // falseLabel, valueRequired); + // return; + // } + // if (((bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) { + // if ((left.implicitConversion & 0xF) /*compile-time*/ == T_boolean) { + // generateOptimizedBooleanEqual(currentScope, codeStream, trueLabel, + // falseLabel, valueRequired); + // } else { + // generateOptimizedNonBooleanEqual(currentScope, codeStream, trueLabel, + // falseLabel, valueRequired); + // } + // } else { + // if ((left.implicitConversion & 0xF) /*compile-time*/ == T_boolean) { + // generateOptimizedBooleanEqual(currentScope, codeStream, falseLabel, + // trueLabel, valueRequired); + // } else { + // generateOptimizedNonBooleanEqual(currentScope, codeStream, falseLabel, + // trueLabel, valueRequired); + // } + // } + // } + /** + * Boolean generation for == with boolean operands + * + * Note this code does not optimize conditional constants !!!! + */ + // public void generateOptimizedBooleanEqual(BlockScope currentScope, + // CodeStream codeStream, Label trueLabel, Label falseLabel, boolean + // valueRequired) { + // + // // optimized cases: true == x, false == x + // if (left.constant != NotAConstant) { + // boolean inline = left.constant.booleanValue(); + // right.generateOptimizedBoolean(currentScope, codeStream, (inline ? + // trueLabel : falseLabel), (inline ? falseLabel : trueLabel), + // valueRequired); + // return; + // } // optimized cases: x == true, x == false + // if (right.constant != NotAConstant) { + // boolean inline = right.constant.booleanValue(); + // left.generateOptimizedBoolean(currentScope, codeStream, (inline ? + // trueLabel : falseLabel), (inline ? falseLabel : trueLabel), + // valueRequired); + // return; + // } + // // default case + // left.generateCode(currentScope, codeStream, valueRequired); + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) { + // if (falseLabel == null) { + // if (trueLabel != null) { + // // implicit falling through the FALSE case + // codeStream.if_icmpeq(trueLabel); + // } + // } else { + // // implicit falling through the TRUE case + // if (trueLabel == null) { + // codeStream.if_icmpne(falseLabel); + // } else { + // // no implicit fall through TRUE/FALSE --> should never occur + // } + // } + // } + // // reposition the endPC + // codeStream.updateLastRecordedEndPC(codeStream.position); + // } + // /** + // * Boolean generation for == with non-boolean operands + // * + // */ + // public void generateOptimizedNonBooleanEqual(BlockScope currentScope, + // CodeStream codeStream, Label trueLabel, Label falseLabel, boolean + // valueRequired) { + // + // int pc = codeStream.position; + // Constant inline; + // if ((inline = right.constant) != NotAConstant) { + // // optimized case: x == 0 + // if (((left.implicitConversion >> 4) == T_int) && (inline.intValue() == + // 0)) { + // left.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) { + // if (falseLabel == null) { + // if (trueLabel != null) { + // // implicit falling through the FALSE case + // codeStream.ifeq(trueLabel); + // } + // } else { + // // implicit falling through the TRUE case + // if (trueLabel == null) { + // codeStream.ifne(falseLabel); + // } else { + // // no implicit fall through TRUE/FALSE --> should never occur + // } + // } + // } + // codeStream.recordPositionsFrom(pc, this.sourceStart); + // return; + // } + // } + // if ((inline = left.constant) != NotAConstant) { + // // optimized case: 0 == x + // if (((left.implicitConversion >> 4) == T_int) + // && (inline.intValue() == 0)) { + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) { + // if (falseLabel == null) { + // if (trueLabel != null) { + // // implicit falling through the FALSE case + // codeStream.ifeq(trueLabel); + // } + // } else { + // // implicit falling through the TRUE case + // if (trueLabel == null) { + // codeStream.ifne(falseLabel); + // } else { + // // no implicit fall through TRUE/FALSE --> should never occur + // } + // } + // } + // codeStream.recordPositionsFrom(pc, this.sourceStart); + // return; + // } + // } + // // null cases + // // optimized case: x == null + // if (right instanceof NullLiteral) { + // if (left instanceof NullLiteral) { + // // null == null + // if (valueRequired) { + // if ((bits & OnlyValueRequiredMASK) != 0) { + // if (((bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) { + // codeStream.iconst_1(); + // } else { + // codeStream.iconst_0(); + // } + // } else { + // if (falseLabel == null) { + // // implicit falling through the FALSE case + // if (trueLabel != null) { + // codeStream.goto_(trueLabel); + // } + // } + // } + // } + // } else { + // left.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) { + // if (falseLabel == null) { + // if (trueLabel != null) { + // // implicit falling through the FALSE case + // codeStream.ifnull(trueLabel); + // } + // } else { + // // implicit falling through the TRUE case + // if (trueLabel == null) { + // codeStream.ifnonnull(falseLabel); + // } else { + // // no implicit fall through TRUE/FALSE --> should never occur + // } + // } + // } + // } + // codeStream.recordPositionsFrom(pc, this.sourceStart); + // return; + // } else if (left instanceof NullLiteral) { // optimized case: null == x + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) { + // if (falseLabel == null) { + // if (trueLabel != null) { + // // implicit falling through the FALSE case + // codeStream.ifnull(trueLabel); + // } + // } else { + // // implicit falling through the TRUE case + // if (trueLabel == null) { + // codeStream.ifnonnull(falseLabel); + // } else { + // // no implicit fall through TRUE/FALSE --> should never occur + // } + // } + // } + // codeStream.recordPositionsFrom(pc, this.sourceStart); + // return; + // } + // + // // default case + // 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 (left.implicitConversion >> 4) { // operand runtime type + // case T_int : + // codeStream.if_icmpeq(trueLabel); + // break; + // case T_float : + // codeStream.fcmpl(); + // codeStream.ifeq(trueLabel); + // break; + // case T_long : + // codeStream.lcmp(); + // codeStream.ifeq(trueLabel); + // break; + // case T_double : + // codeStream.dcmpl(); + // codeStream.ifeq(trueLabel); + // break; + // default : + // codeStream.if_acmpeq(trueLabel); + // } + // } + // } else { + // // implicit falling through the TRUE case + // if (trueLabel == null) { + // switch (left.implicitConversion >> 4) { // operand runtime type + // case T_int : + // codeStream.if_icmpne(falseLabel); + // break; + // case T_float : + // codeStream.fcmpl(); + // codeStream.ifne(falseLabel); + // break; + // case T_long : + // codeStream.lcmp(); + // codeStream.ifne(falseLabel); + // break; + // case T_double : + // codeStream.dcmpl(); + // codeStream.ifne(falseLabel); + // break; + // default : + // codeStream.if_acmpne(falseLabel); + // } + // } else { + // // no implicit fall through TRUE/FALSE --> should never occur + // } + // } + // } + // codeStream.recordPositionsFrom(pc, this.sourceStart); + // } + public boolean isCompactableOperation() { + return false; } - // both base type - if (leftType.isBaseType() && rightType.isBaseType()) { - // the code is an int - // (cast) left == (cast) rigth --> result - // 0000 0000 0000 0000 0000 - // <<16 <<12 <<8 <<4 <<0 - int result = ResolveTypeTables[EQUAL_EQUAL][ (leftType.id << 4) + rightType.id]; - left.implicitConversion = result >>> 12; - right.implicitConversion = (result >>> 4) & 0x000FF; - bits |= result & 0xF; - if ((result & 0x0000F) == T_undefined) { - constant = Constant.NotAConstant; - scope.problemReporter().invalidOperator(this, leftType, rightType); + public TypeBinding resolveType(BlockScope scope) { + // always return BooleanBinding + TypeBinding leftType = left.resolveType(scope); + TypeBinding rightType = right.resolveType(scope); + if (leftType == null || rightType == null) { + constant = NotAConstant; return null; } - computeConstant(leftType, rightType); - this.resolvedType = BooleanBinding; - return BooleanBinding; - } - // Object references - // spec 15.20.3 - if (areTypesCastCompatible(scope, rightType, leftType) || areTypesCastCompatible(scope, leftType, rightType)) { - // (special case for String) - if ((rightType.id == T_String) && (leftType.id == T_String)) + // both base type + if (leftType.isBaseType() && rightType.isBaseType()) { + // the code is an int + // (cast) left == (cast) rigth --> result + // 0000 0000 0000 0000 0000 + // <<16 <<12 <<8 <<4 <<0 + int result = ResolveTypeTables[EQUAL_EQUAL][(leftType.id << 4) + + rightType.id]; + left.implicitConversion = result >>> 12; + right.implicitConversion = (result >>> 4) & 0x000FF; + bits |= result & 0xF; + if ((result & 0x0000F) == T_undefined) { + constant = Constant.NotAConstant; + scope.problemReporter().invalidOperator(this, leftType, + rightType); + return null; + } computeConstant(leftType, rightType); - else - constant = NotAConstant; - if (rightType.id == T_String) - right.implicitConversion = String2String; - if (leftType.id == T_String) - left.implicitConversion = String2String; - this.resolvedType = BooleanBinding; - return BooleanBinding; + this.resolvedType = BooleanBinding; + return BooleanBinding; + } + + // Object references + // spec 15.20.3 + if (areTypesCastCompatible(scope, rightType, leftType) + || areTypesCastCompatible(scope, leftType, rightType)) { + // (special case for String) + if ((rightType.id == T_String) && (leftType.id == T_String)) + computeConstant(leftType, rightType); + else + constant = NotAConstant; + if (rightType.id == T_String) + right.implicitConversion = String2String; + if (leftType.id == T_String) + left.implicitConversion = String2String; + this.resolvedType = BooleanBinding; + return BooleanBinding; + } + constant = NotAConstant; + scope.problemReporter().notCompatibleTypesError(this, leftType, + rightType); + return null; } - constant = NotAConstant; - scope.problemReporter().notCompatibleTypesError(this, leftType, rightType); - return null; -} -public void traverse(ASTVisitor visitor, BlockScope scope) { - if (visitor.visit(this, scope)) { - left.traverse(visitor, scope); - right.traverse(visitor, scope); + + public void traverse(ASTVisitor visitor, BlockScope scope) { + if (visitor.visit(this, scope)) { + left.traverse(visitor, scope); + right.traverse(visitor, scope); + } + visitor.endVisit(this, scope); } - visitor.endVisit(this, scope); -} }