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;
 
  21 public class ArrayAllocationExpression extends Expression {
 
  23         public TypeReference type;
 
  25         // dimensions.length gives the number of dimensions, but the
 
  26         // last ones may be nulled as in new int[4][5][][]
 
  27         public Expression[] dimensions;
 
  29         public ArrayInitializer initializer;
 
  32          * ArrayAllocationExpression constructor comment.
 
  34         public ArrayAllocationExpression() {
 
  38         public FlowInfo analyseCode(BlockScope currentScope,
 
  39                         FlowContext flowContext, FlowInfo flowInfo) {
 
  40                 for (int i = 0, max = dimensions.length; i < max; i++) {
 
  42                         if ((dim = dimensions[i]) != null) {
 
  43                                 flowInfo = dim.analyseCode(currentScope, flowContext, flowInfo);
 
  46                 if (initializer != null) {
 
  47                         return initializer.analyseCode(currentScope, flowContext, flowInfo);
 
  54          * Code generation for a array allocation expression
 
  56         // public void generateCode(
 
  57         // BlockScope currentScope,
 
  58         // CodeStream codeStream,
 
  59         // boolean valueRequired) {
 
  61         // int pc = codeStream.position;
 
  63         // if (initializer != null) {
 
  64         // initializer.generateCode(currentScope, codeStream, valueRequired);
 
  68         // int nonNullDimensionsLength = 0;
 
  69         // for (int i = 0, max = dimensions.length; i < max; i++)
 
  70         // if (dimensions[i] != null) {
 
  71         // dimensions[i].generateCode(currentScope, codeStream, true);
 
  72         // nonNullDimensionsLength++;
 
  75         // // Generate a sequence of bytecodes corresponding to an array allocation
 
  76         // if (this.resolvedType.dimensions() == 1) {
 
  77         // // Mono-dimensional array
 
  78         // codeStream.newArray(currentScope, (ArrayBinding)this.resolvedType);
 
  80         // // Multi-dimensional array
 
  81         // codeStream.multianewarray(this.resolvedType, nonNullDimensionsLength);
 
  84         // if (valueRequired) {
 
  85         // codeStream.generateImplicitConversion(implicitConversion);
 
  90         // 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)
 
 106                         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
 
 116                 // so this must be checked here......(this comes from a reduction to LL1
 
 119                 TypeBinding referenceType = type.resolveType(scope);
 
 121                 // will check for null after dimensions are checked
 
 122                 constant = Constant.NotAConstant;
 
 123                 if (referenceType == VoidBinding) {
 
 124                         scope.problemReporter().cannotAllocateVoidArray(this);
 
 125                         referenceType = null;
 
 128                 // check the validity of the dimension syntax (and test for all null
 
 130                 int explicitDimIndex = -1;
 
 131                 for (int i = dimensions.length; --i >= 0;) {
 
 132                         if (dimensions[i] != null) {
 
 133                                 if (explicitDimIndex < 0)
 
 134                                         explicitDimIndex = i;
 
 135                         } else if (explicitDimIndex > 0) {
 
 136                                 // should not have an empty dimension before an non-empty one
 
 137                                 scope.problemReporter().incorrectLocationForEmptyDimension(
 
 142                 // explicitDimIndex < 0 says if all dimensions are nulled
 
 143                 // when an initializer is given, no dimension must be specified
 
 144                 if (initializer == null) {
 
 145                         if (explicitDimIndex < 0) {
 
 146                                 scope.problemReporter().mustDefineDimensionsOrInitializer(this);
 
 148                 } else if (explicitDimIndex >= 0) {
 
 149                         scope.problemReporter().cannotDefineDimensionsAndInitializer(this);
 
 152                 // dimensions resolution
 
 153                 for (int i = 0; i <= explicitDimIndex; i++) {
 
 154                         if (dimensions[i] != null) {
 
 155                                 TypeBinding dimensionType = dimensions[i].resolveTypeExpecting(
 
 157                                 if (dimensionType != null) {
 
 158                                         dimensions[i].implicitWidening(IntBinding, dimensionType);
 
 163                 // building the array binding
 
 164                 if (referenceType != null) {
 
 165                         if (dimensions.length > 255) {
 
 166                                 scope.problemReporter().tooManyDimensions(this);
 
 168                         this.resolvedType = scope.createArray(referenceType,
 
 171                         // check the initializer
 
 172                         if (initializer != null) {
 
 173                                 if ((initializer.resolveTypeExpecting(scope, this.resolvedType)) != null)
 
 174                                         initializer.binding = (ArrayBinding) this.resolvedType;
 
 177                 return this.resolvedType;
 
 180         public String toStringExpression() {
 
 182                 String s = "new " + type.toString(0); //$NON-NLS-1$
 
 183                 for (int i = 0; i < dimensions.length; i++) {
 
 184                         if (dimensions[i] == null)
 
 185                                 s = s + "[]"; //$NON-NLS-1$
 
 187                                 s = s + "[" + dimensions[i].toStringExpression() + "]"; //$NON-NLS-2$ //$NON-NLS-1$
 
 189                 if (initializer != null)
 
 190                         s = s + initializer.toStringExpression();
 
 194         public void traverse(ASTVisitor visitor, BlockScope scope) {
 
 196                 if (visitor.visit(this, scope)) {
 
 197                         int dimensionsLength = dimensions.length;
 
 198                         type.traverse(visitor, scope);
 
 199                         for (int i = 0; i < dimensionsLength; i++) {
 
 200                                 if (dimensions[i] != null)
 
 201                                         dimensions[i].traverse(visitor, scope);
 
 203                         if (initializer != null)
 
 204                                 initializer.traverse(visitor, scope);
 
 206                 visitor.endVisit(this, scope);