package org.eclipse.jdt.internal.eval;

/*
 * (c) Copyright IBM Corp. 2000, 2001.
 * All Rights Reserved.
 */
import org.eclipse.jdt.internal.compiler.impl.*;
import org.eclipse.jdt.internal.compiler.ast.*;
import org.eclipse.jdt.internal.compiler.codegen.*;
import org.eclipse.jdt.internal.compiler.lookup.*;
import org.eclipse.jdt.internal.compiler.util.CharOperation;

public class CodeSnippetQualifiedNameReference extends QualifiedNameReference implements EvaluationConstants, InvocationSite, ProblemReasons {

	EvaluationContext evaluationContext;
	FieldBinding delegateThis;
/**
 * CodeSnippetQualifiedNameReference constructor comment.
 * @param sources char[][]
 * @param sourceStart int
 * @param sourceEnd int
 */
public CodeSnippetQualifiedNameReference(char[][] sources, int sourceStart, int sourceEnd, EvaluationContext evaluationContext) {
	super(sources, sourceStart, sourceEnd);
	this.evaluationContext = evaluationContext;	
}
/**
 * Check and/or redirect the field access to the delegate receiver if any
 */
public TypeBinding checkFieldAccess(BlockScope scope) {
	// check for forward references
	bits &= ~RestrictiveFlagMASK; // clear bits
	bits |= FIELD;
	return getOtherFieldBindings(scope);
}
public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) {
	generateReadSequence(currentScope, codeStream, true);
	if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
		// the last field access is a write access
		assignment.expression.generateCode(currentScope, codeStream, true);
		fieldStore(codeStream, lastFieldBinding, null, valueRequired);
	} else {
		((CodeSnippetCodeStream) codeStream).generateEmulationForField(lastFieldBinding);
		codeStream.swap();
		assignment.expression.generateCode(currentScope, codeStream, true);
		if (valueRequired) {
			if ((lastFieldBinding.type == LongBinding) || (lastFieldBinding.type == DoubleBinding)) {
				codeStream.dup2_x2();
			} else {
				codeStream.dup_x2();
			}
		}
		((CodeSnippetCodeStream) codeStream).generateEmulatedWriteAccessForField(lastFieldBinding);	
	}
	if (valueRequired) {
		codeStream.generateImplicitConversion(assignment.implicitConversion);
	}
}
public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
	int pc = codeStream.position;
	if (constant != NotAConstant) {
		if (valueRequired) {
			codeStream.generateConstant(constant, implicitConversion);
		}
	} else {
		generateReadSequence(currentScope, codeStream, valueRequired);
		if (valueRequired) {
			if (lastFieldBinding.declaringClass == null) { // array length
				codeStream.arraylength();
				codeStream.generateImplicitConversion(implicitConversion);
			} else {
				if (lastFieldBinding.constant != NotAConstant) {
					// inline the last field constant
					codeStream.generateConstant(lastFieldBinding.constant, implicitConversion);
				} else {	
					if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
						if (lastFieldBinding.isStatic()) {
							codeStream.getstatic(lastFieldBinding);
						} else {
							codeStream.getfield(lastFieldBinding);
						}
					} else {
						((CodeSnippetCodeStream) codeStream).generateEmulatedReadAccessForField(lastFieldBinding);
					}	
					codeStream.generateImplicitConversion(implicitConversion);
				}
			}
		}
	}
	codeStream.recordPositionsFrom(pc, this);
}
public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
	
	generateReadSequence(currentScope, codeStream, true);
	if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
		if (lastFieldBinding.isStatic()){
			codeStream.getstatic(lastFieldBinding);
		} else {
			codeStream.dup();
			codeStream.getfield(lastFieldBinding);
		}
		// the last field access is a write access
		// perform the actual compound operation
		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);
		}
		// actual assignment
		fieldStore(codeStream, lastFieldBinding, null, valueRequired);
	} else {
		if (lastFieldBinding.isStatic()){
			((CodeSnippetCodeStream) codeStream).generateEmulationForField(lastFieldBinding);
			codeStream.swap();
			codeStream.aconst_null();
			codeStream.swap();

			((CodeSnippetCodeStream) codeStream).generateEmulatedReadAccessForField(lastFieldBinding);
		} else {
			((CodeSnippetCodeStream) codeStream).generateEmulationForField(lastFieldBinding);
			codeStream.swap();
			codeStream.dup();

			((CodeSnippetCodeStream) codeStream).generateEmulatedReadAccessForField(lastFieldBinding);
		}
		// the last field access is a write access
		// perform the actual compound operation
		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);
		}
		// actual assignment

		// current stack is:
		// field receiver value
		if (valueRequired) {
			if ((lastFieldBinding.type == LongBinding) || (lastFieldBinding.type == DoubleBinding)) {
				codeStream.dup2_x2();
			} else {
				codeStream.dup_x2();
			}
		}
		// current stack is:
		// value field receiver value				
		((CodeSnippetCodeStream) codeStream).generateEmulatedWriteAccessForField(lastFieldBinding);
	}
}
public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
	generateReadSequence(currentScope, codeStream, true);

	if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
		if (lastFieldBinding.isStatic()){
			codeStream.getstatic(lastFieldBinding);
		} else {
			codeStream.dup();
			codeStream.getfield(lastFieldBinding);
		}	
		// duplicate the old field value
		if (valueRequired) {
			if (lastFieldBinding.isStatic()) {
				if ((lastFieldBinding.type == LongBinding) || (lastFieldBinding.type == DoubleBinding)) {
					codeStream.dup2();
				} else {
					codeStream.dup();
				}
			} else { // Stack:  [owner][old field value]  ---> [old field value][owner][old field value]
				if ((lastFieldBinding.type == LongBinding) || (lastFieldBinding.type == DoubleBinding)) {
					codeStream.dup2_x1();
				} else {
					codeStream.dup_x1();
				}
			}
		}
		codeStream.generateConstant(postIncrement.expression.constant, implicitConversion);
		codeStream.sendOperator(postIncrement.operator, lastFieldBinding.type.id);
		codeStream.generateImplicitConversion(postIncrement.assignmentImplicitConversion);
		
		fieldStore(codeStream, lastFieldBinding, null, false);
	} else {
		((CodeSnippetCodeStream) codeStream).generateEmulatedReadAccessForField(lastFieldBinding);
		if (valueRequired) {
			if ((lastFieldBinding.type == LongBinding) || (lastFieldBinding.type == DoubleBinding)) {
				codeStream.dup2();
			} else {
				codeStream.dup();
			}
		}
		((CodeSnippetCodeStream) codeStream).generateEmulationForField(lastFieldBinding);
		if ((lastFieldBinding.type == LongBinding) || (lastFieldBinding.type == DoubleBinding)) {
			codeStream.dup_x2();
			codeStream.pop();
			if (lastFieldBinding.isStatic()) {
				codeStream.aconst_null();
			} else {
				generateReadSequence(currentScope, codeStream, true);
			}
			codeStream.dup_x2();
			codeStream.pop();					
		} else {
			codeStream.dup_x1();
			codeStream.pop();
			if (lastFieldBinding.isStatic()) {
				codeStream.aconst_null();
			} else {
				generateReadSequence(currentScope, codeStream, true);
			}
			codeStream.dup_x1();
			codeStream.pop();					
		}
		codeStream.generateConstant(postIncrement.expression.constant, implicitConversion);
		codeStream.sendOperator(postIncrement.operator, lastFieldBinding.type.id);
		codeStream.generateImplicitConversion(postIncrement.assignmentImplicitConversion);
		((CodeSnippetCodeStream) codeStream).generateEmulatedWriteAccessForField(lastFieldBinding);
	}
}
/*
 * Generate code for all bindings (local and fields) excluding the last one, which may then be generated code
 * for a read or write access.
 */
