/*******************************************************************************
 * Copyright (c) 2000, 2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;

import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.codegen.*;
import org.eclipse.jdt.internal.compiler.flow.*;
import org.eclipse.jdt.internal.compiler.lookup.*;

public class TryStatement extends SubRoutineStatement {
	
	public Block tryBlock;
	public Block[] catchBlocks;
	public Argument[] catchArguments;
	public Block finallyBlock;
	BlockScope scope;

	private boolean isSubRoutineEscaping = false;
	public UnconditionalFlowInfo subRoutineInits;
	
	// should rename into subRoutineComplete to be set to false by default

	ReferenceBinding[] caughtExceptionTypes;
	boolean tryBlockExit;
	boolean[] catchExits;
	public int[] preserveExceptionHandler;

	Label subRoutineStartLabel;
	public LocalVariableBinding anyExceptionVariable,
		returnAddressVariable,
		secretReturnValue;

	public final static char[] SecretReturnName = " returnAddress".toCharArray(); //$NON-NLS-1$
	public final static char[] SecretAnyHandlerName = " anyExceptionHandler".toCharArray(); //$NON-NLS-1$
	public static final char[] SecretLocalDeclarationName = " returnValue".toCharArray(); //$NON-NLS-1$

	// for local variables table attributes
	int preTryInitStateIndex = -1;
	int mergedInitStateIndex = -1;

	public FlowInfo analyseCode(
		BlockScope currentScope,
		FlowContext flowContext,
		FlowInfo flowInfo) {

		// Consider the try block and catch block so as to compute the intersection of initializations and	
		// the minimum exit relative depth amongst all of them. Then consider the subroutine, and append its
		// initialization to the try/catch ones, if the subroutine completes normally. If the subroutine does not
		// complete, then only keep this result for the rest of the analysis

		// process the finally block (subroutine) - create a context for the subroutine

		preTryInitStateIndex =
			currentScope.methodScope().recordInitializationStates(flowInfo);

		if (anyExceptionVariable != null) {
			anyExceptionVariable.useFlag = LocalVariableBinding.USED;
		}
		if (returnAddressVariable != null) { // TODO (philippe) if subroutine is escaping, unused
			returnAddressVariable.useFlag = LocalVariableBinding.USED;
		}
		InsideSubRoutineFlowContext insideSubContext;
		FinallyFlowContext finallyContext;
		UnconditionalFlowInfo subInfo;
		if (subRoutineStartLabel == null) {
			// no finally block
			insideSubContext = null;
			finallyContext = null;
			subInfo = null;
		} else {
			// analyse finally block first
			insideSubContext = new InsideSubRoutineFlowContext(flowContext, this);
			subInfo = 
				finallyBlock
					.analyseCode(
						currentScope,
						finallyContext = new FinallyFlowContext(flowContext, finallyBlock),
						flowInfo.copy().unconditionalInits().discardNullRelatedInitializations())
					.unconditionalInits();
			if (subInfo == FlowInfo.DEAD_END) {
				isSubRoutineEscaping = true;
				scope.problemReporter().finallyMustCompleteNormally(finallyBlock);
			}
			this.subRoutineInits = subInfo;
		}
		// process the try block in a context handling the local exceptions.
		ExceptionHandlingFlowContext handlingContext =
			new ExceptionHandlingFlowContext(
				insideSubContext == null ? flowContext : insideSubContext,
				tryBlock,
				caughtExceptionTypes,
				scope,
				flowInfo.unconditionalInits());

		FlowInfo tryInfo;
		if (tryBlock.isEmptyBlock()) {
			tryInfo = flowInfo;
			tryBlockExit = false;
		} else {
			tryInfo = tryBlock.analyseCode(currentScope, handlingContext, flowInfo.copy());
			tryBlockExit = !tryInfo.isReachable();
		}

		// check unreachable catch blocks
		handlingContext.complainIfUnusedExceptionHandlers(scope, this);

		// process the catch blocks - computing the minimal exit depth amongst try/catch
		if (catchArguments != null) {
			int catchCount;
			catchExits = new boolean[catchCount = catchBlocks.length];
			for (int i = 0; i < catchCount; i++) {
				// keep track of the inits that could potentially have led to this exception handler (for final assignments diagnosis)
				FlowInfo catchInfo =
					flowInfo
						.copy()
						.unconditionalInits()
						.addPotentialInitializationsFrom(
							handlingContext.initsOnException(caughtExceptionTypes[i]).unconditionalInits())
						.addPotentialInitializationsFrom(tryInfo.unconditionalInits())
						.addPotentialInitializationsFrom(handlingContext.initsOnReturn);

				// catch var is always set
				LocalVariableBinding catchArg = catchArguments[i].binding;
				FlowContext catchContext = insideSubContext == null ? flowContext : insideSubContext;
				catchInfo.markAsDefinitelyAssigned(catchArg);
				catchInfo.markAsDefinitelyNonNull(catchArg);
				/*
				"If we are about to consider an unchecked exception handler, potential inits may have occured inside
				the try block that need to be detected , e.g. 
				try { x = 1; throwSomething();} catch(Exception e){ x = 2} "
				"(uncheckedExceptionTypes notNil and: [uncheckedExceptionTypes at: index])
				ifTrue: [catchInits addPotentialInitializationsFrom: tryInits]."
				*/
				if (tryBlock.statements == null) {
					catchInfo.setReachMode(FlowInfo.UNREACHABLE);
				}
				catchInfo =
					catchBlocks[i].analyseCode(
						currentScope,
						catchContext,
						catchInfo);
				catchExits[i] = !catchInfo.isReachable();
				tryInfo = tryInfo.mergedWith(catchInfo.unconditionalInits());
			}
		}
		if (subRoutineStartLabel == null) {
			mergedInitStateIndex =
				currentScope.methodScope().recordInitializationStates(tryInfo);
			return tryInfo;
		}


		// we also need to check potential multiple assignments of final variables inside the finally block
		// need to include potential inits from returns inside the try/catch parts - 1GK2AOF
		finallyContext.complainOnDeferredChecks(
			tryInfo.isReachable() 
				? (tryInfo.addPotentialInitializationsFrom(insideSubContext.initsOnReturn))
				: insideSubContext.initsOnReturn, 
			currentScope);
		if (subInfo == FlowInfo.DEAD_END) {
			mergedInitStateIndex =
				currentScope.methodScope().recordInitializationStates(subInfo);
			return subInfo;
		} else {
			FlowInfo mergedInfo = tryInfo.addInitializationsFrom(subInfo);
			mergedInitStateIndex =
				currentScope.methodScope().recordInitializationStates(mergedInfo);
			return mergedInfo;
		}
	}

	public boolean isSubRoutineEscaping() {

		return isSubRoutineEscaping;
	}

	/**
	 * Try statement code generation with or without jsr bytecode use
	 *	post 1.5 target level, cannot use jsr bytecode, must instead inline finally block
	 * returnAddress is only allocated if jsr is allowed
	 */
	public void generateCode(BlockScope currentScope, CodeStream codeStream) {
		if ((bits & IsReachable) == 0) {
			return;
		}
		// in case the labels needs to be reinitialized
		// when the code generation is restarted in wide mode
		if (this.anyExceptionLabelsCount > 0) {
			this.anyExceptionLabels = NO_EXCEPTION_HANDLER;
			this.anyExceptionLabelsCount = 0;
		}
		int pc = codeStream.position;
		final int NO_FINALLY = 0;									// no finally block
		final int FINALLY_SUBROUTINE = 1; 					// finally is generated as a subroutine (using jsr/ret bytecodes)
		final int FINALLY_DOES_NOT_COMPLETE = 2;	// non returning finally is optimized with only one instance of finally block
		final int FINALLY_MUST_BE_INLINED = 3;			// finally block must be inlined since cannot use jsr/ret bytecodes >1.5
		int finallyMode;
		if (subRoutineStartLabel == null) { 
			finallyMode = NO_FINALLY;
		} else {
			if (this.isSubRoutineEscaping) {
				finallyMode = FINALLY_DOES_NOT_COMPLETE;
			} else if (scope.compilerOptions().inlineJsrBytecode) {
				finallyMode = FINALLY_MUST_BE_INLINED;
			} else {
				finallyMode = FINALLY_SUBROUTINE;
			}
		}
		boolean requiresNaturalExit = false;
		// preparing exception labels
		int maxCatches;
		ExceptionLabel[] exceptionLabels =
			new ExceptionLabel[maxCatches =
				catchArguments == null ? 0 : catchArguments.length];
		for (int i = 0; i < maxCatches; i++) {
			exceptionLabels[i] = new ExceptionLabel(codeStream, catchArguments[i].binding.type);
		}
		if (subRoutineStartLabel != null) {
			subRoutineStartLabel.initialize(codeStream);
			this.enterAnyExceptionHandler(codeStream);
		}
		// generate the try block
		tryBlock.generateCode(scope, codeStream);
		boolean tryBlockHasSomeCode = codeStream.position != pc;
		// flag telling if some bytecodes were issued inside the try block

		// place end positions of user-defined exception labels
		if (tryBlockHasSomeCode) {
			// natural exit may require subroutine invocation (if finally != null)
			Label naturalExitLabel = new Label(codeStream);
			if (!tryBlockExit) {
				int position = codeStream.position;
				switch(finallyMode) {
					case FINALLY_SUBROUTINE :
					case FINALLY_MUST_BE_INLINED :
						requiresNaturalExit = true;
						// fall through
					case NO_FINALLY :
						codeStream.goto_(naturalExitLabel);
						break;
					case FINALLY_DOES_NOT_COMPLETE :
						codeStream.goto_(subRoutineStartLabel);
						break;
				}
				codeStream.updateLastRecordedEndPC(tryBlock.scope, position);
				//goto is tagged as part of the try block
			}
			for (int i = 0; i < maxCatches; i++) {
				exceptionLabels[i].placeEnd();
			}
			/* generate sequence of handler, all starting by storing the TOS (exception
			thrown) into their own catch variables, the one specified in the source
			that must denote the handled exception.
			*/
			if (catchArguments != null) {
				for (int i = 0; i < maxCatches; i++) {
					// May loose some local variable initializations : affecting the local variable attributes
					if (preTryInitStateIndex != -1) {
						codeStream.removeNotDefinitelyAssignedVariables(currentScope, preTryInitStateIndex);
					}
					exceptionLabels[i].place();
					codeStream.incrStackSize(1);
					// optimizing the case where the exception variable is not actually used
					LocalVariableBinding catchVar;
					int varPC = codeStream.position;
					if ((catchVar = catchArguments[i].binding).resolvedPosition != -1) {
						codeStream.store(catchVar, false);
						catchVar.recordInitializationStartPC(codeStream.position);
						codeStream.addVisibleLocalVariable(catchVar);
					} else {
						codeStream.pop();
					}
					codeStream.recordPositionsFrom(varPC, catchArguments[i].sourceStart);
					// Keep track of the pcs at diverging point for computing the local attribute
					// since not passing the catchScope, the block generation will exitUserScope(catchScope)
					catchBlocks[i].generateCode(scope, codeStream);
					if (!catchExits[i]) {
						switch(finallyMode) {
							case FINALLY_SUBROUTINE :
							case FINALLY_MUST_BE_INLINED :
								requiresNaturalExit = true;
								// fall through
							case NO_FINALLY :
								codeStream.goto_(naturalExitLabel);
								break;
							case FINALLY_DOES_NOT_COMPLETE :
								codeStream.goto_(subRoutineStartLabel);
								break;
						}
					}
				}
			}
			this.exitAnyExceptionHandler();
			// extra handler for trailing natural exit (will be fixed up later on when natural exit is generated below)
			ExceptionLabel naturalExitExceptionHandler = 
				finallyMode == FINALLY_SUBROUTINE && requiresNaturalExit ? new ExceptionLabel(codeStream, null) : null;

			// addition of a special handler so as to ensure that any uncaught exception (or exception thrown
			// inside catch blocks) will run the finally block
			int finallySequenceStartPC = codeStream.position;
			if (subRoutineStartLabel != null) {
				this.placeAllAnyExceptionHandlers();
				if (naturalExitExceptionHandler != null) naturalExitExceptionHandler.place();
				
				if (preTryInitStateIndex != -1) {
					// reset initialization state, as for a normal catch block
					codeStream.removeNotDefinitelyAssignedVariables(currentScope, preTryInitStateIndex);
				}

				codeStream.incrStackSize(1);
				switch(finallyMode) {
					case FINALLY_SUBROUTINE :
						codeStream.store(anyExceptionVariable, false);
						codeStream.jsr(subRoutineStartLabel);
						codeStream.recordPositionsFrom(finallySequenceStartPC, finallyBlock.sourceStart);
						int position = codeStream.position;						
						codeStream.load(anyExceptionVariable);
						codeStream.athrow();
						codeStream.recordPositionsFrom(position, finallyBlock.sourceEnd);
						subRoutineStartLabel.place();
						codeStream.incrStackSize(1);
						position = codeStream.position;	
						codeStream.store(returnAddressVariable, false);
						codeStream.recordPositionsFrom(position, finallyBlock.sourceStart);
						finallyBlock.generateCode(scope, codeStream);
						position = codeStream.position;
						codeStream.ret(returnAddressVariable.resolvedPosition);
//						codeStream.updateLastRecordedEndPC(position);
						codeStream.recordPositionsFrom(
							position,
							finallyBlock.sourceEnd);
						// the ret bytecode is part of the subroutine
						break;
					case FINALLY_MUST_BE_INLINED :
						codeStream.store(anyExceptionVariable, false);
						codeStream.recordPositionsFrom(finallySequenceStartPC, finallyBlock.sourceStart);
						this.finallyBlock.generateCode(currentScope, codeStream);
						position = codeStream.position;
						codeStream.load(anyExceptionVariable);
						codeStream.athrow();
						subRoutineStartLabel.place();
						codeStream.recordPositionsFrom(position, finallyBlock.sourceEnd);
						break;
					case FINALLY_DOES_NOT_COMPLETE :
						codeStream.pop();
						subRoutineStartLabel.place();
						codeStream.recordPositionsFrom(finallySequenceStartPC, finallyBlock.sourceStart);
						finallyBlock.generateCode(scope, codeStream);
						break;
				}
				// will naturally fall into subsequent code after subroutine invocation
				naturalExitLabel.place();
				if (requiresNaturalExit) {
					switch(finallyMode) {
						case FINALLY_SUBROUTINE :
							int position = codeStream.position;
							// fix up natural exit handler
							naturalExitExceptionHandler.placeStart();
							codeStream.jsr(subRoutineStartLabel);
							naturalExitExceptionHandler.placeEnd();
							codeStream.recordPositionsFrom(
								position,
								finallyBlock.sourceEnd);	
							break;
						case FINALLY_MUST_BE_INLINED :
							// May loose some local variable initializations : affecting the local variable attributes
							// needed since any exception handler got inlined subroutine
							if (preTryInitStateIndex != -1) {
								codeStream.removeNotDefinitelyAssignedVariables(currentScope, preTryInitStateIndex);
							}
							// entire sequence for finally is associated to finally block
							finallyBlock.generateCode(scope, codeStream);
							break;
						case FINALLY_DOES_NOT_COMPLETE :
							break;
					}
				}
			} else {
				// no subroutine, simply position end label (natural exit == end)
				naturalExitLabel.place();
			}
		} else {
			// try block had no effect, only generate the body of the finally block if any
			if (subRoutineStartLabel != null) {
				finallyBlock.generateCode(scope, codeStream);
			}
		}
		// May loose some local variable initializations : affecting the local variable attributes
		if (mergedInitStateIndex != -1) {
			codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
			codeStream.addDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
		}
		codeStream.recordPositionsFrom(pc, this.sourceStart);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jdt.internal.compiler.ast.SubRoutineStatement#generateSubRoutineInvocation(org.eclipse.jdt.internal.compiler.lookup.BlockScope, org.eclipse.jdt.internal.compiler.codegen.CodeStream)
	 */
	public void generateSubRoutineInvocation(
			BlockScope currentScope,
			CodeStream codeStream) {
	
		if (this.isSubRoutineEscaping) {
				codeStream.goto_(this.subRoutineStartLabel);
		} else {
			if (currentScope.compilerOptions().inlineJsrBytecode) {
				// cannot use jsr bytecode, then simply inline the subroutine
				this.exitAnyExceptionHandler();				
				this.finallyBlock.generateCode(currentScope, codeStream);
				this.enterAnyExceptionHandler(codeStream);
			} else {
				// classic subroutine invocation, distinguish case of non-returning subroutine
				codeStream.jsr(this.subRoutineStartLabel);
			}
		}
	}

	public StringBuffer printStatement(int indent, StringBuffer output) {
		printIndent(indent, output).append("try \n"); //$NON-NLS-1$
		tryBlock.printStatement(indent + 1, output);

		//catches
		if (catchBlocks != null)
			for (int i = 0; i < catchBlocks.length; i++) {
					output.append('\n');
					printIndent(indent, output).append("catch ("); //$NON-NLS-1$
					catchArguments[i].print(0, output).append(") "); //$NON-NLS-1$
					catchBlocks[i].printStatement(indent + 1, output);
			}
		//finally
		if (finallyBlock != null) {
			output.append('\n');
			printIndent(indent, output).append("finally\n"); //$NON-NLS-1$
			finallyBlock.printStatement(indent + 1, output);
		}

		return output;
	}

	public void resolve(BlockScope upperScope) {

		// special scope for secret locals optimization.	
		this.scope = new BlockScope(upperScope);

		BlockScope tryScope = new BlockScope(scope);
		BlockScope finallyScope = null;
		
		if (finallyBlock != null) {
			if (finallyBlock.isEmptyBlock()) {
				if ((finallyBlock.bits & UndocumentedEmptyBlock) != 0) {
					scope.problemReporter().undocumentedEmptyBlock(finallyBlock.sourceStart, finallyBlock.sourceEnd);
				}
			} else {
				finallyScope = new BlockScope(scope, false); // don't add it yet to parent scope
	
				// provision for returning and forcing the finally block to run
				MethodScope methodScope = scope.methodScope();
	
				// the type does not matter as long as it is not a base type
				if (!upperScope.compilerOptions().inlineJsrBytecode) {
					this.returnAddressVariable =
						new LocalVariableBinding(SecretReturnName, upperScope.getJavaLangObject(), ClassFileConstants.AccDefault, false);
					finallyScope.addLocalVariable(returnAddressVariable);
					this.returnAddressVariable.setConstant(NotAConstant); // not inlinable
				}
				this.subRoutineStartLabel = new Label();
	
				this.anyExceptionVariable =
					new LocalVariableBinding(SecretAnyHandlerName, scope.getJavaLangThrowable(), ClassFileConstants.AccDefault, false);
				finallyScope.addLocalVariable(this.anyExceptionVariable);
				this.anyExceptionVariable.setConstant(NotAConstant); // not inlinable
	
				if (!methodScope.isInsideInitializer()) {
					MethodBinding methodBinding =
						((AbstractMethodDeclaration) methodScope.referenceContext).binding;
					if (methodBinding != null) {
						TypeBinding methodReturnType = methodBinding.returnType;
						if (methodReturnType.id != T_void) {
							this.secretReturnValue =
								new LocalVariableBinding(
									SecretLocalDeclarationName,
									methodReturnType,
									ClassFileConstants.AccDefault,
									false);
							finallyScope.addLocalVariable(this.secretReturnValue);
							this.secretReturnValue.setConstant(NotAConstant); // not inlinable
						}
					}
				}
				finallyBlock.resolveUsing(finallyScope);
				// force the finally scope to have variable positions shifted after its try scope and catch ones
				finallyScope.shiftScopes = new BlockScope[catchArguments == null ? 1 : catchArguments.length+1];
				finallyScope.shiftScopes[0] = tryScope;
			}
		}
		this.tryBlock.resolveUsing(tryScope);

		// arguments type are checked against JavaLangThrowable in resolveForCatch(..)
		if (this.catchBlocks != null) {
			int length = this.catchArguments.length;
			TypeBinding[] argumentTypes = new TypeBinding[length];
			boolean catchHasError = false;
			for (int i = 0; i < length; i++) {
				BlockScope catchScope = new BlockScope(scope);
				if (finallyScope != null){
					finallyScope.shiftScopes[i+1] = catchScope;
				}
				// side effect on catchScope in resolveForCatch(..)
				if ((argumentTypes[i] = catchArguments[i].resolveForCatch(catchScope)) == null) {
					catchHasError = true;
				}
				catchBlocks[i].resolveUsing(catchScope);
			}
			if (catchHasError) {
				return;
			}
			// Verify that the catch clause are ordered in the right way:
			// more specialized first.
			this.caughtExceptionTypes = new ReferenceBinding[length];
			for (int i = 0; i < length; i++) {
				caughtExceptionTypes[i] = (ReferenceBinding) argumentTypes[i];
				for (int j = 0; j < i; j++) {
					if (caughtExceptionTypes[i].isCompatibleWith(argumentTypes[j])) {
						scope.problemReporter().wrongSequenceOfExceptionTypesError(this, caughtExceptionTypes[i], i, argumentTypes[j]);
					}
				}
			}
		} else {
			caughtExceptionTypes = new ReferenceBinding[0];
		}
		
		if (finallyScope != null){
			// add finallyScope as last subscope, so it can be shifted behind try/catch subscopes.
			// the shifting is necessary to achieve no overlay in between the finally scope and its
			// sibling in term of local variable positions.
			this.scope.addSubscope(finallyScope);
		}
	}

	public void traverse(
		ASTVisitor visitor,
		BlockScope blockScope) {

		if (visitor.visit(this, blockScope)) {
			tryBlock.traverse(visitor, scope);
			if (catchArguments != null) {
				for (int i = 0, max = catchBlocks.length; i < max; i++) {
					catchArguments[i].traverse(visitor, scope);
					catchBlocks[i].traverse(visitor, scope);
				}
			}
			if (finallyBlock != null)
				finallyBlock.traverse(visitor, scope);
		}
		visitor.endVisit(this, blockScope);
	}
}
