1 /*******************************************************************************
2 * Copyright (c) 2000, 2004 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 org.eclipse.jdt.internal.compiler.ast;
13 import org.eclipse.jdt.internal.compiler.ASTVisitor;
14 import org.eclipse.jdt.internal.compiler.impl.*;
15 import org.eclipse.jdt.internal.compiler.codegen.*;
16 import org.eclipse.jdt.internal.compiler.flow.*;
17 import org.eclipse.jdt.internal.compiler.lookup.*;
19 public class ArrayReference extends Reference {
21 public Expression receiver;
22 public Expression position;
24 public ArrayReference(Expression rec, Expression pos) {
27 sourceStart = rec.sourceStart;
30 public FlowInfo analyseAssignment(
31 BlockScope currentScope,
32 FlowContext flowContext,
34 Assignment assignment,
35 boolean compoundAssignment) {
37 if (assignment.expression == null) {
38 return analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
45 analyseCode(currentScope, flowContext, flowInfo).unconditionalInits())
46 .unconditionalInits();
49 public FlowInfo analyseCode(
50 BlockScope currentScope,
51 FlowContext flowContext,
54 flowInfo = receiver.analyseCode(currentScope, flowContext, flowInfo);
55 receiver.checkNullStatus(currentScope, flowContext, flowInfo, FlowInfo.NON_NULL);
56 return position.analyseCode(currentScope, flowContext, flowInfo);
59 public void generateAssignment(
60 BlockScope currentScope,
61 CodeStream codeStream,
62 Assignment assignment,
63 boolean valueRequired) {
65 receiver.generateCode(currentScope, codeStream, true);
66 if (receiver instanceof CastExpression // ((type[])null)[0]
67 && ((CastExpression)receiver).innermostCastedExpression().resolvedType == NullBinding){
68 codeStream.checkcast(receiver.resolvedType);
70 position.generateCode(currentScope, codeStream, true);
71 assignment.expression.generateCode(currentScope, codeStream, true);
72 codeStream.arrayAtPut(this.resolvedType.id, valueRequired);
74 codeStream.generateImplicitConversion(assignment.implicitConversion);
79 * Code generation for a array reference
81 public void generateCode(
82 BlockScope currentScope,
83 CodeStream codeStream,
84 boolean valueRequired) {
86 int pc = codeStream.position;
87 receiver.generateCode(currentScope, codeStream, true);
88 if (receiver instanceof CastExpression // ((type[])null)[0]
89 && ((CastExpression)receiver).innermostCastedExpression().resolvedType == NullBinding){
90 codeStream.checkcast(receiver.resolvedType);
92 position.generateCode(currentScope, codeStream, true);
93 codeStream.arrayAt(this.resolvedType.id);
94 // Generating code for the potential runtime type checking
96 codeStream.generateImplicitConversion(implicitConversion);
98 if (this.resolvedType == LongBinding
99 || this.resolvedType == DoubleBinding) {
105 codeStream.recordPositionsFrom(pc, this.sourceStart);
108 public void generateCompoundAssignment(
109 BlockScope currentScope,
110 CodeStream codeStream,
111 Expression expression,
113 int assignmentImplicitConversion,
114 boolean valueRequired) {
116 receiver.generateCode(currentScope, codeStream, true);
117 if (receiver instanceof CastExpression // ((type[])null)[0]
118 && ((CastExpression)receiver).innermostCastedExpression().resolvedType == NullBinding){
119 codeStream.checkcast(receiver.resolvedType);
121 position.generateCode(currentScope, codeStream, true);
123 codeStream.arrayAt(this.resolvedType.id);
125 switch(operationTypeID = (implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) {
126 case T_JavaLangString :
127 case T_JavaLangObject :
129 codeStream.generateStringConcatenationAppend(currentScope, null, expression);
132 // promote the array reference to the suitable operation type
133 codeStream.generateImplicitConversion(implicitConversion);
134 // generate the increment value (will by itself be promoted to the operation value)
135 if (expression == IntLiteral.One) { // prefix operation
136 codeStream.generateConstant(expression.constant, implicitConversion);
138 expression.generateCode(currentScope, codeStream, true);
140 // perform the operation
141 codeStream.sendOperator(operator, operationTypeID);
142 // cast the value back to the array reference type
143 codeStream.generateImplicitConversion(assignmentImplicitConversion);
145 codeStream.arrayAtPut(this.resolvedType.id, valueRequired);
148 public void generatePostIncrement(
149 BlockScope currentScope,
150 CodeStream codeStream,
151 CompoundAssignment postIncrement,
152 boolean valueRequired) {
154 receiver.generateCode(currentScope, codeStream, true);
155 if (receiver instanceof CastExpression // ((type[])null)[0]
156 && ((CastExpression)receiver).innermostCastedExpression().resolvedType == NullBinding){
157 codeStream.checkcast(receiver.resolvedType);
159 position.generateCode(currentScope, codeStream, true);
161 codeStream.arrayAt(this.resolvedType.id);
163 if ((this.resolvedType == LongBinding)
164 || (this.resolvedType == DoubleBinding)) {
165 codeStream.dup2_x2();
170 codeStream.generateImplicitConversion(implicitConversion);
171 codeStream.generateConstant(
172 postIncrement.expression.constant,
174 codeStream.sendOperator(postIncrement.operator, this.implicitConversion & COMPILE_TYPE_MASK);
175 codeStream.generateImplicitConversion(
176 postIncrement.assignmentImplicitConversion);
177 codeStream.arrayAtPut(this.resolvedType.id, false);
180 public StringBuffer printExpression(int indent, StringBuffer output) {
182 receiver.printExpression(0, output).append('[');
183 return position.printExpression(0, output).append(']');
186 public TypeBinding resolveType(BlockScope scope) {
188 constant = Constant.NotAConstant;
189 if (receiver instanceof CastExpression // no cast check for ((type[])null)[0]
190 && ((CastExpression)receiver).innermostCastedExpression() instanceof NullLiteral) {
191 this.receiver.bits |= IgnoreNeedForCastCheckMASK; // will check later on
193 TypeBinding arrayType = receiver.resolveType(scope);
194 if (arrayType != null) {
195 receiver.computeConversion(scope, arrayType, arrayType);
196 if (arrayType.isArrayType()) {
197 this.resolvedType = ((ArrayBinding) arrayType).elementsType();
199 scope.problemReporter().referenceMustBeArrayTypeAt(arrayType, this);
202 TypeBinding positionType = position.resolveTypeExpecting(scope, IntBinding);
203 if (positionType != null) {
204 position.computeConversion(scope, IntBinding, positionType);
206 return this.resolvedType;
209 public void traverse(ASTVisitor visitor, BlockScope scope) {
211 if (visitor.visit(this, scope)) {
212 receiver.traverse(visitor, scope);
213 position.traverse(visitor, scope);
215 visitor.endVisit(this, scope);