1 11 package org.eclipse.jdt.internal.compiler.ast; 12 13 import org.eclipse.jdt.internal.compiler.ASTVisitor; 14 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; 15 import org.eclipse.jdt.internal.compiler.codegen.*; 16 import org.eclipse.jdt.internal.compiler.flow.*; 17 import org.eclipse.jdt.internal.compiler.impl.Constant; 18 import org.eclipse.jdt.internal.compiler.lookup.*; 19 20 public class CompoundAssignment extends Assignment implements OperatorIds { 21 public int operator; 22 public int preAssignImplicitConversion; 23 24 27 public CompoundAssignment(Expression lhs, Expression expression,int operator, int sourceEnd) { 28 31 super(lhs, expression, sourceEnd); 32 lhs.bits &= ~IsStrictlyAssigned; lhs.bits |= IsCompoundAssigned; this.operator = operator ; 35 } 36 37 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, 38 FlowInfo flowInfo) { 39 if (this.resolvedType.id != T_JavaLangString) { 43 lhs.checkNPE(currentScope, flowContext, flowInfo); 44 } 45 return ((Reference) lhs).analyseAssignment(currentScope, flowContext, flowInfo, this, true).unconditionalInits(); 46 } 47 48 public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { 49 50 54 int pc = codeStream.position; 55 ((Reference) lhs).generateCompoundAssignment(currentScope, codeStream, this.expression, this.operator, this.preAssignImplicitConversion, valueRequired); 56 if (valueRequired) { 57 codeStream.generateImplicitConversion(this.implicitConversion); 58 } 59 codeStream.recordPositionsFrom(pc, this.sourceStart); 60 } 61 62 public int nullStatus(FlowInfo flowInfo) { 63 return FlowInfo.NON_NULL; 64 } 66 67 public String operatorToString() { 68 switch (operator) { 69 case PLUS : 70 return "+="; case MINUS : 72 return "-="; case MULTIPLY : 74 return "*="; case DIVIDE : 76 return "/="; case AND : 78 return "&="; case OR : 80 return "|="; case XOR : 82 return "^="; case REMAINDER : 84 return "%="; case LEFT_SHIFT : 86 return "<<="; case RIGHT_SHIFT : 88 return ">>="; case UNSIGNED_RIGHT_SHIFT : 90 return ">>>="; } 92 return "unknown operator"; } 94 95 public StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output) { 96 97 lhs.printExpression(indent, output).append(' ').append(operatorToString()).append(' '); 98 return expression.printExpression(0, output) ; 99 } 100 101 public TypeBinding resolveType(BlockScope scope) { 102 constant = Constant.NotAConstant; 103 if (!(this.lhs instanceof Reference) || this.lhs.isThis()) { 104 scope.problemReporter().expressionShouldBeAVariable(this.lhs); 105 return null; 106 } 107 TypeBinding originalLhsType = lhs.resolveType(scope); 108 TypeBinding originalExpressionType = expression.resolveType(scope); 109 if (originalLhsType == null || originalExpressionType == null) 110 return null; 111 112 LookupEnvironment env = scope.environment(); 114 TypeBinding lhsType = originalLhsType, expressionType = originalExpressionType; 115 boolean use15specifics = scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5; 116 boolean unboxedLhs = false; 117 if (use15specifics) { 118 if (!lhsType.isBaseType() && expressionType.id != T_JavaLangString && expressionType.id != T_null) { 119 TypeBinding unboxedType = env.computeBoxingType(lhsType); 120 if (unboxedType != lhsType) { 121 lhsType = unboxedType; 122 unboxedLhs = true; 123 } 124 } 125 if (!expressionType.isBaseType() && lhsType.id != T_JavaLangString && lhsType.id != T_null) { 126 expressionType = env.computeBoxingType(expressionType); 127 } 128 } 129 130 if (restrainUsageToNumericTypes() && !lhsType.isNumericType()) { 131 scope.problemReporter().operatorOnlyValidOnNumericType(this, lhsType, expressionType); 132 return null; 133 } 134 int lhsID = lhsType.id; 135 int expressionID = expressionType.id; 136 if (lhsID > 15 || expressionID > 15) { 137 if (lhsID != T_JavaLangString) { scope.problemReporter().invalidOperator(this, lhsType, expressionType); 139 return null; 140 } 141 expressionID = T_JavaLangObject; } 143 144 149 int result = OperatorExpression.OperatorSignatures[operator][ (lhsID << 4) + expressionID]; 151 if (result == T_undefined) { 152 scope.problemReporter().invalidOperator(this, lhsType, expressionType); 153 return null; 154 } 155 if (operator == PLUS){ 156 if(lhsID == T_JavaLangObject) { 157 scope.problemReporter().invalidOperator(this, lhsType, expressionType); 159 return null; 160 } else { 161 if ((lhsType.isNumericType() || lhsID == T_boolean) && !expressionType.isNumericType()){ 163 scope.problemReporter().invalidOperator(this, lhsType, expressionType); 164 return null; 165 } 166 } 167 } 168 this.lhs.computeConversion(scope, TypeBinding.wellKnownType(scope, (result >>> 16) & 0x0000F), originalLhsType); 169 this.expression.computeConversion(scope, TypeBinding.wellKnownType(scope, (result >>> 8) & 0x0000F), originalExpressionType); 170 this.preAssignImplicitConversion = (unboxedLhs ? BOXING : 0) | (lhsID << 4) | (result & 0x0000F); 171 if (unboxedLhs) scope.problemReporter().autoboxing(this, lhsType, originalLhsType); 172 return this.resolvedType = originalLhsType; 173 } 174 175 public boolean restrainUsageToNumericTypes(){ 176 return false ; 177 } 178 179 public void traverse(ASTVisitor visitor, BlockScope scope) { 180 if (visitor.visit(this, scope)) { 181 lhs.traverse(visitor, scope); 182 expression.traverse(visitor, scope); 183 } 184 visitor.endVisit(this, scope); 185 } 186 } 187 | Popular Tags |