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.NullConstant;
18 import net.sourceforge.phpdt.internal.compiler.lookup.ArrayBinding;
19 import net.sourceforge.phpdt.internal.compiler.lookup.BaseTypeBinding;
20 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
21 import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
23 public class ArrayInitializer extends Expression {
24 public Expression[] expressions;
25 public ArrayBinding binding; //the type of the { , , , }
28 * ArrayInitializer constructor comment.
30 public ArrayInitializer() {
33 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
34 if (expressions != null) {
35 for (int i = 0, max = expressions.length; i < max; i++) {
36 flowInfo = expressions[i].analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
42 * Code generation for a array initializer
44 public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
45 // Flatten the values and compute the dimensions, by iterating in depth into nested array initializers
47 int pc = codeStream.position;
48 int expressionLength = (expressions == null) ? 0: expressions.length;
49 codeStream.generateInlinedValue(expressionLength);
50 codeStream.newArray(currentScope, binding);
51 if (expressions != null) {
52 // binding is an ArrayType, so I can just deal with the dimension
53 int elementsTypeID = binding.dimensions > 1 ? -1 : binding.leafComponentType.id;
54 for (int i = 0; i < expressionLength; i++) {
56 if ((expr = expressions[i]).constant != NotAConstant) {
57 switch (elementsTypeID) { // filter out initializations to default values
65 if (expr.constant.doubleValue() != 0) {
67 codeStream.generateInlinedValue(i);
68 expr.generateCode(currentScope, codeStream, true);
69 codeStream.arrayAtPut(elementsTypeID, false);
73 if (expr.constant.booleanValue() != false) {
75 codeStream.generateInlinedValue(i);
76 expr.generateCode(currentScope, codeStream, true);
77 codeStream.arrayAtPut(elementsTypeID, false);
81 if (expr.constant != NullConstant.Default) {
83 codeStream.generateInlinedValue(i);
84 expr.generateCode(currentScope, codeStream, true);
85 codeStream.arrayAtPut(elementsTypeID, false);
90 codeStream.generateInlinedValue(i);
91 expr.generateCode(currentScope, codeStream, true);
92 codeStream.arrayAtPut(elementsTypeID, false);
99 codeStream.recordPositionsFrom(pc, this.sourceStart);
101 public TypeBinding resolveTypeExpecting(BlockScope scope, TypeBinding expectedTb) {
102 // Array initializers can only occur on the right hand side of an assignment
103 // expression, therefore the expected type contains the valid information
104 // concerning the type that must be enforced by the elements of the array initializer.
106 // this method is recursive... (the test on isArrayType is the stop case)
108 constant = NotAConstant;
109 if (expectedTb.isArrayType()) {
110 binding = (ArrayBinding) expectedTb;
111 if (expressions == null)
113 TypeBinding expectedElementsTb = binding.elementsType(scope);
114 if (expectedElementsTb.isBaseType()) {
115 for (int i = 0, length = expressions.length; i < length; i++) {
116 Expression expression = expressions[i];
117 TypeBinding expressionTb =
118 (expression instanceof ArrayInitializer)
119 ? expression.resolveTypeExpecting(scope, expectedElementsTb)
120 : expression.resolveType(scope);
121 if (expressionTb == null)
124 // Compile-time conversion required?
125 if (expression.isConstantValueOfTypeAssignableToType(expressionTb, expectedElementsTb)) {
126 expression.implicitWidening(expectedElementsTb, expressionTb);
127 } else if (BaseTypeBinding.isWidening(expectedElementsTb.id, expressionTb.id)) {
128 expression.implicitWidening(expectedElementsTb, expressionTb);
130 scope.problemReporter().typeMismatchErrorActualTypeExpectedType(expression, expressionTb, expectedElementsTb);
135 for (int i = 0, length = expressions.length; i < length; i++)
136 if (expressions[i].resolveTypeExpecting(scope, expectedElementsTb) == null)
142 // infer initializer type for error reporting based on first element
143 TypeBinding leafElementType = null;
145 if (expressions == null) {
146 leafElementType = scope.getJavaLangObject();
148 Expression currentExpression = expressions[0];
149 while(currentExpression != null && currentExpression instanceof ArrayInitializer) {
151 Expression[] subExprs = ((ArrayInitializer) currentExpression).expressions;
152 if (subExprs == null){
153 leafElementType = scope.getJavaLangObject();
154 currentExpression = null;
157 currentExpression = ((ArrayInitializer) currentExpression).expressions[0];
159 if (currentExpression != null) {
160 leafElementType = currentExpression.resolveType(scope);
163 if (leafElementType != null) {
164 TypeBinding probableTb = scope.createArray(leafElementType, dim);
165 scope.problemReporter().typeMismatchErrorActualTypeExpectedType(this, probableTb, expectedTb);
169 public String toStringExpression() {
171 String s = "{" ; //$NON-NLS-1$
172 if (expressions != null)
174 for (int i = 0 ; i < expressions.length ; i++)
175 { s = s + expressions[i].toStringExpression() + "," ; //$NON-NLS-1$
178 { s = s + "\n "; j = 20;}}}; //$NON-NLS-1$
179 s = s + "}"; //$NON-NLS-1$
182 public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
183 if (visitor.visit(this, scope)) {
184 if (expressions != null) {
185 int expressionsLength = expressions.length;
186 for (int i = 0; i < expressionsLength; i++)
187 expressions[i].traverse(visitor, scope);
190 visitor.endVisit(this, scope);