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.Constant;
18 import net.sourceforge.phpdt.internal.compiler.lookup.ArrayBinding;
19 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
20 import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
22 public class ArrayReference extends Reference {
24 public Expression receiver;
25 public Expression position;
27 public TypeBinding arrayElementBinding;
29 public ArrayReference(Expression rec, Expression pos) {
32 sourceStart = rec.sourceStart;
35 public FlowInfo analyseAssignment(
36 BlockScope currentScope,
37 FlowContext flowContext,
39 Assignment assignment,
40 boolean compoundAssignment) {
42 if (assignment.expression == null) {
43 return analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
50 analyseCode(currentScope, flowContext, flowInfo).unconditionalInits())
51 .unconditionalInits();
55 public FlowInfo analyseCode(
56 BlockScope currentScope,
57 FlowContext flowContext,
60 return position.analyseCode(
63 receiver.analyseCode(currentScope, flowContext, flowInfo));
66 public void generateAssignment(
67 BlockScope currentScope,
68 CodeStream codeStream,
69 Assignment assignment,
70 boolean valueRequired) {
72 receiver.generateCode(currentScope, codeStream, true);
73 position.generateCode(currentScope, codeStream, true);
74 assignment.expression.generateCode(currentScope, codeStream, true);
75 codeStream.arrayAtPut(arrayElementBinding.id, valueRequired);
77 codeStream.generateImplicitConversion(assignment.implicitConversion);
82 * Code generation for a array reference
84 public void generateCode(
85 BlockScope currentScope,
86 CodeStream codeStream,
87 boolean valueRequired) {
89 int pc = codeStream.position;
90 receiver.generateCode(currentScope, codeStream, true);
91 position.generateCode(currentScope, codeStream, true);
92 codeStream.arrayAt(arrayElementBinding.id);
93 // Generating code for the potential runtime type checking
95 codeStream.generateImplicitConversion(implicitConversion);
97 if (arrayElementBinding == LongBinding
98 || arrayElementBinding == DoubleBinding) {
104 codeStream.recordPositionsFrom(pc, this.sourceStart);
107 public void generateCompoundAssignment(
108 BlockScope currentScope,
109 CodeStream codeStream,
110 Expression expression,
112 int assignmentImplicitConversion,
113 boolean valueRequired) {
115 receiver.generateCode(currentScope, codeStream, true);
116 position.generateCode(currentScope, codeStream, true);
118 codeStream.arrayAt(arrayElementBinding.id);
120 if ((operationTypeID = implicitConversion >> 4) == T_String) {
121 codeStream.generateStringAppend(currentScope, null, expression);
123 // promote the array reference to the suitable operation type
124 codeStream.generateImplicitConversion(implicitConversion);
125 // generate the increment value (will by itself be promoted to the operation value)
126 if (expression == IntLiteral.One) { // prefix operation
127 codeStream.generateConstant(expression.constant, implicitConversion);
129 expression.generateCode(currentScope, codeStream, true);
131 // perform the operation
132 codeStream.sendOperator(operator, operationTypeID);
133 // cast the value back to the array reference type
134 codeStream.generateImplicitConversion(assignmentImplicitConversion);
136 codeStream.arrayAtPut(arrayElementBinding.id, valueRequired);
139 public void generatePostIncrement(
140 BlockScope currentScope,
141 CodeStream codeStream,
142 CompoundAssignment postIncrement,
143 boolean valueRequired) {
145 receiver.generateCode(currentScope, codeStream, true);
146 position.generateCode(currentScope, codeStream, true);
148 codeStream.arrayAt(arrayElementBinding.id);
150 if ((arrayElementBinding == LongBinding)
151 || (arrayElementBinding == DoubleBinding)) {
152 codeStream.dup2_x2();
157 codeStream.generateConstant(
158 postIncrement.expression.constant,
160 codeStream.sendOperator(postIncrement.operator, arrayElementBinding.id);
161 codeStream.generateImplicitConversion(
162 postIncrement.assignmentImplicitConversion);
163 codeStream.arrayAtPut(arrayElementBinding.id, false);
166 public TypeBinding resolveType(BlockScope scope) {
168 constant = Constant.NotAConstant;
169 TypeBinding arrayTb = receiver.resolveType(scope);
172 if (!arrayTb.isArrayType()) {
173 scope.problemReporter().referenceMustBeArrayTypeAt(arrayTb, this);
176 TypeBinding positionTb = position.resolveTypeExpecting(scope, IntBinding);
177 if (positionTb == null)
179 position.implicitWidening(IntBinding, positionTb);
180 return arrayElementBinding = ((ArrayBinding) arrayTb).elementsType(scope);
183 public String toStringExpression() {
185 return receiver.toStringExpression() + "[" //$NON-NLS-1$
186 +position.toStringExpression() + "]"; //$NON-NLS-1$
189 public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
191 if (visitor.visit(this, scope)) {
192 receiver.traverse(visitor, scope);
193 position.traverse(visitor, scope);
195 visitor.endVisit(this, scope);