Skip to main content
summaryrefslogtreecommitdiffstats
blob: fab10057d7d129b3ac8c46b1aeef97d3a04e8703 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package org.eclipse.jdt.internal.compiler.ast;

/*
 * (c) Copyright IBM Corp. 2000, 2001.
 * All Rights Reserved.
 */
import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
import org.eclipse.jdt.internal.compiler.impl.*;
import org.eclipse.jdt.internal.compiler.codegen.*;
import org.eclipse.jdt.internal.compiler.flow.*;
import org.eclipse.jdt.internal.compiler.lookup.*;

public class ArrayAllocationExpression extends Expression {
	public TypeReference type;

	//dimensions.length gives the number of dimensions, but the
	// last ones may be nulled as in new int[4][5][][]
	public Expression[] dimensions;
	public ArrayInitializer initializer;

	public ArrayBinding arrayTb;
/**
 * ArrayAllocationExpression constructor comment.
 */
public ArrayAllocationExpression() {
	super();
}
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);
	} else {
		return flowInfo;
	}
}
/**
 * Code generation for a array allocation expression
 */
public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {

	int pc = codeStream.position;
	ArrayBinding arrayBinding;
	
	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 ((arrayTb.isArrayType()) && ((arrayBinding = (ArrayBinding) arrayTb).dimensions == 1)) {
		// Mono-dimensional array
		codeStream.newArray(currentScope, arrayBinding);
	} else {
		// Multi-dimensional array
		codeStream.multianewarray(arrayTb, nonNullDimensionsLength);
	}
 
	if (valueRequired) {
		codeStream.generateImplicitConversion(implicitConversion);
	} else {
		codeStream.pop();
	}

	codeStream.recordPositionsFrom(pc, this);
}
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 referenceTb = type.resolveType(scope); // will check for null after dimensions are checked
	constant = Constant.NotAConstant;
	if (referenceTb == VoidBinding) {
		scope.problemReporter().cannotAllocateVoidArray(this);
		referenceTb = null; // will return below
	}

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

	// lengthDim == -1 says if all dimensions are nulled
	// when an initializer is given, no dimension must be specified
	if (initializer == null) {
		if (lengthDim == -1) {
			scope.problemReporter().mustDefineDimensionsOrInitializer(this);
			return null;
		}
	} else if (lengthDim != -1) {
		scope.problemReporter().cannotDefineDimensionsAndInitializer(this);
		return null;
	}

	// dimensions resolution 
	for (int i = 0; i <= lengthDim; i++) {
		TypeBinding dimTb = dimensions[i].resolveTypeExpecting(scope, IntBinding);
		if (dimTb == null)
			return null;
		dimensions[i].implicitWidening(IntBinding, dimTb);
	}

	// building the array binding
	arrayTb = scope.createArray(referenceTb, dimensions.length);

	// check the initializer
	if (initializer != null)
		if ((initializer.resolveTypeExpecting(scope, arrayTb)) != null)
			initializer.binding = arrayTb;
	return arrayTb;
}
public String toStringExpression() {
	/* slow code */

	String s = "new " + type.toString(0);
	for (int i = 0 ; i < dimensions.length ; i++)
	{	if (dimensions[i] == null)
			s = s + "[]";
		else
			s = s + "[" + dimensions[i].toStringExpression() + "]" ;}
	if (initializer != null)
		s = s + initializer.toStringExpression();
	return s;}
public void traverse(IAbstractSyntaxTreeVisitor 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);
}
}

Back to the top