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 ArrayReference extends Reference {
21 public Expression receiver;
22 public Expression position;
24 public TypeBinding arrayElementBinding;
26 public ArrayReference(Expression rec, Expression pos) {
29 sourceStart = rec.sourceStart;
32 public FlowInfo analyseAssignment(
33 BlockScope currentScope,
34 FlowContext flowContext,
36 Assignment assignment,
37 boolean compoundAssignment) {
39 if (assignment.expression == null) {
40 return analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
47 analyseCode(currentScope, flowContext, flowInfo).unconditionalInits())
48 .unconditionalInits();
52 public FlowInfo analyseCode(
53 BlockScope currentScope,
54 FlowContext flowContext,
57 return position.analyseCode(
60 receiver.analyseCode(currentScope, flowContext, flowInfo));
63 public void generateAssignment(
64 BlockScope currentScope,
65 CodeStream codeStream,
66 Assignment assignment,
67 boolean valueRequired) {
69 receiver.generateCode(currentScope, codeStream, true);
70 position.generateCode(currentScope, codeStream, true);
71 assignment.expression.generateCode(currentScope, codeStream, true);
72 codeStream.arrayAtPut(arrayElementBinding.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 position.generateCode(currentScope, codeStream, true);
89 codeStream.arrayAt(arrayElementBinding.id);
90 // Generating code for the potential runtime type checking
92 codeStream.generateImplicitConversion(implicitConversion);
94 if (arrayElementBinding == LongBinding
95 || arrayElementBinding == DoubleBinding) {
101 codeStream.recordPositionsFrom(pc, this.sourceStart);
104 public void generateCompoundAssignment(
105 BlockScope currentScope,
106 CodeStream codeStream,
107 Expression expression,
109 int assignmentImplicitConversion,
110 boolean valueRequired) {
112 receiver.generateCode(currentScope, codeStream, true);
113 position.generateCode(currentScope, codeStream, true);
115 codeStream.arrayAt(arrayElementBinding.id);
117 if ((operationTypeID = implicitConversion >> 4) == T_String) {
118 codeStream.generateStringAppend(currentScope, null, expression);
120 // promote the array reference to the suitable operation type
121 codeStream.generateImplicitConversion(implicitConversion);
122 // generate the increment value (will by itself be promoted to the operation value)
123 if (expression == IntLiteral.One) { // prefix operation
124 codeStream.generateConstant(expression.constant, implicitConversion);
126 expression.generateCode(currentScope, codeStream, true);
128 // perform the operation
129 codeStream.sendOperator(operator, operationTypeID);
130 // cast the value back to the array reference type
131 codeStream.generateImplicitConversion(assignmentImplicitConversion);
133 codeStream.arrayAtPut(arrayElementBinding.id, valueRequired);
136 public void generatePostIncrement(
137 BlockScope currentScope,
138 CodeStream codeStream,
139 CompoundAssignment postIncrement,
140 boolean valueRequired) {
142 receiver.generateCode(currentScope, codeStream, true);
143 position.generateCode(currentScope, codeStream, true);
145 codeStream.arrayAt(arrayElementBinding.id);
147 if ((arrayElementBinding == LongBinding)
148 || (arrayElementBinding == DoubleBinding)) {
149 codeStream.dup2_x2();
154 codeStream.generateConstant(
155 postIncrement.expression.constant,
157 codeStream.sendOperator(postIncrement.operator, arrayElementBinding.id);
158 codeStream.generateImplicitConversion(
159 postIncrement.assignmentImplicitConversion);
160 codeStream.arrayAtPut(arrayElementBinding.id, false);
163 public TypeBinding resolveType(BlockScope scope) {
165 constant = Constant.NotAConstant;
166 TypeBinding arrayTb = receiver.resolveType(scope);
169 if (!arrayTb.isArrayType()) {
170 scope.problemReporter().referenceMustBeArrayTypeAt(arrayTb, this);
173 TypeBinding positionTb = position.resolveTypeExpecting(scope, IntBinding);
174 if (positionTb == null)
176 position.implicitWidening(IntBinding, positionTb);
177 return arrayElementBinding = ((ArrayBinding) arrayTb).elementsType(scope);
180 public String toStringExpression() {
182 return receiver.toStringExpression() + "[" //$NON-NLS-1$
183 +position.toStringExpression() + "]"; //$NON-NLS-1$
186 public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
188 if (visitor.visit(this, scope)) {
189 receiver.traverse(visitor, scope);
190 position.traverse(visitor, scope);
192 visitor.endVisit(this, scope);