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 e2385de..3788b65 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 @@ -1,20 +1,25 @@ /******************************************************************************* - * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others. + * 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 v0.5 + * 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-v05.html + * http://www.eclipse.org/legal/cpl-v10.html * * Contributors: * IBM Corporation - initial API and implementation - ******************************************************************************/ + *******************************************************************************/ package net.sourceforge.phpdt.internal.compiler.ast; -import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor; -import net.sourceforge.phpdt.internal.compiler.impl.*; -import net.sourceforge.phpdt.internal.compiler.codegen.*; -import net.sourceforge.phpdt.internal.compiler.flow.*; -import net.sourceforge.phpdt.internal.compiler.lookup.*; +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.MethodBinding; +import net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding; +import net.sourceforge.phpdt.internal.compiler.lookup.Scope; +import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding; public class EqualExpression extends BinaryExpression { @@ -68,32 +73,33 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits()).asNegatedCondition().unconditionalInits(); } } -public final boolean areTypesCastCompatible(BlockScope scope, TypeBinding castTb, TypeBinding expressionTb) { - //see specifications p.68 +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; //========ARRAY=============== - if (expressionTb.isArrayType()) { - if (castTb.isArrayType()) { //------- (castTb.isArray) expressionTb.isArray ----------- - TypeBinding expressionEltTb = ((ArrayBinding) expressionTb).elementsType(scope); - if (expressionEltTb.isBaseType()) + if (expressionType.isArrayType()) { + if (castType.isArrayType()) { //------- (castTb.isArray) expressionTb.isArray ----------- + TypeBinding expressionEltType = ((ArrayBinding) expressionType).elementsType(scope); + if (expressionEltType.isBaseType()) // <---stop the recursion------- - return ((ArrayBinding) castTb).elementsType(scope) == expressionEltTb; + return ((ArrayBinding) castType).elementsType(scope) == expressionEltType; //recursivly on the elts... - return areTypesCastCompatible(scope, ((ArrayBinding) castTb).elementsType(scope), expressionEltTb); + return areTypesCastCompatible(scope, ((ArrayBinding) castType).elementsType(scope), expressionEltType); } - if (castTb.isBaseType()) { + if (castType.isBaseType()) { return false; } - if (castTb.isClass()) { //------(castTb.isClass) expressionTb.isArray --------------- - if (scope.isJavaLangObject(castTb)) + if (castType.isClass()) { //------(castTb.isClass) expressionTb.isArray --------------- + if (scope.isJavaLangObject(castType)) return true; return false; } - if (castTb.isInterface()) { //------- (castTb.isInterface) expressionTb.isArray ----------- - if (scope.isJavaLangCloneable(castTb) || scope.isJavaIoSerializable(castTb)) { + if (castType.isInterface()) { //------- (castTb.isInterface) expressionTb.isArray ----------- + if (scope.isJavaLangCloneable(castType) || scope.isJavaIoSerializable(castType)) { return true; } return false; @@ -103,39 +109,39 @@ public final boolean areTypesCastCompatible(BlockScope scope, TypeBinding castTb } //------------(castType) null-------------- - if (expressionTb == NullBinding) { - return !castTb.isBaseType(); + if (expressionType == NullBinding) { + return !castType.isBaseType(); } //========BASETYPE============== - if (expressionTb.isBaseType()) { + if (expressionType.isBaseType()) { return false; } //========REFERENCE TYPE=================== - if (expressionTb.isClass()) { - if (castTb.isArrayType()) { // ---- (castTb.isArray) expressionTb.isClass ------- - if (scope.isJavaLangObject(expressionTb)) + if (expressionType.isClass()) { + if (castType.isArrayType()) { // ---- (castTb.isArray) expressionTb.isClass ------- + if (scope.isJavaLangObject(expressionType)) return true; } - if (castTb.isBaseType()) { + if (castType.isBaseType()) { return false; } - if (castTb.isClass()) { // ----- (castTb.isClass) expressionTb.isClass ------ - if (scope.areTypesCompatible(expressionTb, castTb)) + if (castType.isClass()) { // ----- (castTb.isClass) expressionTb.isClass ------ + if (expressionType.isCompatibleWith(castType)) return true; else { - if (scope.areTypesCompatible(castTb, expressionTb)) { + if (castType.isCompatibleWith(expressionType)) { return true; } return false; } } - if (castTb.isInterface()) { // ----- (castTb.isInterface) expressionTb.isClass ------- - if (((ReferenceBinding) expressionTb).isFinal()) { //no subclass for expressionTb, thus compile-time check is valid - if (scope.areTypesCompatible(expressionTb, castTb)) + 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 { @@ -145,34 +151,34 @@ public final boolean areTypesCastCompatible(BlockScope scope, TypeBinding castTb return false; } - if (expressionTb.isInterface()) { - if (castTb.isArrayType()) { // ----- (castTb.isArray) expressionTb.isInterface ------ - if (scope.isJavaLangCloneable(expressionTb) || scope.isJavaIoSerializable(expressionTb)) + if (expressionType.isInterface()) { + if (castType.isArrayType()) { // ----- (castTb.isArray) expressionTb.isInterface ------ + if (scope.isJavaLangCloneable(expressionType) || scope.isJavaIoSerializable(expressionType)) //potential runtime error { return true; } return false; } - if (castTb.isBaseType()) { + if (castType.isBaseType()) { return false; } - if (castTb.isClass()) { // ----- (castTb.isClass) expressionTb.isInterface -------- - if (scope.isJavaLangObject(castTb)) + if (castType.isClass()) { // ----- (castTb.isClass) expressionTb.isInterface -------- + if (scope.isJavaLangObject(castType)) return true; - if (((ReferenceBinding) castTb).isFinal()) { //no subclass for castTb, thus compile-time check is valid - if (scope.areTypesCompatible(castTb, expressionTb)) { + 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 (castTb.isInterface()) { // ----- (castTb.isInterface) expressionTb.isInterface ------- - if (castTb != expressionTb && (Scope.compareTypes(castTb, expressionTb) == NotRelated)) { - MethodBinding[] castTbMethods = ((ReferenceBinding) castTb).methods(); + 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) expressionTb).methods(); + MethodBinding[] expressionTbMethods = ((ReferenceBinding) expressionType).methods(); int expressionTbMethodsLength = expressionTbMethods.length; for (int i = 0; i < castTbMethodsLength; i++) { for (int j = 0; j < expressionTbMethodsLength; j++) { @@ -194,336 +200,357 @@ public final boolean areTypesCastCompatible(BlockScope scope, TypeBinding castTb return false; } -public final void computeConstant(TypeBinding leftTb, TypeBinding rightTb) { - if ((left.constant != NotAConstant) && (right.constant != NotAConstant)) { - constant = +public final void computeConstant(TypeBinding leftType, TypeBinding rightType) { + if ((this.left.constant != NotAConstant) && (this.right.constant != NotAConstant)) { + this.constant = Constant.computeConstantOperationEQUAL_EQUAL( left.constant, - leftTb.id, + leftType.id, EQUAL_EQUAL, right.constant, - rightTb.id); - if (((bits & OperatorMASK) >> OperatorSHIFT) == NOT_EQUAL) + rightType.id); + if (((this.bits & OperatorMASK) >> OperatorSHIFT) == NOT_EQUAL) constant = Constant.fromValue(!constant.booleanValue()); } else { - constant = NotAConstant; + this.constant = NotAConstant; + // no optimization for null == null } } /** * Normal == or != code generation. * - * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope - * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream + * @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; - 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(); - } - } -} +//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) && (constant.typeID() == T_boolean)) { - super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired); - return; - } - int pc = codeStream.position; - 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); - } - } - codeStream.recordPositionsFrom(pc, this.sourceStart); -} +//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) { - int pc = codeStream.position; - // 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); - codeStream.recordPositionsFrom(pc, this.sourceStart); - 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); - 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 - 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 - } - } - } - codeStream.recordPositionsFrom(pc, this.sourceStart); -} -/** - * 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 == null - if (right.constant == NullConstant.Default) { - 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; - } - // 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: null == x - if (left.constant == NullConstant.Default) { - 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; - } - // 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; - } - } - // 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 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 leftTb = left.resolveType(scope); - TypeBinding rightTb = right.resolveType(scope); - if (leftTb == null || rightTb == null){ + TypeBinding leftType = left.resolveType(scope); + TypeBinding rightType = right.resolveType(scope); + if (leftType == null || rightType == null){ constant = NotAConstant; return null; } // both base type - if (leftTb.isBaseType() && rightTb.isBaseType()) { + 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][ (leftTb.id << 4) + rightTb.id]; + 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, leftTb, rightTb); + scope.problemReporter().invalidOperator(this, leftType, rightType); return null; } - computeConstant(leftTb, rightTb); - this.typeBinding = BooleanBinding; + computeConstant(leftType, rightType); + this.resolvedType = BooleanBinding; return BooleanBinding; } // Object references // spec 15.20.3 - if (areTypesCastCompatible(scope, rightTb, leftTb) || areTypesCastCompatible(scope, leftTb, rightTb)) { + if (areTypesCastCompatible(scope, rightType, leftType) || areTypesCastCompatible(scope, leftType, rightType)) { // (special case for String) - if ((rightTb.id == T_String) && (leftTb.id == T_String)) - computeConstant(leftTb, rightTb); + if ((rightType.id == T_String) && (leftType.id == T_String)) + computeConstant(leftType, rightType); else constant = NotAConstant; - if (rightTb.id == T_String) + if (rightType.id == T_String) right.implicitConversion = String2String; - if (leftTb.id == T_String) + if (leftType.id == T_String) left.implicitConversion = String2String; - this.typeBinding = BooleanBinding; + this.resolvedType = BooleanBinding; return BooleanBinding; } constant = NotAConstant; - scope.problemReporter().notCompatibleTypesError(this, leftTb, rightTb); + scope.problemReporter().notCompatibleTypesError(this, leftType, rightType); return null; } -public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) { +public void traverse(ASTVisitor visitor, BlockScope scope) { if (visitor.visit(this, scope)) { left.traverse(visitor, scope); right.traverse(visitor, scope);