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);
-}
}