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 return position.analyseCode(
57 receiver.analyseCode(currentScope, flowContext, flowInfo));
60 public void generateAssignment(
61 BlockScope currentScope,
62 CodeStream codeStream,
63 Assignment assignment,
64 boolean valueRequired) {
66 receiver.generateCode(currentScope, codeStream, true);
67 if (receiver instanceof CastExpression // ((type[])null)[0]
68 && ((CastExpression)receiver).innermostCastedExpression().resolvedType == NullBinding){
69 codeStream.checkcast(receiver.resolvedType);
71 position.generateCode(currentScope, codeStream, true);
72 assignment.expression.generateCode(currentScope, codeStream, true);
73 codeStream.arrayAtPut(this.resolvedType.id, valueRequired);
75 codeStream.generateImplicitConversion(assignment.implicitConversion);
80 * Code generation for a array reference
82 public void generateCode(
83 BlockScope currentScope,
84 CodeStream codeStream,
85 boolean valueRequired) {
87 int pc = codeStream.position;
88 receiver.generateCode(currentScope, codeStream, true);
89 if (receiver instanceof CastExpression // ((type[])null)[0]
90 && ((CastExpression)receiver).innermostCastedExpression().resolvedType == NullBinding){
91 codeStream.checkcast(receiver.resolvedType);
93 position.generateCode(currentScope, codeStream, true);
94 codeStream.arrayAt(this.resolvedType.id);
95 // Generating code for the potential runtime type checking
97 codeStream.generateImplicitConversion(implicitConversion);
99 if (this.resolvedType == LongBinding
100 || this.resolvedType == DoubleBinding) {
106 codeStream.recordPositionsFrom(pc, this.sourceStart);
109 public void generateCompoundAssignment(
110 BlockScope currentScope,
111 CodeStream codeStream,
112 Expression expression,
114 int assignmentImplicitConversion,
115 boolean valueRequired) {
117 receiver.generateCode(currentScope, codeStream, true);
118 if (receiver instanceof CastExpression // ((type[])null)[0]
119 && ((CastExpression)receiver).innermostCastedExpression().resolvedType == NullBinding){
120 codeStream.checkcast(receiver.resolvedType);
122 position.generateCode(currentScope, codeStream, true);
124 codeStream.arrayAt(this.resolvedType.id);
126 if ((operationTypeID = implicitConversion >> 4) == T_String) {
127 codeStream.generateStringAppend(currentScope, null, expression);
129 // promote the array reference to the suitable operation type
130 codeStream.generateImplicitConversion(implicitConversion);
131 // generate the increment value (will by itself be promoted to the operation value)
132 if (expression == IntLiteral.One) { // prefix operation
133 codeStream.generateConstant(expression.constant, implicitConversion);
135 expression.generateCode(currentScope, codeStream, true);
137 // perform the operation
138 codeStream.sendOperator(operator, operationTypeID);
139 // cast the value back to the array reference type
140 codeStream.generateImplicitConversion(assignmentImplicitConversion);
142 codeStream.arrayAtPut(this.resolvedType.id, valueRequired);
145 public void generatePostIncrement(
146 BlockScope currentScope,
147 CodeStream codeStream,
148 CompoundAssignment postIncrement,
149 boolean valueRequired) {
151 receiver.generateCode(currentScope, codeStream, true);
152 if (receiver instanceof CastExpression // ((type[])null)[0]
153 && ((CastExpression)receiver).innermostCastedExpression().resolvedType == NullBinding){
154 codeStream.checkcast(receiver.resolvedType);
156 position.generateCode(currentScope, codeStream, true);
158 codeStream.arrayAt(this.resolvedType.id);
160 if ((this.resolvedType == LongBinding)
161 || (this.resolvedType == DoubleBinding)) {
162 codeStream.dup2_x2();
167 codeStream.generateConstant(
168 postIncrement.expression.constant,
170 codeStream.sendOperator(postIncrement.operator, this.resolvedType.id);
171 codeStream.generateImplicitConversion(
172 postIncrement.assignmentImplicitConversion);
173 codeStream.arrayAtPut(this.resolvedType.id, false);
176 public StringBuffer printExpression(int indent, StringBuffer output) {
178 receiver.printExpression(0, output).append('[');
179 return position.printExpression(0, output).append(']');
182 public TypeBinding resolveType(BlockScope scope) {
184 constant = Constant.NotAConstant;
185 if (receiver instanceof CastExpression // no cast check for ((type[])null)[0]
186 && ((CastExpression)receiver).innermostCastedExpression() instanceof NullLiteral) {
187 this.receiver.bits |= IgnoreNeedForCastCheckMASK; // will check later on
189 TypeBinding arrayType = receiver.resolveType(scope);
190 if (arrayType != null) {
191 if (arrayType.isArrayType()) {
192 this.resolvedType = ((ArrayBinding) arrayType).elementsType(scope);
194 scope.problemReporter().referenceMustBeArrayTypeAt(arrayType, this);
197 TypeBinding positionType = position.resolveTypeExpecting(scope, IntBinding);
198 if (positionType != null) {
199 position.implicitWidening(IntBinding, positionType);
201 return this.resolvedType;
204 public void traverse(ASTVisitor visitor, BlockScope scope) {
206 if (visitor.visit(this, scope)) {
207 receiver.traverse(visitor, scope);
208 position.traverse(visitor, scope);
210 visitor.endVisit(this, scope);