public void generateReadSequence(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {

	// determine the rank until which we now we do not need any actual value for the field access
	int otherBindingsCount = otherBindings == null ? 0 : otherBindings.length;
	int indexOfFirstValueRequired;
	if (valueRequired) {
		indexOfFirstValueRequired = otherBindingsCount;
		while (indexOfFirstValueRequired > 0) {
			FieldBinding otherBinding = otherBindings[indexOfFirstValueRequired - 1];
			if (otherBinding.isStatic() || otherBinding.constant != NotAConstant)
				break; // no longer need any value before this point
			indexOfFirstValueRequired--;
		}
	} else {
		indexOfFirstValueRequired = otherBindingsCount + 1;
	}
	if (indexOfFirstValueRequired == 0) {
		switch (bits & RestrictiveFlagMASK) {
			case FIELD :
				lastFieldBinding = (FieldBinding) binding;
				// if first field is actually constant, we can inline it
				if (lastFieldBinding.constant != NotAConstant) {
					codeStream.generateConstant(lastFieldBinding.constant, 0); // no implicit conversion
					lastFieldBinding = null; // will not generate it again
					break;
				}
				if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
					if (!lastFieldBinding.isStatic()) {
						if ((bits & DepthMASK) != 0) {
							Object[] emulationPath = currentScope.getExactEmulationPath(currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT));
							if (emulationPath == null) {
								// internal error, per construction we should have found it
								currentScope.problemReporter().needImplementation();
							} else {
								codeStream.generateOuterAccess(emulationPath, this, currentScope);
							}
						} else {
							generateReceiver(codeStream);
						}
					}
				} else {
					if (!lastFieldBinding.isStatic()) {
						if ((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 LOCAL : // reading the first local variable
				lastFieldBinding = null;
				LocalVariableBinding localBinding = (LocalVariableBinding) binding;

				// regular local variable read
				if (localBinding.constant != NotAConstant) {
					codeStream.generateConstant(localBinding.constant, 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);
						if (path == null) {
							// emulation was not possible (should not happen per construction)
							currentScope.problemReporter().needImplementation();
						} else {
							codeStream.generateOuterAccess(path, this, currentScope);
						}
					} else {
						codeStream.load(localBinding);
					}
				}
		}
	} else {
		lastFieldBinding = null;
	}
	// all intermediate field accesses are read accesses
	// only the last field binding is a write access
	if (otherBindings != null) {
		int start = indexOfFirstValueRequired == 0 ? 0 : indexOfFirstValueRequired - 1;
		for (int i = start; i < otherBindingsCount; i++) {
			if (lastFieldBinding != null) {
				if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
					if (lastFieldBinding.isStatic())
						codeStream.getstatic(lastFieldBinding);
					else
						codeStream.getfield(lastFieldBinding);
				} else {
					((CodeSnippetCodeStream) codeStream).generateEmulatedReadAccessForField(lastFieldBinding);
				}
			}

			lastFieldBinding = otherBindings[i];
			if (lastFieldBinding != null && !lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
				if (lastFieldBinding.isStatic()) {
					codeStream.aconst_null();
				}
			}
		}
	}
}
public void generateReceiver(CodeStream codeStream) {
	codeStream.aload_0();
	if (delegateThis != null) codeStream.getfield(delegateThis); // delegated field access
}
public TypeBinding getOtherFieldBindings(BlockScope scope) {
	// At this point restrictiveFlag may ONLY have two potential value : FIELD LOCAL (i.e cast <<(VariableBinding) binding>> is valid)

	if ((bits & FIELD) != 0) {
		if (!((FieldBinding) binding).isStatic()) { //must check for the static status....
			if (indexOfFirstFieldBinding == 1) {
				//the field is the first token of the qualified reference....
				if (scope.methodScope().isStatic) {
					scope.problemReporter().staticFieldAccessToNonStaticVariable(this, (FieldBinding) binding);
					return null;
				}
			} else { //accessing to a field using a type as "receiver" is allowed only with static field	
				scope.problemReporter().staticFieldAccessToNonStaticVariable(this, (FieldBinding) binding);
				return null;
			}
		}
		if (isFieldUseDeprecated((FieldBinding) binding, scope))
			scope.problemReporter().deprecatedField((FieldBinding) binding, this);

		// if the binding declaring class is not visible, need special action
		// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
		FieldBinding fieldBinding = (FieldBinding)binding;
		if (delegateThis == null) {
			if (fieldBinding.declaringClass != null
				&& fieldBinding.constant == NotAConstant
				&& !fieldBinding.declaringClass.canBeSeenBy(scope))
					binding = new FieldBinding(fieldBinding, (ReferenceBinding) delegateThis.type);
		} else {
			CodeSnippetScope localScope = new CodeSnippetScope(scope);
			if (fieldBinding.declaringClass != null
				&& fieldBinding.constant == NotAConstant
				&& !localScope.canBeSeenByForCodeSnippet(fieldBinding.declaringClass, (ReferenceBinding) delegateThis.type))
					binding = new FieldBinding(fieldBinding, (ReferenceBinding) delegateThis.type);
		}
	}

	TypeBinding type = ((VariableBinding) binding).type;
	int index = indexOfFirstFieldBinding;
	int length = tokens.length;
	if (index == length) { //	restrictiveFlag == FIELD
		constant = FieldReference.getConstantFor((FieldBinding) binding, false, this, index - 1);
		return type;
	}

	// allocation of the fieldBindings array	and its respective constants
	int otherBindingsLength = length - index;
	otherBindings = new FieldBinding[otherBindingsLength];
	
	// fill the first constant (the one of the binding)
	constant =
		((bits & FIELD) != 0)
			? FieldReference.getConstantFor((FieldBinding) binding, false, this, index - 1)
			: ((VariableBinding) binding).constant;

	// iteration on each field	
	while (index < length) {
		char[] token = tokens[index];
		if (type == null) return null; // could not resolve type prior to this point
		FieldBinding field = scope.getField(type, token, this);
		int place = index - indexOfFirstFieldBinding;
		otherBindings[place] = field;
		if (!field.isValidBinding()) {
			// try to retrieve the field as private field
			CodeSnippetScope localScope = new CodeSnippetScope(scope);
			if (delegateThis == null) {
				if (this.evaluationContext.declaringTypeName != null) {
					delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this);
					if (delegateThis == null){ ; // if not found then internal error, field should have been found
						return super.reportError(scope);
					}
				} else {
					return super.reportError(scope);
				}
			}
			field = localScope.getFieldForCodeSnippet(delegateThis.type, token, this);
			otherBindings[place] = field;
		}
		if (field.isValidBinding()) {
			if (isFieldUseDeprecated(field, scope))
				scope.problemReporter().deprecatedField(field, this);
			Constant someConstant = FieldReference.getConstantFor(field, false, this, place);
			// constant propagation can only be performed as long as the previous one is a constant too.
			if (constant != NotAConstant){
				constant = someConstant;
			}
			// if the binding declaring class is not visible, need special action
			// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
			if (delegateThis == null) {
				CodeSnippetScope localScope = new CodeSnippetScope(scope);
				if (field.declaringClass != type
					&& field.declaringClass != null // array.length
					&& field.constant == NotAConstant
					&& !field.declaringClass.canBeSeenBy(scope))
						otherBindings[place] = new FieldBinding(field, (ReferenceBinding)type);
			} else {
				CodeSnippetScope localScope = new CodeSnippetScope(scope);
				if (field.declaringClass != type
					&& field.declaringClass != null // array.length
					&& field.constant == NotAConstant
					&& !localScope.canBeSeenByForCodeSnippet(field.declaringClass, (ReferenceBinding) delegateThis.type))
						otherBindings[place] = new FieldBinding(field, (ReferenceBinding)type);
			}
			type = field.type;
			index++;
		} else {
			constant = NotAConstant; //don't fill other constants slots...
			scope.problemReporter().invalidField(this, field, index, type);
			return null;
		}
	}
	return (otherBindings[otherBindingsLength - 1]).type;
}
/**
 * Check and/or redirect the field access to the delegate receiver if any
 */
