KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 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.impl.*;
15 import org.eclipse.jdt.internal.compiler.codegen.*;
16 import org.eclipse.jdt.internal.compiler.flow.*;
17 import org.eclipse.jdt.internal.compiler.lookup.*;
18
19 public class ArrayReference extends Reference {
20     
21     public Expression receiver;
22     public Expression position;
23
24     public ArrayReference(Expression rec, Expression pos) {
25         this.receiver = rec;
26         this.position = pos;
27         sourceStart = rec.sourceStart;
28     }
29
30 public FlowInfo analyseAssignment(
31         BlockScope currentScope,
32         FlowContext flowContext,
33         FlowInfo flowInfo,
34         Assignment assignment,
35         boolean compoundAssignment) {
36     // TODO (maxime) optimization: unconditionalInits is applied to all existing calls
37
if (assignment.expression == null) {
38         return analyseCode(currentScope, flowContext, flowInfo);
39     }
40     return assignment
41         .expression
42         .analyseCode(
43             currentScope,
44             flowContext,
45             analyseCode(currentScope, flowContext, flowInfo).unconditionalInits());
46 }
47
48 public FlowInfo analyseCode(
49         BlockScope currentScope,
50         FlowContext flowContext,
51         FlowInfo flowInfo) {
52     receiver.checkNPE(currentScope, flowContext, flowInfo);
53     flowInfo = receiver.analyseCode(currentScope, flowContext, flowInfo);
54     return position.analyseCode(currentScope, flowContext, flowInfo);
55 }
56
57     public void generateAssignment(
58         BlockScope currentScope,
59         CodeStream codeStream,
60         Assignment assignment,
61         boolean valueRequired) {
62
63         int pc = codeStream.position;
64         receiver.generateCode(currentScope, codeStream, true);
65         if (receiver instanceof CastExpression // ((type[])null)[0]
66
&& ((CastExpression)receiver).innermostCastedExpression().resolvedType == TypeBinding.NULL){
67             codeStream.checkcast(receiver.resolvedType);
68         }
69         codeStream.recordPositionsFrom(pc, this.sourceStart);
70         position.generateCode(currentScope, codeStream, true);
71         assignment.expression.generateCode(currentScope, codeStream, true);
72         codeStream.arrayAtPut(this.resolvedType.id, valueRequired);
73         if (valueRequired) {
74             codeStream.generateImplicitConversion(assignment.implicitConversion);
75         }
76     }
77
78     /**
79      * Code generation for a array reference
80      */

81     public void generateCode(
82         BlockScope currentScope,
83         CodeStream codeStream,
84         boolean valueRequired) {
85
86         int pc = codeStream.position;
87         receiver.generateCode(currentScope, codeStream, true);
88         if (receiver instanceof CastExpression // ((type[])null)[0]
89
&& ((CastExpression)receiver).innermostCastedExpression().resolvedType == TypeBinding.NULL){
90             codeStream.checkcast(receiver.resolvedType);
91         }
92         position.generateCode(currentScope, codeStream, true);
93         codeStream.arrayAt(this.resolvedType.id);
94         // Generating code for the potential runtime type checking
95
if (valueRequired) {
96             codeStream.generateImplicitConversion(implicitConversion);
97         } else {
98             boolean isUnboxing = (implicitConversion & TypeIds.UNBOXING) != 0;
99             // conversion only generated if unboxing
100
if (isUnboxing) codeStream.generateImplicitConversion(implicitConversion);
101             switch (isUnboxing ? postConversionType(currentScope).id : this.resolvedType.id) {
102                 case T_long :
103                 case T_double :
104                     codeStream.pop2();
105                     break;
106                 default :
107                     codeStream.pop();
108             }
109         }
110         codeStream.recordPositionsFrom(pc, this.sourceStart);
111     }
112
113     public void generateCompoundAssignment(
114         BlockScope currentScope,
115         CodeStream codeStream,
116         Expression expression,
117         int operator,
118         int assignmentImplicitConversion,
119         boolean valueRequired) {
120
121         receiver.generateCode(currentScope, codeStream, true);
122         if (receiver instanceof CastExpression // ((type[])null)[0]
123
&& ((CastExpression)receiver).innermostCastedExpression().resolvedType == TypeBinding.NULL){
124             codeStream.checkcast(receiver.resolvedType);
125         }
126         position.generateCode(currentScope, codeStream, true);
127         codeStream.dup2();
128         codeStream.arrayAt(this.resolvedType.id);
129         int operationTypeID;
130         switch(operationTypeID = (implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) {
131             case T_JavaLangString :
132             case T_JavaLangObject :
133             case T_undefined :
134                 codeStream.generateStringConcatenationAppend(currentScope, null, expression);
135                 break;
136             default :
137                 // promote the array reference to the suitable operation type
138
codeStream.generateImplicitConversion(implicitConversion);
139                 // generate the increment value (will by itself be promoted to the operation value)
140
if (expression == IntLiteral.One) { // prefix operation
141
codeStream.generateConstant(expression.constant, implicitConversion);
142                 } else {
143                     expression.generateCode(currentScope, codeStream, true);
144                 }
145                 // perform the operation
146
codeStream.sendOperator(operator, operationTypeID);
147                 // cast the value back to the array reference type
148
codeStream.generateImplicitConversion(assignmentImplicitConversion);
149         }
150         codeStream.arrayAtPut(this.resolvedType.id, valueRequired);
151     }
152
153     public void generatePostIncrement(
154         BlockScope currentScope,
155         CodeStream codeStream,
156         CompoundAssignment postIncrement,
157         boolean valueRequired) {
158
159         receiver.generateCode(currentScope, codeStream, true);
160         if (receiver instanceof CastExpression // ((type[])null)[0]
161
&& ((CastExpression)receiver).innermostCastedExpression().resolvedType == TypeBinding.NULL){
162             codeStream.checkcast(receiver.resolvedType);
163         }
164         position.generateCode(currentScope, codeStream, true);
165         codeStream.dup2();
166         codeStream.arrayAt(this.resolvedType.id);
167         if (valueRequired) {
168             if ((this.resolvedType == TypeBinding.LONG)
169                 || (this.resolvedType == TypeBinding.DOUBLE)) {
170                 codeStream.dup2_x2();
171             } else {
172                 codeStream.dup_x2();
173             }
174         }
175         codeStream.generateImplicitConversion(implicitConversion);
176         codeStream.generateConstant(
177             postIncrement.expression.constant,
178             implicitConversion);
179         codeStream.sendOperator(postIncrement.operator, this.implicitConversion & COMPILE_TYPE_MASK);
180         codeStream.generateImplicitConversion(
181             postIncrement.preAssignImplicitConversion);
182         codeStream.arrayAtPut(this.resolvedType.id, false);
183     }
184
185 public int nullStatus(FlowInfo flowInfo) {
186     return FlowInfo.UNKNOWN;
187 }
188
189     public StringBuffer JavaDoc printExpression(int indent, StringBuffer JavaDoc output) {
190
191         receiver.printExpression(0, output).append('[');
192         return position.printExpression(0, output).append(']');
193     }
194
195     public TypeBinding resolveType(BlockScope scope) {
196
197         constant = Constant.NotAConstant;
198         if (receiver instanceof CastExpression // no cast check for ((type[])null)[0]
199
&& ((CastExpression)receiver).innermostCastedExpression() instanceof NullLiteral) {
200             this.receiver.bits |= DisableUnnecessaryCastCheck; // will check later on
201
}
202         TypeBinding arrayType = receiver.resolveType(scope);
203         if (arrayType != null) {
204             receiver.computeConversion(scope, arrayType, arrayType);
205             if (arrayType.isArrayType()) {
206                 TypeBinding elementType = ((ArrayBinding) arrayType).elementsType();
207                 this.resolvedType = ((this.bits & IsStrictlyAssigned) == 0) ? elementType.capture(scope, this.sourceEnd) : elementType;
208             } else {
209                 scope.problemReporter().referenceMustBeArrayTypeAt(arrayType, this);
210             }
211         }
212         TypeBinding positionType = position.resolveTypeExpecting(scope, TypeBinding.INT);
213         if (positionType != null) {
214             position.computeConversion(scope, TypeBinding.INT, positionType);
215         }
216         return this.resolvedType;
217     }
218
219     public void traverse(ASTVisitor visitor, BlockScope scope) {
220         
221         if (visitor.visit(this, scope)) {
222             receiver.traverse(visitor, scope);
223             position.traverse(visitor, scope);
224         }
225         visitor.endVisit(this, scope);
226     }
227 }
228
Popular Tags