Skip to main content
summaryrefslogtreecommitdiffstats
blob: e3491a0e327fe8c6da3101a7901d9b08b251e0fc (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
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);
}
}

Back to the top