KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > compiler > ast > CompoundAssignment


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

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     // var op exp is equivalent to var = (varType) var op exp
25
// assignmentImplicitConversion stores the cast needed for the assignment
26

27     public CompoundAssignment(Expression lhs, Expression expression,int operator, int sourceEnd) {
28         //lhs is always a reference by construction ,
29
//but is build as an expression ==> the checkcast cannot fail
30

31         super(lhs, expression, sourceEnd);
32         lhs.bits &= ~IsStrictlyAssigned; // tag lhs as NON assigned - it is also a read access
33
lhs.bits |= IsCompoundAssigned; // tag lhs as assigned by compound
34
this.operator = operator ;
35     }
36     
37 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext,
38         FlowInfo flowInfo) {
39     // record setting a variable: various scenarii are possible, setting an array reference,
40
// a field reference, a blank final field reference, a field of an enclosing instance or
41
// just a local variable.
42
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         // various scenarii are possible, setting an array reference,
51
// a field reference, a blank final field reference, a field of an enclosing instance or
52
// just a local variable.
53

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     // we may have complained on checkNPE, but we avoid duplicate error
65
}
66     
67     public String JavaDoc operatorToString() {
68         switch (operator) {
69             case PLUS :
70                 return "+="; //$NON-NLS-1$
71
case MINUS :
72                 return "-="; //$NON-NLS-1$
73
case MULTIPLY :
74                 return "*="; //$NON-NLS-1$
75
case DIVIDE :
76                 return "/="; //$NON-NLS-1$
77
case AND :
78                 return "&="; //$NON-NLS-1$
79
case OR :
80                 return "|="; //$NON-NLS-1$
81
case XOR :
82                 return "^="; //$NON-NLS-1$
83
case REMAINDER :
84                 return "%="; //$NON-NLS-1$
85
case LEFT_SHIFT :
86                 return "<<="; //$NON-NLS-1$
87
case RIGHT_SHIFT :
88                 return ">>="; //$NON-NLS-1$
89
case UNSIGNED_RIGHT_SHIFT :
90                 return ">>>="; //$NON-NLS-1$
91
}
92         return "unknown operator"; //$NON-NLS-1$
93
}
94     
95     public StringBuffer JavaDoc printExpressionNoParenthesis(int indent, StringBuffer JavaDoc 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         // autoboxing support
113
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) { // String += Thread is valid whereas Thread += String is not
138
scope.problemReporter().invalidOperator(this, lhsType, expressionType);
139                 return null;
140             }
141             expressionID = T_JavaLangObject; // use the Object has tag table
142
}
143     
144         // the code is an int
145
// (cast) left Op (cast) rigth --> result
146
// 0000 0000 0000 0000 0000
147
// <<16 <<12 <<8 <<4 <<0
148

149         // the conversion is stored INTO the reference (info needed for the code gen)
150
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                 // <Object> += <String> is illegal (39248)
158
scope.problemReporter().invalidOperator(this, lhsType, expressionType);
159                 return null;
160             } else {
161                 // <int | boolean> += <String> is illegal
162
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