/** Code generation for a array allocation expression */
  public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {

    int pc = codeStream.position;

    if (initializer != null) {
      initializer.generateCode(currentScope, codeStream, valueRequired);
      return;
    }

    int nonNullDimensionsLength = 0;
    for (int i = 0, max = dimensions.length; i < max; i++)
      if (dimensions[i] != null) {
        dimensions[i].generateCode(currentScope, codeStream, true);
        nonNullDimensionsLength++;
      }

    // Generate a sequence of bytecodes corresponding to an array allocation
    if (this.resolvedType.dimensions() == 1) {
      // Mono-dimensional array
      codeStream.newArray((ArrayBinding) this.resolvedType);
    } else {
      // Multi-dimensional array
      codeStream.multianewarray(this.resolvedType, nonNullDimensionsLength);
    }

    if (valueRequired) {
      codeStream.generateImplicitConversion(implicitConversion);
    } else {
      codeStream.pop();
    }

    codeStream.recordPositionsFrom(pc, this.sourceStart);
  }
 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
   for (int i = 0, max = dimensions.length; i < max; i++) {
     Expression dim;
     if ((dim = dimensions[i]) != null) {
       flowInfo = dim.analyseCode(currentScope, flowContext, flowInfo);
     }
   }
   if (initializer != null) {
     return initializer.analyseCode(currentScope, flowContext, flowInfo);
   }
   return flowInfo;
 }
  public void traverse(ASTVisitor visitor, BlockScope scope) {

    if (visitor.visit(this, scope)) {
      int dimensionsLength = dimensions.length;
      type.traverse(visitor, scope);
      for (int i = 0; i < dimensionsLength; i++) {
        if (dimensions[i] != null) dimensions[i].traverse(visitor, scope);
      }
      if (initializer != null) initializer.traverse(visitor, scope);
    }
    visitor.endVisit(this, scope);
  }
  public StringBuffer printExpression(int indent, StringBuffer output) {

    output.append("new "); // $NON-NLS-1$
    type.print(0, output);
    for (int i = 0; i < dimensions.length; i++) {
      if (dimensions[i] == null) output.append("[]"); // $NON-NLS-1$
      else {
        output.append('[');
        dimensions[i].printExpression(0, output);
        output.append(']');
      }
    }
    if (initializer != null) initializer.printExpression(0, output);
    return output;
  }
  public TypeBinding resolveType(BlockScope scope) {

    // Build an array type reference using the current dimensions
    // The parser does not check for the fact that dimension may be null
    // only at the -end- like new int [4][][]. The parser allows new int[][4][]
    // so this must be checked here......(this comes from a reduction to LL1 grammar)

    TypeBinding referenceType = type.resolveType(scope, true /* check bounds*/);

    // will check for null after dimensions are checked
    constant = Constant.NotAConstant;
    if (referenceType == VoidBinding) {
      scope.problemReporter().cannotAllocateVoidArray(this);
      referenceType = null;
    }

    // check the validity of the dimension syntax (and test for all null dimensions)
    int explicitDimIndex = -1;
    loop:
    for (int i = dimensions.length; --i >= 0; ) {
      if (dimensions[i] != null) {
        if (explicitDimIndex < 0) explicitDimIndex = i;
      } else if (explicitDimIndex > 0) {
        // should not have an empty dimension before an non-empty one
        scope.problemReporter().incorrectLocationForNonEmptyDimension(this, explicitDimIndex);
        break loop;
      }
    }

    // explicitDimIndex < 0 says if all dimensions are nulled
    // when an initializer is given, no dimension must be specified
    if (initializer == null) {
      if (explicitDimIndex < 0) {
        scope.problemReporter().mustDefineDimensionsOrInitializer(this);
      }
      // allow new List<?>[5] - only check for generic array when no initializer, since also checked
      // inside initializer resolution
      if (referenceType != null && !referenceType.isReifiable()) {
        scope.problemReporter().illegalGenericArray(referenceType, this);
      }
    } else if (explicitDimIndex >= 0) {
      scope.problemReporter().cannotDefineDimensionsAndInitializer(this);
    }

    // dimensions resolution
    for (int i = 0; i <= explicitDimIndex; i++) {
      if (dimensions[i] != null) {
        TypeBinding dimensionType = dimensions[i].resolveTypeExpecting(scope, IntBinding);
        if (dimensionType != null) {
          dimensions[i].computeConversion(scope, IntBinding, dimensionType);
        }
      }
    }

    // building the array binding
    if (referenceType != null) {
      if (dimensions.length > 255) {
        scope.problemReporter().tooManyDimensions(this);
      }
      this.resolvedType = scope.createArrayType(referenceType, dimensions.length);

      // check the initializer
      if (initializer != null) {
        if ((initializer.resolveTypeExpecting(scope, this.resolvedType)) != null)
          initializer.binding = (ArrayBinding) this.resolvedType;
      }
    }
    return this.resolvedType;
  }