public TypeBinding getReceiverType(BlockScope currentScope) {
	if (receiverType != null) return receiverType;
	Scope scope = currentScope.parent;
	while (true) {
			switch (scope.kind) {
				case Scope.CLASS_SCOPE :
					return receiverType = ((ClassScope) scope).referenceContext.binding;
				default:
					scope = scope.parent;
			}
	}
}
public void manageSyntheticReadAccessIfNecessary(BlockScope currentScope, FieldBinding fieldBinding, int index) {
	// nothing to do the code generation will take care of private access
}
/*
 * No need to emulate access to protected fields since not implicitly accessed
 */
public void manageSyntheticWriteAccessIfNecessary(BlockScope currentScope, FieldBinding fieldBinding) {
	// nothing to do the code generation will take care of private access
}
/**
 * Normal field binding did not work, try to bind to a field of the delegate receiver.
 */
public TypeBinding reportError(BlockScope scope) {

	if (this.evaluationContext.declaringTypeName != null) {
		delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this);
		if (delegateThis == null){ ; // if not found then internal error, field should have been found
			return super.reportError(scope);
		}
	} else {
		return super.reportError(scope);
	}

	if (binding instanceof ProblemFieldBinding && ((ProblemFieldBinding) binding).problemId() == NotFound){
		// will not support innerclass emulation inside delegate
		binding = scope.getField(delegateThis.type, this.tokens[0], this);
		if (!binding.isValidBinding()) return super.reportError(scope);
		return checkFieldAccess(scope);
	}

	if (binding instanceof ProblemBinding && ((ProblemBinding) binding).problemId() == NotFound){
		// will not support innerclass emulation inside delegate
		FieldBinding fieldBinding = scope.getField(delegateThis.type, this.tokens[0], this);
		if (!fieldBinding.isValidBinding()) return super.reportError(scope);
		binding = fieldBinding;
		return checkFieldAccess(scope);
	}

	TypeBinding result;
	if (binding instanceof ProblemFieldBinding
		&& ((ProblemFieldBinding) binding).problemId() == NotVisible) {
		result = resolveTypeVisibility(scope);
		if (result == null)
			return super.reportError(scope);
		if (result.isValidBinding()) {
			return result;
		}
	}

	return super.reportError(scope);
}

public TypeBinding resolveTypeVisibility(BlockScope scope) {
	// field and/or local are done before type lookups

	// the only available value for the restrictiveFlag BEFORE
	// the TC is Flag_Type Flag_LocalField and Flag_TypeLocalField 

	CodeSnippetScope localScope = new CodeSnippetScope(scope);
	if ((binding = localScope.getBinding(tokens, bits & RestrictiveFlagMASK, this, (ReferenceBinding) delegateThis.type)).isValidBinding()) {
		bits &= ~RestrictiveFlagMASK; // clear bits
		bits |= FIELD;
		return getOtherFieldBindings(scope);
	}
	//========error cases===============
	return super.reportError(scope);
}
}
