Makefile fixup
[org.ibex.tool.git] / repo / org.ibex.tool / src / org / eclipse / jdt / internal / compiler / ast / ArrayAllocationExpression.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2004 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-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 ArrayAllocationExpression extends Expression {
20
21         public TypeReference type;
22
23         //dimensions.length gives the number of dimensions, but the
24         // last ones may be nulled as in new int[4][5][][]
25         public Expression[] dimensions;
26         public ArrayInitializer initializer;
27
28         /**
29          * ArrayAllocationExpression constructor comment.
30          */
31         public ArrayAllocationExpression() {
32                 super();
33         }
34
35         public FlowInfo analyseCode(
36                 BlockScope currentScope,
37                 FlowContext flowContext,
38                 FlowInfo flowInfo) {
39                 for (int i = 0, max = dimensions.length; i < max; i++) {
40                         Expression dim;
41                         if ((dim = dimensions[i]) != null) {
42                                 flowInfo = dim.analyseCode(currentScope, flowContext, flowInfo);
43                         }
44                 }
45                 if (initializer != null) {
46                         return initializer.analyseCode(currentScope, flowContext, flowInfo);
47                 }
48                 return flowInfo;
49         }
50
51         /**
52          * Code generation for a array allocation expression
53          */
54         public void generateCode(
55                 BlockScope currentScope,
56                 CodeStream codeStream,
57                 boolean valueRequired) {
58
59                 int pc = codeStream.position;
60
61                 if (initializer != null) {
62                         initializer.generateCode(currentScope, codeStream, valueRequired);
63                         return;
64                 }
65
66                 int nonNullDimensionsLength = 0;
67                 for (int i = 0, max = dimensions.length; i < max; i++)
68                         if (dimensions[i] != null) {
69                                 dimensions[i].generateCode(currentScope, codeStream, true);
70                                 nonNullDimensionsLength++;
71                         }
72
73                 // Generate a sequence of bytecodes corresponding to an array allocation
74                 if (this.resolvedType.dimensions() == 1) {
75                         // Mono-dimensional array
76                         codeStream.newArray(currentScope, (ArrayBinding)this.resolvedType);
77                 } else {
78                         // Multi-dimensional array
79                         codeStream.multianewarray(this.resolvedType, nonNullDimensionsLength);
80                 }
81
82                 if (valueRequired) {
83                         codeStream.generateImplicitConversion(implicitConversion);
84                 } else {
85                         codeStream.pop();
86                 }
87
88                 codeStream.recordPositionsFrom(pc, this.sourceStart);
89         }
90
91
92         public StringBuffer printExpression(int indent, StringBuffer output) {
93
94                 output.append("new "); //$NON-NLS-1$
95                 type.print(0, output); 
96                 for (int i = 0; i < dimensions.length; i++) {
97                         if (dimensions[i] == null)
98                                 output.append("[]"); //$NON-NLS-1$
99                         else {
100                                 output.append('[');
101                                 dimensions[i].printExpression(0, output);
102                                 output.append(']');
103                         }
104                 } 
105                 if (initializer != null) initializer.printExpression(0, output);
106                 return output;
107         }
108         
109         public TypeBinding resolveType(BlockScope scope) {
110
111                 // Build an array type reference using the current dimensions
112                 // The parser does not check for the fact that dimension may be null
113                 // only at the -end- like new int [4][][]. The parser allows new int[][4][]
114                 // so this must be checked here......(this comes from a reduction to LL1 grammar)
115
116                 TypeBinding referenceType = type.resolveType(scope);
117                 
118                 // will check for null after dimensions are checked
119                 constant = Constant.NotAConstant;
120                 if (referenceType == VoidBinding) {
121                         scope.problemReporter().cannotAllocateVoidArray(this);
122                         referenceType = null;
123                 }
124
125                 // check the validity of the dimension syntax (and test for all null dimensions)
126                 int explicitDimIndex = -1;
127                 for (int i = dimensions.length; --i >= 0;) {
128                         if (dimensions[i] != null) {
129                                 if (explicitDimIndex < 0) explicitDimIndex = i;
130                         } else if (explicitDimIndex> 0) {
131                                 // should not have an empty dimension before an non-empty one
132                                 scope.problemReporter().incorrectLocationForEmptyDimension(this, i);
133                         }
134                 }
135
136                 // explicitDimIndex < 0 says if all dimensions are nulled
137                 // when an initializer is given, no dimension must be specified
138                 if (initializer == null) {
139                         if (explicitDimIndex < 0) {
140                                 scope.problemReporter().mustDefineDimensionsOrInitializer(this);
141                         }
142                 } else if (explicitDimIndex >= 0) {
143                         scope.problemReporter().cannotDefineDimensionsAndInitializer(this);
144                 }
145
146                 // dimensions resolution 
147                 for (int i = 0; i <= explicitDimIndex; i++) {
148                         if (dimensions[i] != null) {
149                                 TypeBinding dimensionType = dimensions[i].resolveTypeExpecting(scope, IntBinding);
150                                 if (dimensionType != null) {
151                                         dimensions[i].implicitWidening(IntBinding, dimensionType);
152                                 }
153                         }
154                 }
155
156                 // building the array binding
157                 if (referenceType != null) {
158                         if (dimensions.length > 255) {
159                                 scope.problemReporter().tooManyDimensions(this);
160                         }
161                         this.resolvedType = scope.createArray(referenceType, dimensions.length);
162
163                         // check the initializer
164                         if (initializer != null) {
165                                 if ((initializer.resolveTypeExpecting(scope, this.resolvedType)) != null)
166                                         initializer.binding = (ArrayBinding)this.resolvedType;
167                         }
168                 }
169                 return this.resolvedType;
170         }
171
172
173         public void traverse(ASTVisitor visitor, BlockScope scope) {
174
175                 if (visitor.visit(this, scope)) {
176                         int dimensionsLength = dimensions.length;
177                         type.traverse(visitor, scope);
178                         for (int i = 0; i < dimensionsLength; i++) {
179                                 if (dimensions[i] != null)
180                                         dimensions[i].traverse(visitor, scope);
181                         }
182                         if (initializer != null)
183                                 initializer.traverse(visitor, scope);
184                 }
185                 visitor.endVisit(this, scope);
186         }
187 }