1 /*******************************************************************************
2 * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v0.5
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v05.html
9 * IBM Corporation - initial API and implementation
10 ******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.ast;
13 import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
14 import net.sourceforge.phpdt.internal.compiler.codegen.CodeStream;
15 import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
16 import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
17 import net.sourceforge.phpdt.internal.compiler.impl.Constant;
18 import net.sourceforge.phpdt.internal.compiler.lookup.ArrayBinding;
19 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
20 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;
31 public ArrayBinding arrayTb;
34 * ArrayAllocationExpression constructor comment.
36 public ArrayAllocationExpression() {
40 public FlowInfo analyseCode(
41 BlockScope currentScope,
42 FlowContext flowContext,
44 for (int i = 0, max = dimensions.length; i < max; i++) {
46 if ((dim = dimensions[i]) != null) {
47 flowInfo = dim.analyseCode(currentScope, flowContext, flowInfo);
50 if (initializer != null) {
51 return initializer.analyseCode(currentScope, flowContext, flowInfo);
58 * Code generation for a array allocation expression
60 public void generateCode(
61 BlockScope currentScope,
62 CodeStream codeStream,
63 boolean valueRequired) {
65 int pc = codeStream.position;
66 ArrayBinding arrayBinding;
68 if (initializer != null) {
69 initializer.generateCode(currentScope, codeStream, valueRequired);
73 int nonNullDimensionsLength = 0;
74 for (int i = 0, max = dimensions.length; i < max; i++)
75 if (dimensions[i] != null) {
76 dimensions[i].generateCode(currentScope, codeStream, true);
77 nonNullDimensionsLength++;
80 // Generate a sequence of bytecodes corresponding to an array allocation
81 if ((arrayTb.isArrayType())
82 && ((arrayBinding = (ArrayBinding) arrayTb).dimensions == 1)) {
83 // Mono-dimensional array
84 codeStream.newArray(currentScope, arrayBinding);
86 // Multi-dimensional array
87 codeStream.multianewarray(arrayTb, nonNullDimensionsLength);
91 codeStream.generateImplicitConversion(implicitConversion);
96 codeStream.recordPositionsFrom(pc, this.sourceStart);
99 public TypeBinding resolveType(BlockScope scope) {
101 // Build an array type reference using the current dimensions
102 // The parser does not check for the fact that dimension may be null
103 // only at the -end- like new int [4][][]. The parser allows new int[][4][]
104 // so this must be checked here......(this comes from a reduction to LL1 grammar)
106 TypeBinding referenceTb = type.resolveType(scope);
107 // will check for null after dimensions are checked
108 constant = Constant.NotAConstant;
109 if (referenceTb == VoidBinding) {
110 scope.problemReporter().cannotAllocateVoidArray(this);
111 referenceTb = null; // will return below
114 // check the validity of the dimension syntax (and test for all null dimensions)
116 for (int i = dimensions.length; --i >= 0;) {
117 if (dimensions[i] != null) {
122 // should not have an empty dimension before an non-empty one
123 scope.problemReporter().incorrectLocationForEmptyDimension(this, i);
127 if (referenceTb == null)
130 // lengthDim == -1 says if all dimensions are nulled
131 // when an initializer is given, no dimension must be specified
132 if (initializer == null) {
133 if (lengthDim == -1) {
134 scope.problemReporter().mustDefineDimensionsOrInitializer(this);
137 } else if (lengthDim != -1) {
138 scope.problemReporter().cannotDefineDimensionsAndInitializer(this);
142 // dimensions resolution
143 for (int i = 0; i <= lengthDim; i++) {
144 TypeBinding dimTb = dimensions[i].resolveTypeExpecting(scope, IntBinding);
147 dimensions[i].implicitWidening(IntBinding, dimTb);
150 // building the array binding
151 arrayTb = scope.createArray(referenceTb, dimensions.length);
153 // check the initializer
154 if (initializer != null)
155 if ((initializer.resolveTypeExpecting(scope, arrayTb)) != null)
156 initializer.binding = arrayTb;
160 public String toStringExpression() {
162 String s = "new " + type.toString(0); //$NON-NLS-1$
163 for (int i = 0; i < dimensions.length; i++) {
164 if (dimensions[i] == null)
165 s = s + "[]"; //$NON-NLS-1$
167 s = s + "[" + dimensions[i].toStringExpression() + "]"; //$NON-NLS-2$ //$NON-NLS-1$
169 if (initializer != null)
170 s = s + initializer.toStringExpression();
174 public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
176 if (visitor.visit(this, scope)) {
177 int dimensionsLength = dimensions.length;
178 type.traverse(visitor, scope);
179 for (int i = 0; i < dimensionsLength; i++) {
180 if (dimensions[i] != null)
181 dimensions[i].traverse(visitor, scope);
183 if (initializer != null)
184 initializer.traverse(visitor, scope);
186 visitor.endVisit(this, scope);