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
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package org.eclipse.jdt.internal.compiler.ast;
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.*;
19 public class ArrayAllocationExpression extends Expression {
21 public TypeReference type;
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;
29 * ArrayAllocationExpression constructor comment.
31 public ArrayAllocationExpression() {
35 public FlowInfo analyseCode(
36 BlockScope currentScope,
37 FlowContext flowContext,
39 for (int i = 0, max = dimensions.length; i < max; i++) {
41 if ((dim = dimensions[i]) != null) {
42 flowInfo = dim.analyseCode(currentScope, flowContext, flowInfo);
45 if (initializer != null) {
46 return initializer.analyseCode(currentScope, flowContext, flowInfo);
52 * Code generation for a array allocation expression
54 public void generateCode(
55 BlockScope currentScope,
56 CodeStream codeStream,
57 boolean valueRequired) {
59 int pc = codeStream.position;
61 if (initializer != null) {
62 initializer.generateCode(currentScope, codeStream, valueRequired);
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++;
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);
78 // Multi-dimensional array
79 codeStream.multianewarray(this.resolvedType, nonNullDimensionsLength);
83 codeStream.generateImplicitConversion(implicitConversion);
88 codeStream.recordPositionsFrom(pc, this.sourceStart);
92 public StringBuffer printExpression(int indent, StringBuffer output) {
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$
101 dimensions[i].printExpression(0, output);
105 if (initializer != null) initializer.printExpression(0, output);
109 public TypeBinding resolveType(BlockScope scope) {
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)
116 TypeBinding referenceType = type.resolveType(scope);
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;
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);
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);
142 } else if (explicitDimIndex >= 0) {
143 scope.problemReporter().cannotDefineDimensionsAndInitializer(this);
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);
156 // building the array binding
157 if (referenceType != null) {
158 if (dimensions.length > 255) {
159 scope.problemReporter().tooManyDimensions(this);
161 this.resolvedType = scope.createArray(referenceType, dimensions.length);
163 // check the initializer
164 if (initializer != null) {
165 if ((initializer.resolveTypeExpecting(scope, this.resolvedType)) != null)
166 initializer.binding = (ArrayBinding)this.resolvedType;
169 return this.resolvedType;
173 public void traverse(ASTVisitor visitor, BlockScope scope) {
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);
182 if (initializer != null)
183 initializer.traverse(visitor, scope);
185 visitor.endVisit(this, scope);