KickJava   Java API By Example, From Geeks To Geeks.

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


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.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 ArrayInitializer extends Expression {
21         
22     public Expression[] expressions;
23     public ArrayBinding binding; //the type of the { , , , }
24

25     /**
26      * ArrayInitializer constructor comment.
27      */

28     public ArrayInitializer() {
29
30         super();
31     }
32
33     public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
34
35         if (expressions != null) {
36             for (int i = 0, max = expressions.length; i < max; i++) {
37                 flowInfo = expressions[i].analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
38             }
39         }
40         return flowInfo;
41     }
42
43     /**
44      * Code generation for a array initializer
45      */

46     public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
47
48         // Flatten the values and compute the dimensions, by iterating in depth into nested array initializers
49
int pc = codeStream.position;
50         int expressionLength = (expressions == null) ? 0: expressions.length;
51         codeStream.generateInlinedValue(expressionLength);
52         codeStream.newArray(binding);
53         if (expressions != null) {
54             // binding is an ArrayType, so I can just deal with the dimension
55
int elementsTypeID = binding.dimensions > 1 ? -1 : binding.leafComponentType.id;
56             for (int i = 0; i < expressionLength; i++) {
57                 Expression expr;
58                 if ((expr = expressions[i]).constant != Constant.NotAConstant) {
59                     switch (elementsTypeID) { // filter out initializations to default values
60
case T_int :
61                         case T_short :
62                         case T_byte :
63                         case T_char :
64                         case T_long :
65                             if (expr.constant.longValue() != 0) {
66                                 codeStream.dup();
67                                 codeStream.generateInlinedValue(i);
68                                 expr.generateCode(currentScope, codeStream, true);
69                                 codeStream.arrayAtPut(elementsTypeID, false);
70                             }
71                             break;
72                         case T_float :
73                         case T_double :
74                             double constantValue = expr.constant.doubleValue();
75                             if (constantValue == -0.0 || constantValue != 0) {
76                                 codeStream.dup();
77                                 codeStream.generateInlinedValue(i);
78                                 expr.generateCode(currentScope, codeStream, true);
79                                 codeStream.arrayAtPut(elementsTypeID, false);
80                             }
81                             break;
82                         case T_boolean :
83                             if (expr.constant.booleanValue() != false) {
84                                 codeStream.dup();
85                                 codeStream.generateInlinedValue(i);
86                                 expr.generateCode(currentScope, codeStream, true);
87                                 codeStream.arrayAtPut(elementsTypeID, false);
88                             }
89                             break;
90                         default :
91                             if (!(expr instanceof NullLiteral)) {
92                                 codeStream.dup();
93                                 codeStream.generateInlinedValue(i);
94                                 expr.generateCode(currentScope, codeStream, true);
95                                 codeStream.arrayAtPut(elementsTypeID, false);
96                             }
97                     }
98                 } else if (!(expr instanceof NullLiteral)) {
99                     codeStream.dup();
100                     codeStream.generateInlinedValue(i);
101                     expr.generateCode(currentScope, codeStream, true);
102                     codeStream.arrayAtPut(elementsTypeID, false);
103                 }
104             }
105         }
106         if (valueRequired) {
107             codeStream.generateImplicitConversion(this.implicitConversion);
108         } else {
109             codeStream.pop();
110         }
111         codeStream.recordPositionsFrom(pc, this.sourceStart);
112     }
113
114     public StringBuffer JavaDoc printExpression(int indent, StringBuffer JavaDoc output) {
115     
116         output.append('{');
117         if (expressions != null) {
118             int j = 20 ;
119             for (int i = 0 ; i < expressions.length ; i++) {
120                 if (i > 0) output.append(", "); //$NON-NLS-1$
121
expressions[i].printExpression(0, output);
122                 j -- ;
123                 if (j == 0) {
124                     output.append('\n');
125                     printIndent(indent+1, output);
126                     j = 20;
127                 }
128             }
129         }
130         return output.append('}');
131     }
132
133     public TypeBinding resolveTypeExpecting(BlockScope scope, TypeBinding expectedType) {
134         // Array initializers can only occur on the right hand side of an assignment
135
// expression, therefore the expected type contains the valid information
136
// concerning the type that must be enforced by the elements of the array initializer.
137

138         // this method is recursive... (the test on isArrayType is the stop case)
139

140         this.constant = Constant.NotAConstant;
141         
142         if (expectedType instanceof ArrayBinding) {
143             // allow new List<?>[5]
144
if ((this.bits & IsAnnotationDefaultValue) == 0) { // annotation default value need only to be commensurate JLS9.7
145
// allow new List<?>[5] - only check for generic array when no initializer, since also checked inside initializer resolution
146
TypeBinding leafComponentType = expectedType.leafComponentType();
147                 if (!leafComponentType.isReifiable()) {
148                     scope.problemReporter().illegalGenericArray(leafComponentType, this);
149                 }
150             }
151             this.resolvedType = this.binding = (ArrayBinding) expectedType;
152             if (this.expressions == null)
153                 return this.binding;
154             TypeBinding elementType = this.binding.elementsType();
155             for (int i = 0, length = this.expressions.length; i < length; i++) {
156                 Expression expression = this.expressions[i];
157                 expression.setExpectedType(elementType);
158                 TypeBinding expressionType = expression instanceof ArrayInitializer
159                         ? expression.resolveTypeExpecting(scope, elementType)
160                         : expression.resolveType(scope);
161                 if (expressionType == null)
162                     continue;
163
164                 // Compile-time conversion required?
165
if (elementType != expressionType) // must call before computeConversion() and typeMismatchError()
166
scope.compilationUnitScope().recordTypeConversion(elementType, expressionType);
167
168                 if ((expression.isConstantValueOfTypeAssignableToType(expressionType, elementType)
169                         || (elementType.isBaseType() && BaseTypeBinding.isWidening(elementType.id, expressionType.id)))
170                         || expressionType.isCompatibleWith(elementType)) {
171                     expression.computeConversion(scope, elementType, expressionType);
172                 } else if (scope.isBoxingCompatibleWith(expressionType, elementType)
173                                     || (expressionType.isBaseType() // narrowing then boxing ?
174
&& scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5 // autoboxing
175
&& !elementType.isBaseType()
176                                             && expression.isConstantValueOfTypeAssignableToType(expressionType, scope.environment().computeBoxingType(elementType)))) {
177                     expression.computeConversion(scope, elementType, expressionType);
178                 } else {
179                     scope.problemReporter().typeMismatchError(expressionType, elementType, expression);
180                 }
181             }
182             return this.binding;
183         }
184         
185         // infer initializer type for error reporting based on first element
186
TypeBinding leafElementType = null;
187         int dim = 1;
188         if (this.expressions == null) {
189             leafElementType = scope.getJavaLangObject();
190         } else {
191             Expression expression = this.expressions[0];
192             while(expression != null && expression instanceof ArrayInitializer) {
193                 dim++;
194                 Expression[] subExprs = ((ArrayInitializer) expression).expressions;
195                 if (subExprs == null){
196                     leafElementType = scope.getJavaLangObject();
197                     expression = null;
198                     break;
199                 }
200                 expression = ((ArrayInitializer) expression).expressions[0];
201             }
202             if (expression != null) {
203                 leafElementType = expression.resolveType(scope);
204             }
205             // fault-tolerance - resolve other expressions as well
206
for (int i = 1, length = this.expressions.length; i < length; i++) {
207                 expression = this.expressions[i];
208                 if (expression != null) {
209                     expression.resolveType(scope) ;
210                 }
211             } }
212         if (leafElementType != null) {
213             this.resolvedType = scope.createArrayType(leafElementType, dim);
214             if (expectedType != null)
215                 scope.problemReporter().typeMismatchError(this.resolvedType, expectedType, this);
216         }
217         return null;
218     }
219     
220     public void traverse(ASTVisitor visitor, BlockScope scope) {
221
222         if (visitor.visit(this, scope)) {
223             if (this.expressions != null) {
224                 int expressionsLength = this.expressions.length;
225                 for (int i = 0; i < expressionsLength; i++)
226                     this.expressions[i].traverse(visitor, scope);
227             }
228         }
229         visitor.endVisit(this, scope);
230     }
231 }
232
Popular Tags