1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 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 net.sourceforge.phpdt.internal.compiler.ast;
13 import net.sourceforge.phpdt.internal.compiler.ASTVisitor;
14 import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
15 import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
16 import net.sourceforge.phpdt.internal.compiler.impl.Constant;
17 import net.sourceforge.phpdt.internal.compiler.lookup.ArrayBinding;
18 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
19 import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
22 public class ArrayAllocationExpression extends Expression {
24 public TypeReference type;
26 //dimensions.length gives the number of dimensions, but the
27 // last ones may be nulled as in new int[4][5][][]
28 public Expression[] dimensions;
29 public ArrayInitializer initializer;
32 * ArrayAllocationExpression constructor comment.
34 public ArrayAllocationExpression() {
38 public FlowInfo analyseCode(
39 BlockScope currentScope,
40 FlowContext flowContext,
42 for (int i = 0, max = dimensions.length; i < max; i++) {
44 if ((dim = dimensions[i]) != null) {
45 flowInfo = dim.analyseCode(currentScope, flowContext, flowInfo);
48 if (initializer != null) {
49 return initializer.analyseCode(currentScope, flowContext, flowInfo);
56 * Code generation for a array allocation expression
58 // public void generateCode(
59 // BlockScope currentScope,
60 // CodeStream codeStream,
61 // boolean valueRequired) {
63 // int pc = codeStream.position;
65 // if (initializer != null) {
66 // initializer.generateCode(currentScope, codeStream, valueRequired);
70 // int nonNullDimensionsLength = 0;
71 // for (int i = 0, max = dimensions.length; i < max; i++)
72 // if (dimensions[i] != null) {
73 // dimensions[i].generateCode(currentScope, codeStream, true);
74 // nonNullDimensionsLength++;
77 // // Generate a sequence of bytecodes corresponding to an array allocation
78 // if (this.resolvedType.dimensions() == 1) {
79 // // Mono-dimensional array
80 // codeStream.newArray(currentScope, (ArrayBinding)this.resolvedType);
82 // // Multi-dimensional array
83 // codeStream.multianewarray(this.resolvedType, nonNullDimensionsLength);
86 // if (valueRequired) {
87 // codeStream.generateImplicitConversion(implicitConversion);
92 // codeStream.recordPositionsFrom(pc, this.sourceStart);
94 public StringBuffer printExpression(int indent, StringBuffer output) {
96 output.append("new "); //$NON-NLS-1$
97 type.print(0, output);
98 for (int i = 0; i < dimensions.length; i++) {
99 if (dimensions[i] == null)
100 output.append("[]"); //$NON-NLS-1$
103 dimensions[i].printExpression(0, output);
107 if (initializer != null) initializer.printExpression(0, output);
110 public TypeBinding resolveType(BlockScope scope) {
112 // Build an array type reference using the current dimensions
113 // The parser does not check for the fact that dimension may be null
114 // only at the -end- like new int [4][][]. The parser allows new int[][4][]
115 // so this must be checked here......(this comes from a reduction to LL1 grammar)
117 TypeBinding referenceType = type.resolveType(scope);
119 // will check for null after dimensions are checked
120 constant = Constant.NotAConstant;
121 if (referenceType == VoidBinding) {
122 scope.problemReporter().cannotAllocateVoidArray(this);
123 referenceType = null;
126 // check the validity of the dimension syntax (and test for all null dimensions)
127 int explicitDimIndex = -1;
128 for (int i = dimensions.length; --i >= 0;) {
129 if (dimensions[i] != null) {
130 if (explicitDimIndex < 0) explicitDimIndex = i;
131 } else if (explicitDimIndex> 0) {
132 // should not have an empty dimension before an non-empty one
133 scope.problemReporter().incorrectLocationForEmptyDimension(this, i);
137 // explicitDimIndex < 0 says if all dimensions are nulled
138 // when an initializer is given, no dimension must be specified
139 if (initializer == null) {
140 if (explicitDimIndex < 0) {
141 scope.problemReporter().mustDefineDimensionsOrInitializer(this);
143 } else if (explicitDimIndex >= 0) {
144 scope.problemReporter().cannotDefineDimensionsAndInitializer(this);
147 // dimensions resolution
148 for (int i = 0; i <= explicitDimIndex; i++) {
149 if (dimensions[i] != null) {
150 TypeBinding dimensionType = dimensions[i].resolveTypeExpecting(scope, IntBinding);
151 if (dimensionType != null) {
152 dimensions[i].implicitWidening(IntBinding, dimensionType);
157 // building the array binding
158 if (referenceType != null) {
159 if (dimensions.length > 255) {
160 scope.problemReporter().tooManyDimensions(this);
162 this.resolvedType = scope.createArray(referenceType, dimensions.length);
164 // check the initializer
165 if (initializer != null) {
166 if ((initializer.resolveTypeExpecting(scope, this.resolvedType)) != null)
167 initializer.binding = (ArrayBinding)this.resolvedType;
170 return this.resolvedType;
173 public String toStringExpression() {
175 String s = "new " + type.toString(0); //$NON-NLS-1$
176 for (int i = 0; i < dimensions.length; i++) {
177 if (dimensions[i] == null)
178 s = s + "[]"; //$NON-NLS-1$
180 s = s + "[" + dimensions[i].toStringExpression() + "]"; //$NON-NLS-2$ //$NON-NLS-1$
182 if (initializer != null)
183 s = s + initializer.toStringExpression();
187 public void traverse(ASTVisitor visitor, BlockScope scope) {
189 if (visitor.visit(this, scope)) {
190 int dimensionsLength = dimensions.length;
191 type.traverse(visitor, scope);
192 for (int i = 0; i < dimensionsLength; i++) {
193 if (dimensions[i] != null)
194 dimensions[i].traverse(visitor, scope);
196 if (initializer != null)
197 initializer.traverse(visitor, scope);
199 visitor.endVisit(this, scope);