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);