blob: e3491a0e327fe8c6da3101a7901d9b08b251e0fc [file] [log] [blame]
package org.eclipse.jdt.internal.compiler.ast;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
import org.eclipse.jdt.internal.compiler.impl.*;
import org.eclipse.jdt.internal.compiler.codegen.*;
import org.eclipse.jdt.internal.compiler.flow.*;
import org.eclipse.jdt.internal.compiler.lookup.*;
public class ArrayReference extends Reference {
public Expression receiver;
public Expression position;
public TypeBinding arrayElementBinding;
public ArrayReference(Expression rec, Expression pos) {
this.receiver = rec;
this.position = pos;
sourceStart = rec.sourceStart ;
}
public FlowInfo analyseAssignment(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, Assignment assignment, boolean compoundAssignment) {
if (assignment.expression == null) {
return analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
} else {
return assignment.expression.analyseCode(currentScope, flowContext, analyseCode(currentScope, flowContext, flowInfo).unconditionalInits()).unconditionalInits();
}
}
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
return position.analyseCode(
currentScope,
flowContext,
receiver.analyseCode(currentScope, flowContext, flowInfo));
}
public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) {
receiver.generateCode(currentScope, codeStream, true);
position.generateCode(currentScope, codeStream, true);
assignment.expression.generateCode(currentScope, codeStream, true);
codeStream.arrayAtPut(arrayElementBinding.id, valueRequired);
if (valueRequired) {
codeStream.generateImplicitConversion(assignment.implicitConversion);
}
}
/**
* Code generation for a array reference
*/
public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
int pc = codeStream.position;
receiver.generateCode(currentScope, codeStream, true);
position.generateCode(currentScope, codeStream, true);
codeStream.arrayAt(arrayElementBinding.id);
// Generating code for the potential runtime type checking
if (valueRequired) {
codeStream.generateImplicitConversion(implicitConversion);
} else {
if (arrayElementBinding == LongBinding || arrayElementBinding == DoubleBinding) {
codeStream.pop2();
} else {
codeStream.pop();
}
}
codeStream.recordPositionsFrom(pc, this);
}
public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
receiver.generateCode(currentScope, codeStream, true);
position.generateCode(currentScope, codeStream, true);
codeStream.dup2();
codeStream.arrayAt(arrayElementBinding.id);
int operationTypeID;
if ((operationTypeID = implicitConversion >> 4) == T_String) {
codeStream.generateStringAppend(currentScope, null, expression);
} else {
// promote the array reference to the suitable operation type
codeStream.generateImplicitConversion(implicitConversion);
// generate the increment value (will by itself be promoted to the operation value)
if (expression == IntLiteral.One){ // prefix operation
codeStream.generateConstant(expression.constant, implicitConversion);
} else {
expression.generateCode(currentScope, codeStream, true);
}
// perform the operation
codeStream.sendOperator(operator, operationTypeID);
// cast the value back to the array reference type
codeStream.generateImplicitConversion(assignmentImplicitConversion);
}
codeStream.arrayAtPut(arrayElementBinding.id, valueRequired);
}
public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
receiver.generateCode(currentScope, codeStream, true);
position.generateCode(currentScope, codeStream, true);
codeStream.dup2();
codeStream.arrayAt(arrayElementBinding.id);
if (valueRequired) {
if ((arrayElementBinding == LongBinding) || (arrayElementBinding == DoubleBinding)) {
codeStream.dup2_x2();
} else {
codeStream.dup_x2();
}
}
codeStream.generateConstant(postIncrement.expression.constant, implicitConversion);
codeStream.sendOperator(postIncrement.operator, arrayElementBinding.id);
codeStream.generateImplicitConversion(postIncrement.assignmentImplicitConversion);
codeStream.arrayAtPut(arrayElementBinding.id, false);
}
public TypeBinding resolveType(BlockScope scope) {
constant = Constant.NotAConstant;
TypeBinding arrayTb = receiver.resolveType(scope);
if (arrayTb == null)
return null;
if (!arrayTb.isArrayType()) {
scope.problemReporter().referenceMustBeArrayTypeAt(arrayTb, this);
return null;
}
TypeBinding positionTb = position.resolveTypeExpecting(scope, IntBinding);
if (positionTb == null)
return null;
position.implicitWidening(IntBinding, positionTb);
return arrayElementBinding = ((ArrayBinding) arrayTb).elementsType(scope);
}
public String toStringExpression(){
/* slow code */
return receiver.toStringExpression()
+ "["/*nonNLS*/
+ position.toStringExpression()
+ "]"/*nonNLS*/ ;}
public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
if (visitor.visit(this, scope)) {
receiver.traverse(visitor, scope);
position.traverse(visitor, scope);
}
visitor.endVisit(this, scope);
}
}