public FieldBinding generateReadSequence(BlockScope currentScope, CodeStream codeStream) {
// determine the rank until which we now we do not need any actual value for the field access
int otherBindingsCount = this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length;
boolean needValue = otherBindingsCount == 0 || !this.otherBindings[0].isStatic();
FieldBinding lastFieldBinding = null;
TypeBinding lastGenericCast = null;
switch (this.bits & RestrictiveFlagMASK) {
case Binding.FIELD :
lastFieldBinding = (FieldBinding) this.codegenBinding;
lastGenericCast = this.genericCast;
// if first field is actually constant, we can inline it
if (lastFieldBinding.constant() != Constant.NotAConstant) {
break;
}
if (needValue) {
if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
if (!lastFieldBinding.isStatic()) {
if ((this.bits & DepthMASK) != 0) {
ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT);
Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
} else {
generateReceiver(codeStream);
}
}
} else {
if (!lastFieldBinding.isStatic()) {
if ((this.bits & DepthMASK) != 0) {
// internal error, per construction we should have found it
// not yet supported
currentScope.problemReporter().needImplementation();
} else {
generateReceiver(codeStream);
}
} else {
codeStream.aconst_null();
}
}
}
break;
case Binding.LOCAL : // reading the first local variable
if (!needValue) break; // no value needed
LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
// regular local variable read
Constant localConstant = localBinding.constant();
if (localConstant != Constant.NotAConstant) {
codeStream.generateConstant(localConstant, 0);
// no implicit conversion
} else {
// outer local?
if ((bits & DepthMASK) != 0) {
// outer local can be reached either through a synthetic arg or a synthetic field
VariableBinding[] path = currentScope.getEmulationPath(localBinding);
codeStream.generateOuterAccess(path, this, localBinding, currentScope);
} else {
codeStream.load(localBinding);
}
}
}
// all intermediate field accesses are read accesses
// only the last field binding is a write access
if (this.otherCodegenBindings != null) {
for (int i = 0; i < otherBindingsCount; i++) {
FieldBinding nextField = this.otherCodegenBindings[i];
TypeBinding nextGenericCast = this.otherGenericCasts == null ? null : this.otherGenericCasts[i];
if (lastFieldBinding != null) {
needValue = !nextField.isStatic();
if (needValue) {
if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
Constant fieldConstant = lastFieldBinding.constant();
if (fieldConstant != Constant.NotAConstant) {
if (lastFieldBinding != this.codegenBinding && !lastFieldBinding.isStatic()) {