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.impl.*;
15 import net.sourceforge.phpdt.internal.compiler.codegen.*;
16 import net.sourceforge.phpdt.internal.compiler.flow.*;
17 import net.sourceforge.phpdt.internal.compiler.lookup.*;
19 public class ArrayInitializer extends Expression {
20 public Expression[] expressions;
21 public ArrayBinding binding; //the type of the { , , , }
24 * ArrayInitializer constructor comment.
26 public ArrayInitializer() {
29 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
30 if (expressions != null) {
31 for (int i = 0, max = expressions.length; i < max; i++) {
32 flowInfo = expressions[i].analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
38 * Code generation for a array initializer
40 public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
41 // Flatten the values and compute the dimensions, by iterating in depth into nested array initializers
43 int pc = codeStream.position;
44 int expressionLength = (expressions == null) ? 0: expressions.length;
45 codeStream.generateInlinedValue(expressionLength);
46 codeStream.newArray(currentScope, binding);
47 if (expressions != null) {
48 // binding is an ArrayType, so I can just deal with the dimension
49 int elementsTypeID = binding.dimensions > 1 ? -1 : binding.leafComponentType.id;
50 for (int i = 0; i < expressionLength; i++) {
52 if ((expr = expressions[i]).constant != NotAConstant) {
53 switch (elementsTypeID) { // filter out initializations to default values
61 if (expr.constant.doubleValue() != 0) {
63 codeStream.generateInlinedValue(i);
64 expr.generateCode(currentScope, codeStream, true);
65 codeStream.arrayAtPut(elementsTypeID, false);
69 if (expr.constant.booleanValue() != false) {
71 codeStream.generateInlinedValue(i);
72 expr.generateCode(currentScope, codeStream, true);
73 codeStream.arrayAtPut(elementsTypeID, false);
77 if (expr.constant != NullConstant.Default) {
79 codeStream.generateInlinedValue(i);
80 expr.generateCode(currentScope, codeStream, true);
81 codeStream.arrayAtPut(elementsTypeID, false);
86 codeStream.generateInlinedValue(i);
87 expr.generateCode(currentScope, codeStream, true);
88 codeStream.arrayAtPut(elementsTypeID, false);
95 codeStream.recordPositionsFrom(pc, this.sourceStart);
97 public TypeBinding resolveTypeExpecting(BlockScope scope, TypeBinding expectedTb) {
98 // Array initializers can only occur on the right hand side of an assignment
99 // expression, therefore the expected type contains the valid information
100 // concerning the type that must be enforced by the elements of the array initializer.
102 // this method is recursive... (the test on isArrayType is the stop case)
104 constant = NotAConstant;
105 if (expectedTb.isArrayType()) {
106 binding = (ArrayBinding) expectedTb;
107 if (expressions == null)
109 TypeBinding expectedElementsTb = binding.elementsType(scope);
110 if (expectedElementsTb.isBaseType()) {
111 for (int i = 0, length = expressions.length; i < length; i++) {
112 Expression expression = expressions[i];
113 TypeBinding expressionTb =
114 (expression instanceof ArrayInitializer)
115 ? expression.resolveTypeExpecting(scope, expectedElementsTb)
116 : expression.resolveType(scope);
117 if (expressionTb == null)
120 // Compile-time conversion required?
121 if (expression.isConstantValueOfTypeAssignableToType(expressionTb, expectedElementsTb)) {
122 expression.implicitWidening(expectedElementsTb, expressionTb);
123 } else if (BaseTypeBinding.isWidening(expectedElementsTb.id, expressionTb.id)) {
124 expression.implicitWidening(expectedElementsTb, expressionTb);
126 scope.problemReporter().typeMismatchErrorActualTypeExpectedType(expression, expressionTb, expectedElementsTb);
131 for (int i = 0, length = expressions.length; i < length; i++)
132 if (expressions[i].resolveTypeExpecting(scope, expectedElementsTb) == null)
138 // infer initializer type for error reporting based on first element
139 TypeBinding leafElementType = null;
141 if (expressions == null) {
142 leafElementType = scope.getJavaLangObject();
144 Expression currentExpression = expressions[0];
145 while(currentExpression != null && currentExpression instanceof ArrayInitializer) {
147 Expression[] subExprs = ((ArrayInitializer) currentExpression).expressions;
148 if (subExprs == null){
149 leafElementType = scope.getJavaLangObject();
150 currentExpression = null;
153 currentExpression = ((ArrayInitializer) currentExpression).expressions[0];
155 if (currentExpression != null) {
156 leafElementType = currentExpression.resolveType(scope);
159 if (leafElementType != null) {
160 TypeBinding probableTb = scope.createArray(leafElementType, dim);
161 scope.problemReporter().typeMismatchErrorActualTypeExpectedType(this, probableTb, expectedTb);
165 public String toStringExpression() {
167 String s = "{" ; //$NON-NLS-1$
168 if (expressions != null)
170 for (int i = 0 ; i < expressions.length ; i++)
171 { s = s + expressions[i].toStringExpression() + "," ; //$NON-NLS-1$
174 { s = s + "\n "; j = 20;}}}; //$NON-NLS-1$
175 s = s + "}"; //$NON-NLS-1$
178 public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
179 if (visitor.visit(this, scope)) {
180 if (expressions != null) {
181 int expressionsLength = expressions.length;
182 for (int i = 0; i < expressionsLength; i++)
183 expressions[i].traverse(visitor, scope);
186 visitor.endVisit(this, scope);