/*******************************************************************************
 * Copyright (c) 2000, 2016 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
 *     Jesper Steen Moller - Bug 427089
 *******************************************************************************/
package org.eclipse.jdt.internal.debug.eval.ast.engine;

import java.util.ArrayList;
import java.util.EmptyStackException;
import java.util.Iterator;
import java.util.List;
import java.util.Stack;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.dom.*;
import org.eclipse.jdt.internal.debug.core.JDIDebugPlugin;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.AndAssignmentOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.AndOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.ArrayAllocation;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.ArrayInitializerInstruction;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.AssignmentOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.Cast;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.CompoundInstruction;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.ConditionalJump;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.Constructor;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.DivideAssignmentOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.DivideOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.Dup;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.DupX1;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.EqualEqualOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.GreaterEqualOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.GreaterOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.InstanceOfOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.Instruction;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.InstructionSequence;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.Jump;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.LeftShiftAssignmentOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.LeftShiftOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.LessEqualOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.LessOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.LocalVariableCreation;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.MinusAssignmentOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.MinusOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.MultiplyAssignmentOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.MultiplyOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.NoOp;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.NotOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.OrAssignmentOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.OrOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PlusAssignmentOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PlusOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.Pop;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PostfixMinusMinusOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PostfixPlusPlusOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PrefixMinusMinusOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PrefixPlusPlusOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushArrayLength;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushArrayType;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushBoolean;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushChar;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushClassLiteralValue;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushDouble;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushFieldVariable;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushFloat;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushInt;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushLocalVariable;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushLong;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushNull;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushPrimitiveType;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushStaticFieldVariable;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushString;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushThis;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushType;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.RemainderAssignmentOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.RemainderOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.ReturnInstruction;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.RightShiftAssignmentOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.RightShiftOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.SendMessage;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.SendStaticMessage;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.ThrowInstruction;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.TwiddleOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.UnaryMinusOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.UnaryPlusOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.UnsignedRightShiftAssignmentOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.UnsignedRightShiftOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.Value;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.XorAssignmentOperator;
import org.eclipse.jdt.internal.debug.eval.ast.instructions.XorOperator;
import org.eclipse.osgi.util.NLS;

import com.ibm.icu.text.MessageFormat;

/**
 * The AST instruction compiler generates a sequence of instructions
 * (InstructionSequence) from a DOM AST.
 */
public class ASTInstructionCompiler extends ASTVisitor {

	/**
	 * Represent a break or a continue instruction. These instructions needs are
	 * stored and managed later by their related statement.
	 */
	class CompleteInstruction {
		Jump fInstruction;
		String fLabel;
		boolean fIsBreak;

		public CompleteInstruction(Jump instruction, String label,
				boolean isBreak) {
			fInstruction = instruction;
			fLabel = label;
			fIsBreak = isBreak;
		}
	}

	/**
	 * Whether to print debug messages to the console
	 */
	private static boolean VERBOSE = false;

	private InstructionSequence fInstructions;

	/**
	 * The list of pending break and continue instruction.
	 */
	private List<CompleteInstruction> fCompleteInstructions;

	private int fStartPosition;

	private boolean fActive;

	private boolean fHasErrors;

	private Stack<Instruction> fStack;

	private int fCounter;

	// internal index used to create unique variable name
	private int fUniqueIdIndex = 0;

	/**
	 * Create a new AST instruction compiler
	 */
	public ASTInstructionCompiler(int startPosition, String snippet) {
		fStartPosition = startPosition;
		fInstructions = new InstructionSequence(snippet);
		fStack = new Stack<>();
		fCompleteInstructions = new ArrayList<>();
	}

	/**
	 * Returns the instruction sequence generated by this AST instruction
	 * compiler
	 */
	public InstructionSequence getInstructions() {
		return fInstructions;
	}

	/**
	 * Returns whether the generated instruction sequence has errors. Errors
	 * include:
	 * <ol>
	 * <li>AST contains unimplemented operations (features which will be
	 * supported, but aren't yet)</li>
	 * <li>AST contains unsupported operations (features which are not yet
	 * implemented and are likely NOT to be implemented)</li>
	 * </ol>
	 */
	public boolean hasErrors() {
		return fHasErrors;
	}

	private void setHasError(boolean value) {
		fHasErrors = value;
	}

	private void addErrorMessage(String message) {
		fInstructions.addError(message);
	}

	private boolean isActive() {
		return fActive;
	}

	private void setActive(boolean active) {
		fActive = active;
	}

	private void push(Instruction i) {
		fStack.push(i);
	}

	private void storeInstruction() {
		Instruction instruction = null;
		try {
			instruction = fStack.pop();
		}
		catch(EmptyStackException ese) {
			JDIDebugPlugin.log(new Status(
					IStatus.WARNING,
					JDIDebugPlugin.getUniqueIdentifier(),
					NLS.bind(EvaluationEngineMessages.ASTInstructionCompiler_4, fCounter),
					ese));
		}
		if(instruction != null) {
			fCounter++;
			if (instruction instanceof CompoundInstruction) {
				((CompoundInstruction) instruction).setEnd(fCounter);
			}
			fInstructions.add(instruction);
			verbose("Add " + instruction.toString()); //$NON-NLS-1$
		}
	}

	/**
	 * Prints the given message to the console if verbose mode is on.
	 *
	 * @param message
	 *            the message to display
	 */
	private void verbose(String message) {
		if (VERBOSE) {
			System.out.println(message);
		}
	}

	private String getTypeName(ITypeBinding typeBinding) {
		if (typeBinding.isRawType()) {
			typeBinding = typeBinding.getErasure();
		}
		if (typeBinding.isTypeVariable()) {
			ITypeBinding[] typeBounds = typeBinding.getTypeBounds();
			if (typeBounds.length > 0) {
				String name = getTypeName(typeBounds[0]);
				if (typeBounds.length > 1 && "java.lang.Object".equals(name)) { //$NON-NLS-1$
					return getTypeName(typeBounds[1]);
				}
				return name;
			}
			return "java.lang.Object"; //$NON-NLS-1$
		}
		StringBuilder name;
		if (typeBinding.isArray()) {
			name = new StringBuilder(getTypeName(typeBinding.getElementType()));
			int dimensions = typeBinding.getDimensions();
			for (int i = 0; i < dimensions; i++) {
				name.append("[]"); //$NON-NLS-1$
			}
			return name.toString();
		}
		//try it the old way
		name = new StringBuilder(Signature.getTypeErasure(typeBinding.getName()));
		IPackageBinding packageBinding = typeBinding.getPackage();
		typeBinding = typeBinding.getDeclaringClass();
		while (typeBinding != null) {
			name.insert(0, '$').insert(0, Signature.getTypeErasure(typeBinding.getName()));
			typeBinding = typeBinding.getDeclaringClass();
		}
		if (packageBinding != null && !packageBinding.isUnnamed()) {
			name.insert(0, '.').insert(0, packageBinding.getName());
		}
		return name.toString();
	}

	private String getTypeSignature(ITypeBinding typeBinding) {
		return Signature.createTypeSignature(getTypeName(typeBinding), true)
				.replace('.', '/');
	}

	private boolean isALocalType(ITypeBinding typeBinding) {
		while (typeBinding != null) {
			if (typeBinding.isLocal()) {
				return true;
			}
			typeBinding = typeBinding.getDeclaringClass();
		}
		return false;
	}

	private boolean containsALocalType(IMethodBinding methodBinding) {
		ITypeBinding[] typeBindings = methodBinding.getParameterTypes();
		for (ITypeBinding typeBinding : typeBindings) {
			if (isALocalType(typeBinding)) {
				return true;
			}
		}
		return false;
	}

	private int getEnclosingLevel(ASTNode node,
			ITypeBinding referenceTypeBinding) {
		ASTNode parent = node;
		ITypeBinding refbinding = referenceTypeBinding.isParameterizedType() ? referenceTypeBinding
				.getTypeDeclaration() : referenceTypeBinding;
		do {
			parent = parent.getParent();
		} while (parent != null
				&& !(parent instanceof AbstractTypeDeclaration || parent instanceof AnonymousClassDeclaration));
		if (parent == null) {
			return 0;
		}
		ITypeBinding parentBinding = null;
		if (parent instanceof AbstractTypeDeclaration) {
			parentBinding = ((AbstractTypeDeclaration) parent).resolveBinding();
		} else if (parent instanceof AnonymousClassDeclaration) {
			parentBinding = ((AnonymousClassDeclaration) parent)
					.resolveBinding();
		}
		if (parentBinding != null
				&& (parentBinding.isEqualTo(refbinding) || parentBinding
						.isCastCompatible(refbinding))) {
			return 0;
		}
		return getEnclosingLevel(parent, referenceTypeBinding) + 1;
	}

	private int getSuperLevel(ITypeBinding current, ITypeBinding reference) {
		if (current.equals(reference)) {
			return 0;
		}
		return getSuperLevel(current.getSuperclass(), reference);
	}

	/**
	 * Return the label associated with the given statement.
	 *
	 * @param statement
	 *            the statement.
	 * @return the associated label, or <code>null</code> if there is none.
	 */
	private String getLabel(Statement statement) {
		ASTNode parent = statement.getParent();
		if (parent instanceof LabeledStatement) {
			return ((LabeledStatement) parent).getLabel().getIdentifier();
		}
		return null;
	}

	/**
	 * Append a pop instruction in the instruction list if needed. A pop
	 * instruction is added when the expression has a return value, i.e. all
	 * expressions expect method invocation expressions which have
	 * <code>void</code> as return type and variable declaration expression.
	 *
	 * @param expression
	 *            the expression to test.
	 */
	private void addPopInstructionIfNeeded(Expression expression) {
		boolean pop = true;

		if (expression instanceof MethodInvocation) {
			IMethodBinding methodBinding = (IMethodBinding) ((MethodInvocation) expression)
					.getName().resolveBinding();
			if (methodBinding != null
					&& "void".equals(methodBinding.getReturnType().getName())) { //$NON-NLS-1$
				pop = false;
			}
		} else if (expression instanceof SuperMethodInvocation) {
			IMethodBinding methodBinding = (IMethodBinding) ((SuperMethodInvocation) expression)
					.getName().resolveBinding();
			if (methodBinding != null
					&& "void".equals(methodBinding.getReturnType().getName())) { //$NON-NLS-1$
				pop = false;
			}
		} else if (expression instanceof VariableDeclarationExpression) {
			pop = false;
		}

		if (pop) {
			addPopInstruction();
		}
	}

	/**
	 *
	 */
	private void addPopInstruction() {
		Instruction lastInstruction = fInstructions
				.getInstruction(fInstructions.getEnd());
		push(new Pop(lastInstruction.getSize() + 1));
		storeInstruction();
	}

	/**
	 * Check the current type of a value and the requested type to decide if
	 * boxing/un-boxing is required. If needed, the correct instruction is added
	 * to the stack Returns true if a storeInstruction() is needed after
	 * visiting the expression
	 */
	private boolean checkAutoBoxing(ITypeBinding valueBinding,
			ITypeBinding requestedBinding) {
		if (valueBinding == null) {
			return false; // unresolved
		}
		if (valueBinding.isPrimitive() == requestedBinding.isPrimitive()) {
			return false;
		}
		if (requestedBinding.isPrimitive()) {
			unBoxing(valueBinding);
		} else {
			boxing(requestedBinding, valueBinding);
		}
		return true;
	}

	/**
	 * Add to the stack the instruction to box a primitive value.
	 */
	private void boxing(ITypeBinding requestedBinding, ITypeBinding valueBinding) {
		String requestedTypeName = requestedBinding.getQualifiedName();
		if ("java.lang.Object".equals(requestedTypeName)) { //$NON-NLS-1$
			switch (valueBinding.getBinaryName().charAt(0)) {
			case 'I':
				push(new SendStaticMessage(
						"java.lang.Integer", "valueOf", "(I)Ljava/lang/Integer;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				break;
			case 'C':
				push(new SendStaticMessage(
						"java.lang.Character", "valueOf", "(C)Ljava/lang/Character;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				break;
			case 'B':
				push(new SendStaticMessage(
						"java.lang.Byte", "valueOf", "(B)Ljava/lang/Byte;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				break;
			case 'S':
				push(new SendStaticMessage(
						"java.lang.Short", "valueOf", "(S)Ljava/lang/Short;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				break;
			case 'J':
				push(new SendStaticMessage(
						"java.lang.Long", "valueOf", "(J)Ljava/lang/Long;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				break;
			case 'F':
				push(new SendStaticMessage(
						"java.lang.Float", "valueOf", "(F)Ljava/lang/Float;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				break;
			case 'D':
				push(new SendStaticMessage(
						"java.lang.Double", "valueOf", "(D)Ljava/lang/Double;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				break;
			case 'Z':
				push(new SendStaticMessage(
						"java.lang.Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				break;
			}
		} else if ("java.lang.Integer".equals(requestedTypeName)) { //$NON-NLS-1$
			push(new SendStaticMessage(requestedTypeName,
					"valueOf", "(I)Ljava/lang/Integer;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
		} else if ("java.lang.Character".equals(requestedTypeName)) { //$NON-NLS-1$
			push(new SendStaticMessage(requestedTypeName,
					"valueOf", "(C)Ljava/lang/Character;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
		} else if ("java.lang.Byte".equals(requestedTypeName)) { //$NON-NLS-1$
			push(new SendStaticMessage(requestedTypeName,
					"valueOf", "(B)Ljava/lang/Byte;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
		} else if ("java.lang.Short".equals(requestedTypeName)) { //$NON-NLS-1$
			push(new SendStaticMessage(requestedTypeName,
					"valueOf", "(S)Ljava/lang/Short;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
		} else if ("java.lang.Long".equals(requestedTypeName)) { //$NON-NLS-1$
			push(new SendStaticMessage(requestedTypeName,
					"valueOf", "(J)Ljava/lang/Long;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
		} else if ("java.lang.Float".equals(requestedTypeName)) { //$NON-NLS-1$
			push(new SendStaticMessage(requestedTypeName,
					"valueOf", "(F)Ljava/lang/Float;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
		} else if ("java.lang.Double".equals(requestedTypeName)) { //$NON-NLS-1$
			push(new SendStaticMessage(requestedTypeName,
					"valueOf", "(D)Ljava/lang/Double;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
		} else if ("java.lang.Boolean".equals(requestedTypeName)) { //$NON-NLS-1$
			push(new SendStaticMessage(requestedTypeName,
					"valueOf", "(Z)Ljava/lang/Boolean;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
		}
	}

	/**
	 * Add the instruction to un-box a non-primitive value if needed. Returns
	 * true if a storeInstruction() is needed after visiting the expression
	 */
	private boolean unBoxing(ITypeBinding valueBinding) {
		String valueTypeName = valueBinding.getQualifiedName();
		if ("java.lang.Integer".equals(valueTypeName)) { //$NON-NLS-1$
			push(new SendMessage("intValue", "()I", 0, null, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
		} else if ("java.lang.Character".equals(valueTypeName)) { //$NON-NLS-1$
			push(new SendMessage("charValue", "()C", 0, null, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
		} else if ("java.lang.Byte".equals(valueTypeName)) { //$NON-NLS-1$
			push(new SendMessage("byteValue", "()B", 0, null, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
		} else if ("java.lang.Short".equals(valueTypeName)) { //$NON-NLS-1$
			push(new SendMessage("shortValue", "()S", 0, null, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
		} else if ("java.lang.Long".equals(valueTypeName)) { //$NON-NLS-1$
			push(new SendMessage("longValue", "()J", 0, null, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
		} else if ("java.lang.Float".equals(valueTypeName)) { //$NON-NLS-1$
			push(new SendMessage("floatValue", "()F", 0, null, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
		} else if ("java.lang.Double".equals(valueTypeName)) { //$NON-NLS-1$
			push(new SendMessage("doubleValue", "()D", 0, null, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
		} else if ("java.lang.Boolean".equals(valueTypeName)) { //$NON-NLS-1$
			push(new SendMessage("booleanValue", "()Z", 0, null, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
		} else {
			return false;
		}
		return true;
	}

	/**
	 * End visit methods
	 *
	 * There are two paths to ending a visit to a node:
	 * <ol>
	 * <li>For control statements, the necessary control instructions (jump,
	 * conditional jump) are inserted into the instruction sequence</li>
	 * <li>For other cases, we simply remove the node's instruction from the
	 * stack and add it to the instruction sequence.</li>
	 * </ol>
	 */

	/**
	 * @see ASTVisitor#endVisit(AnonymousClassDeclaration)
	 */
	@Override
	public void endVisit(AnonymousClassDeclaration node) {

	}

	/**
	 * @see ASTVisitor#endVisit(ArrayAccess)
	 */
	@Override
	public void endVisit(ArrayAccess node) {
		if (!isActive() || hasErrors())
			return;
		ITypeBinding typeBinding = node.getIndex().resolveTypeBinding();
		if (typeBinding != null && unBoxing(typeBinding)) {
			// un-box the index, if required
			storeInstruction();
		}
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(ArrayCreation)
	 */
	@Override
	public void endVisit(ArrayCreation node) {
		if (!isActive() || hasErrors())
			return;
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(ArrayInitializer)
	 */
	@Override
	public void endVisit(ArrayInitializer node) {
		if (!isActive() || hasErrors())
			return;
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(ArrayType)
	 */
	@Override
	public void endVisit(ArrayType node) {
		if (!isActive() || hasErrors())
			return;
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(AssertStatement)
	 */
	@Override
	public void endVisit(AssertStatement node) {

	}

	/**
	 * @see ASTVisitor#endVisit(Assignment)
	 */
	@Override
	public void endVisit(Assignment node) {
		if (!isActive() || hasErrors())
			return;
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(Block)
	 */
	@Override
	public void endVisit(Block node) {
		if (!isActive() || hasErrors())
			return;
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(BooleanLiteral)
	 */
	@Override
	public void endVisit(BooleanLiteral node) {
		if (!isActive() || hasErrors())
			return;
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(BreakStatement)
	 */
	@Override
	public void endVisit(BreakStatement node) {
		if (!isActive() || hasErrors())
			return;
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(CastExpression)
	 */
	@Override
	public void endVisit(CastExpression node) {
		if (!isActive() || hasErrors())
			return;
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(CatchClause)
	 */
	@Override
	public void endVisit(CatchClause node) {

	}

	/**
	 * @see ASTVisitor#endVisit(CharacterLiteral)
	 */
	@Override
	public void endVisit(CharacterLiteral node) {
		if (!isActive() || hasErrors())
			return;
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(ClassInstanceCreation)
	 */
	@Override
	public void endVisit(ClassInstanceCreation node) {
		if (!isActive() || hasErrors())
			return;
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(CompilationUnit)
	 */
	@Override
	public void endVisit(CompilationUnit node) {
		while(!fStack.isEmpty()) {
			storeInstruction();
		}
	}

	/**
	 * @see ASTVisitor#endVisit(ConditionalExpression)
	 */
	@Override
	public void endVisit(ConditionalExpression node) {
		if (!isActive() || hasErrors())
			return;

		// Get the instructions
		int ifFalseAddress = fInstructions.getEnd();
		Instruction ifFalse = fInstructions.get(ifFalseAddress);
		int ifTrueAddress = ifFalseAddress - ifFalse.getSize();
		Instruction ifTrue = fInstructions.get(ifTrueAddress);
		int conditionalAddress = ifTrueAddress - ifTrue.getSize();

		// Insert the conditional jump
		ConditionalJump conditionalJump = new ConditionalJump(false);
		fInstructions.insert(conditionalJump, conditionalAddress + 1);

		// Insert the jump
		int jumpAddress = ifTrueAddress + 2;
		Jump jump = new Jump();
		fInstructions.insert(jump, jumpAddress);

		// Set the jump offsets
		conditionalJump.setOffset(ifTrue.getSize() + 1);
		jump.setOffset(ifFalse.getSize() + 1);

		fCounter += 2;
		storeInstruction();

	}

	/**
	 * @see ASTVisitor#endVisit(ConstructorInvocation)
	 */
	@Override
	public void endVisit(ConstructorInvocation node) {

	}

	/**
	 * @see ASTVisitor#endVisit(ContinueStatement)
	 */
	@Override
	public void endVisit(ContinueStatement node) {
		if (!isActive() || hasErrors())
			return;
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(DoStatement)
	 */
	@Override
	public void endVisit(DoStatement node) {
		if (!isActive() || hasErrors())
			return;

		/*
		 * The structure of generated instructions is :
		 *
		 * -- | body -- -- |condition -- - jump to the first instruction of the
		 * body if the condition is true.
		 */

		String label = getLabel(node);

		// get address of each part
		int conditionAddress = fInstructions.getEnd();
		Instruction condition = fInstructions.getInstruction(conditionAddress);
		int bodyAddress = conditionAddress - condition.getSize();
		Instruction body = fInstructions.getInstruction(bodyAddress);
		int bodyStartAddress = bodyAddress - body.getSize();

		// add the conditionnalJump
		ConditionalJump conditionalJump = new ConditionalJump(true);
		fInstructions.add(conditionalJump);
		fCounter++;

		// set jump offsets
		conditionalJump.setOffset(-(condition.getSize() + body.getSize() + 1));

		// for each pending break or continue instruction which are related to
		// this loop, set the offset of the corresponding jump.
		for (Iterator<CompleteInstruction> iter = fCompleteInstructions.iterator(); iter.hasNext();) {
			CompleteInstruction instruction = iter.next();
			Jump jumpInstruction = instruction.fInstruction;
			int instructionAddress = fInstructions.indexOf(jumpInstruction);
			if (instructionAddress > bodyStartAddress
					&& (instruction.fLabel == null || instruction.fLabel
							.equals(label))) {
				iter.remove();
				if (instruction.fIsBreak) {
					// jump to the instruction after the last jump
					jumpInstruction
							.setOffset((conditionAddress - instructionAddress) + 1);
				} else {
					// jump to the first instruction of the condition
					jumpInstruction.setOffset(bodyAddress - instructionAddress);
				}
			}
		}

		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(EmptyStatement)
	 */
	@Override
	public void endVisit(EmptyStatement node) {
		if (!isActive() || hasErrors())
			return;
		storeInstruction();
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.eclipse.jdt.core.dom.ASTVisitor#endVisit(org.eclipse.jdt.core.dom
	 * .EnhancedForStatement)
	 */
	@Override
	public void endVisit(EnhancedForStatement node) {
		if (!isActive() || hasErrors())
			return;

		/*
		 * The structure of generated instructions is :
		 *
		 * For an array: -- | <ParameterType>[] a= Expression | int i= 0 |
		 * <ParameterType> <ParameterName> -- -- | i < a.length - jump to the
		 * instruction after the last jump if the condition is false. -- -- | s=
		 * a[i] | Body -- -- - jump to the first instruction of the condition.
		 *
		 * For an Iterable: -- | Iterator i= Expression.iterator() |
		 * <ParameterType> <ParameterName> -- -- | i.hasNext() - jump to the
		 * instruction after the last jump if the condition is false. -- -- | s=
		 * i.next() | Body -- -- - jump to the first instruction of the
		 * condition.
		 */

		int bodyAddress = fInstructions.getEnd();
		Instruction body = fInstructions.getInstruction(bodyAddress);
		int conditionAddress = bodyAddress - body.getSize();
		Instruction condition = fInstructions.getInstruction(conditionAddress);
		int initAddress = conditionAddress - condition.getSize();

		// add conditional jump
		ConditionalJump condJump = new ConditionalJump(false);
		fInstructions.insert(condJump, conditionAddress + 1);
		bodyAddress++;
		fCounter++;
		condJump.setOffset(body.getSize() + 1);

		// add jump
		Jump jump = new Jump();
		fInstructions.add(jump);
		fCounter++;
		jump.setOffset(initAddress - (bodyAddress + 1));

		// for each pending break or continue instruction which are related to
		// this loop, set the offset of the corresponding jump.
		String label = getLabel(node);
		for (Iterator<CompleteInstruction> iter = fCompleteInstructions.iterator(); iter.hasNext();) {
			CompleteInstruction instruction = iter.next();
			Jump jumpInstruction = instruction.fInstruction;
			int instructionAddress = fInstructions.indexOf(jumpInstruction);
			if (instructionAddress > conditionAddress
					&& (instruction.fLabel == null || instruction.fLabel
							.equals(label))) {
				iter.remove();
				if (instruction.fIsBreak) {
					// jump to the instruction after the last jump
					jumpInstruction
							.setOffset((bodyAddress - instructionAddress) + 1);
				} else {
					// jump to the first instruction of the condition
					jumpInstruction.setOffset(initAddress - instructionAddress);
				}
			}
		}

		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(ExpressionStatement)
	 */
	@Override
	public void endVisit(ExpressionStatement node) {
		if (!isActive() || hasErrors())
			return;

		addPopInstructionIfNeeded(node.getExpression());
	}

	/**
	 * @see ASTVisitor#endVisit(FieldAccess)
	 */
	@Override
	public void endVisit(FieldAccess node) {
		if (!isActive() || hasErrors())
			return;
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(FieldDeclaration)
	 */
	@Override
	public void endVisit(FieldDeclaration node) {

	}

	/**
	 * @see ASTVisitor#endVisit(ForStatement)
	 */
	@Override
	public void endVisit(ForStatement node) {
		if (!isActive() || hasErrors())
			return;

		/*
		 * The structure of generated instructions is :
		 *
		 * -- |initialization -- -- |condition -- - jump to the instruction
		 * after the last jump if the condition is false. -- | body -- -- |
		 * updaters -- - jump to the first instruction of the condition.
		 */

		String label = getLabel(node);
		boolean hasCondition = node.getExpression() != null;

		// get address of each part
		int updatersAddress = fInstructions.getEnd();
		Instruction updaters = fInstructions.getInstruction(updatersAddress);
		int bodyAddress = updatersAddress - updaters.getSize();
		Instruction body = fInstructions.getInstruction(bodyAddress);
		int bodyStartAddress = bodyAddress - body.getSize();

		int conditionAddress;
		Instruction condition;

		if (hasCondition) {
			conditionAddress = bodyStartAddress;
			condition = fInstructions.getInstruction(conditionAddress);
		} else {
			conditionAddress = 0;
			condition = null;
		}

		// add jump
		Jump jump = new Jump();
		fInstructions.add(jump);
		fCounter++;

		if (hasCondition) {
			// add conditional jump
			ConditionalJump condJump = new ConditionalJump(false);
			fInstructions.insert(condJump, conditionAddress + 1);
			bodyAddress++;
			bodyStartAddress++;
			updatersAddress++;
			fCounter++;
			// set conditional jump offset
			condJump.setOffset(body.getSize() + updaters.getSize() + 1);
		}

		// set jump offset
		jump.setOffset(-((hasCondition && (condition != null) ? condition
				.getSize() : 0) + body.getSize() + updaters.getSize() + 2));

		// for each pending break or continue instruction which are related to
		// this loop, set the offset of the corresponding jump.
		for (Iterator<CompleteInstruction> iter = fCompleteInstructions.iterator(); iter.hasNext();) {
			CompleteInstruction instruction = iter.next();
			Jump jumpInstruction = instruction.fInstruction;
			int instructionAddress = fInstructions.indexOf(jumpInstruction);
			if (instructionAddress > bodyStartAddress
					&& (instruction.fLabel == null || instruction.fLabel
							.equals(label))) {
				iter.remove();
				if (instruction.fIsBreak) {
					// jump to the instruction after the last jump
					jumpInstruction
							.setOffset((updatersAddress - instructionAddress) + 1);
				} else {
					// jump to the first instruction of the condition
					jumpInstruction.setOffset(bodyAddress - instructionAddress);
				}
			}
		}

		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(IfStatement)
	 */
	@Override
	public void endVisit(IfStatement node) {
		if (!isActive() || hasErrors())
			return;

		boolean hasElseStatement = node.getElseStatement() != null;

		// Get the instructions

		int ifFalseAddress = 0;
		Instruction ifFalse = null;
		int ifTrueAddress = 0;
		Instruction ifTrue = null;

		if (hasElseStatement) {
			ifFalseAddress = fInstructions.getEnd();
			ifFalse = fInstructions.get(ifFalseAddress);
			ifTrueAddress = ifFalseAddress - ifFalse.getSize();
			ifTrue = fInstructions.get(ifTrueAddress);
		} else {
			ifTrueAddress = fInstructions.getEnd();
			ifTrue = fInstructions.get(ifTrueAddress);
		}

		int conditionalAddress = ifTrueAddress - ifTrue.getSize();

		// Insert the conditional jump
		ConditionalJump conditionalJump = new ConditionalJump(false);
		fInstructions.insert(conditionalJump, conditionalAddress + 1);
		// Set the jump offset
		conditionalJump.setOffset(ifTrue.getSize()
				+ ((hasElseStatement) ? 1 : 0));
		fCounter++;

		if (hasElseStatement) {
			// Insert the jump
			int jumpAddress = ifTrueAddress + 2;
			Jump jump = new Jump();
			fInstructions.insert(jump, jumpAddress);
			// Set the jump offset
			jump.setOffset(ifFalse.getSize() + 1);
			fCounter++;
		}

		storeInstruction();

	}

	/**
	 * @see ASTVisitor#endVisit(ImportDeclaration)
	 */
	@Override
	public void endVisit(ImportDeclaration node) {

	}

	/**
	 * @see ASTVisitor#endVisit(InfixExpression)
	 */
	@Override
	public void endVisit(InfixExpression node) {
	}

	/**
	 * @see ASTVisitor#endVisit(Initializer)
	 */
	@Override
	public void endVisit(Initializer node) {

	}

	/**
	 * @see ASTVisitor#endVisit(InstanceofExpression)
	 */
	@Override
	public void endVisit(InstanceofExpression node) {
		if (!isActive() || hasErrors())
			return;
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(Javadoc)
	 */
	@Override
	public void endVisit(Javadoc node) {

	}

	/**
	 * @see ASTVisitor#endVisit(LabeledStatement)
	 */
	@Override
	public void endVisit(LabeledStatement node) {
		if (!isActive() || hasErrors())
			return;

		String label = node.getLabel().getIdentifier();

		// for each pending continue instruction which are related to
		// this statement, set the offset of the corresponding jump.
		for (Iterator<CompleteInstruction> iter = fCompleteInstructions.iterator(); iter.hasNext();) {
			CompleteInstruction instruction = iter.next();
			if (instruction.fLabel != null && instruction.fLabel.equals(label)) {
				iter.remove();
				Jump jumpInstruction = instruction.fInstruction;
				int instructionAddress = fInstructions.indexOf(jumpInstruction);
				if (instruction.fIsBreak) {
					// jump to the instruction after the statement
					jumpInstruction.setOffset(fInstructions.getEnd()
							- instructionAddress);
				}
			}
		}
	}

	/**
	 * @see ASTVisitor#endVisit(MethodDeclaration)
	 */
	@Override
	public void endVisit(MethodDeclaration node) {
		setActive(false);
	}

	/**
	 * @see ASTVisitor#endVisit(MethodInvocation)
	 */
	@Override
	public void endVisit(MethodInvocation node) {
		if (!isActive() || hasErrors())
			return;
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(NullLiteral)
	 */
	@Override
	public void endVisit(NullLiteral node) {
		if (!isActive() || hasErrors())
			return;
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(NumberLiteral)
	 */
	@Override
	public void endVisit(NumberLiteral node) {
		if (!isActive() || hasErrors())
			return;
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(PackageDeclaration)
	 */
	@Override
	public void endVisit(PackageDeclaration node) {

	}

	/**
	 * @see ASTVisitor#endVisit(SimpleType)
	 */
	@Override
	public void endVisit(ParameterizedType node) {
		if (!isActive() || hasErrors())
			return;
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(ParenthesizedExpression)
	 */
	@Override
	public void endVisit(ParenthesizedExpression node) {

	}

	/**
	 * @see ASTVisitor#endVisit(PostfixExpression)
	 */
	@Override
	public void endVisit(PostfixExpression node) {
		if (!isActive() || hasErrors())
			return;
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(PrefixExpression)
	 */
	@Override
	public void endVisit(PrefixExpression node) {
		if (!isActive() || hasErrors())
			return;
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(PrimitiveType)
	 */
	@Override
	public void endVisit(PrimitiveType node) {
		if (!isActive() || hasErrors())
			return;
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(QualifiedName)
	 */
	@Override
	public void endVisit(QualifiedName node) {
	}

	/**
	 * @see ASTVisitor#endVisit(SimpleType)
	 */
	@Override
	public void endVisit(QualifiedType node) {
		if (!isActive() || hasErrors())
			return;
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(ReturnStatement)
	 */
	@Override
	public void endVisit(ReturnStatement node) {
		if (!isActive() || hasErrors())
			return;
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(SimpleName)
	 */
	@Override
	public void endVisit(SimpleName node) {
		if (!isActive() || hasErrors())
			return;
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(SimpleType)
	 */
	@Override
	public void endVisit(SimpleType node) {
		if (!isActive() || hasErrors())
			return;
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(SingleVariableDeclaration)
	 */
	@Override
	public void endVisit(SingleVariableDeclaration node) {
		if (!isActive() || hasErrors())
			return;
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(StringLiteral)
	 */
	@Override
	public void endVisit(StringLiteral node) {
		if (!isActive() || hasErrors())
			return;
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(SuperConstructorInvocation)
	 */
	@Override
	public void endVisit(SuperConstructorInvocation node) {

	}

	/**
	 * @see ASTVisitor#endVisit(SuperFieldAccess)
	 */
	@Override
	public void endVisit(SuperFieldAccess node) {
		if (!isActive() || hasErrors())
			return;
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(SuperMethodInvocation)
	 */
	@Override
	public void endVisit(SuperMethodInvocation node) {
		if (!isActive() || hasErrors())
			return;
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(SwitchCase)
	 */
	@Override
	public void endVisit(SwitchCase node) {
		// never called
	}

	/**
	 * @see ASTVisitor#endVisit(SwitchStatement)
	 */
	@Override
	public void endVisit(SwitchStatement node) {
		// nothing to do
	}

	/**
	 * @see ASTVisitor#endVisit(SynchronizedStatement)
	 */
	@Override
	public void endVisit(SynchronizedStatement node) {

	}

	/**
	 * @see ASTVisitor#endVisit(ThisExpression)
	 */
	@Override
	public void endVisit(ThisExpression node) {
		if (!isActive() || hasErrors())
			return;
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(ThrowStatement)
	 */
	@Override
	public void endVisit(ThrowStatement node) {
		if (!isActive() || hasErrors())
			return;
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(TryStatement)
	 */
	@Override
	public void endVisit(TryStatement node) {

	}

	/**
	 * @see ASTVisitor#endVisit(TypeDeclaration)
	 */
	@Override
	public void endVisit(TypeDeclaration node) {

	}

	/**
	 * @see ASTVisitor#endVisit(TypeDeclarationStatement)
	 */
	@Override
	public void endVisit(TypeDeclarationStatement node) {

	}

	/**
	 * @see ASTVisitor#endVisit(TypeLiteral)
	 */
	@Override
	public void endVisit(TypeLiteral node) {
		if (!isActive() || hasErrors())
			return;
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(VariableDeclarationExpression)
	 */
	@Override
	public void endVisit(VariableDeclarationExpression node) {

	}

	/**
	 * @see ASTVisitor#endVisit(VariableDeclarationFragment)
	 */
	@Override
	public void endVisit(VariableDeclarationFragment node) {
		if (!isActive() || hasErrors())
			return;
		storeInstruction();
	}

	/**
	 * @see ASTVisitor#endVisit(VariableDeclarationStatement)
	 */
	@Override
	public void endVisit(VariableDeclarationStatement node) {

	}

	/**
	 * @see ASTVisitor#endVisit(WhileStatement)
	 */
	@Override
	public void endVisit(WhileStatement node) {
		if (!isActive() || hasErrors())
			return;

		/*
		 * The structure of generated instructions is :
		 *
		 * -- |condition -- - jump to the instruction after the last jump if the
		 * condition is false. -- | body -- - jump to the first instruction of
		 * the condition.
		 */

		String label = getLabel(node);

		// get address of each part
		int bodyAddress = fInstructions.getEnd();
		Instruction body = fInstructions.getInstruction(bodyAddress);
		int conditionAddress = bodyAddress - body.getSize();
		Instruction condition = fInstructions.getInstruction(conditionAddress);

		// add the conditionnalJump
		ConditionalJump conditionalJump = new ConditionalJump(false);
		fInstructions.insert(conditionalJump, conditionAddress + 1);

		// add the jump
		Jump jump = new Jump();
		fInstructions.add(jump);

		// set jump offsets
		conditionalJump.setOffset(body.getSize() + 1);
		jump.setOffset(-(condition.getSize() + body.getSize() + 2));

		// for each pending break or continue instruction which are related to
		// this loop, set the offset of the corresponding jump.
		for (Iterator<CompleteInstruction> iter = fCompleteInstructions.iterator(); iter.hasNext();) {
			CompleteInstruction instruction = iter.next();
			Jump jumpInstruction = instruction.fInstruction;
			int instructionAddress = fInstructions.indexOf(jumpInstruction);
			if (instructionAddress > conditionAddress
					&& (instruction.fLabel == null || instruction.fLabel
							.equals(label))) {
				iter.remove();
				if (instruction.fIsBreak) {
					// jump to the instruction after the last jump
					jumpInstruction
							.setOffset((bodyAddress - instructionAddress) + 2);
				} else {
					// jump to the first instruction of the condition
					jumpInstruction.setOffset((conditionAddress - condition
							.getSize()) - instructionAddress);
				}
			}
		}

		fCounter += 2;
		storeInstruction();
	}

	/*
	 * Visit methods
	 *
	 * There are two variations of node visiting: <ol> <li>Push the instruction
	 * corresponding to the node onto the stack and return <code>true</code> to
	 * visit the children of the node.</li> <li>Push the instruction
	 * corresponding to the node onto the stack and visit the children of the
	 * node manually (return <code>false</code> to avoid the default child
	 * visiting implementation).</li> </ol>
	 */

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.
	 * AnnotationTypeDeclaration)
	 */
	@Override
	public boolean visit(AnnotationTypeDeclaration node) {
		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.
	 * AnnotationTypeMemberDeclaration)
	 */
	@Override
	public boolean visit(AnnotationTypeMemberDeclaration node) {
		return false;
	}

	/**
	 * @see ASTVisitor#visit(AnonymousClassDeclaration)
	 */
	@Override
	public boolean visit(AnonymousClassDeclaration node) {
		if (!isActive()) {
			return true;
		}
		setHasError(true);
		addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Anonymous_type_declaration_cannot_be_used_in_an_evaluation_expression_2);
		return false;
	}

	/**
	 * @see ASTVisitor#visit(ArrayAccess)
	 */
	@Override
	public boolean visit(ArrayAccess node) {
		if (!isActive()) {
			return false;
		}

		push(new org.eclipse.jdt.internal.debug.eval.ast.instructions.ArrayAccess(
				fCounter));

		return true;
	}

	/**
	 * @see ASTVisitor#visit(ArrayCreation)
	 */
	@Override
	public boolean visit(ArrayCreation node) {
		if (!isActive()) {
			return false;
		}

		ArrayType arrayType = node.getType();

		ITypeBinding binding = resolveTypeBinding(arrayType);
		if (binding != null && isALocalType(binding.getElementType())) {
			addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Local_type_array_instance_creation_cannot_be_used_in_an_evaluation_expression_29);
			setHasError(true);
			return false;
		}

		push(new ArrayAllocation(arrayType.getDimensions(), node.dimensions()
				.size(), node.getInitializer() != null, fCounter));

		return true;
	}

	/**
	 * @see ASTVisitor#visit(ArrayInitializer)
	 */
	@Override
	public boolean visit(ArrayInitializer node) {
		if (!isActive()) {
			return false;
		}

		ITypeBinding typeBinding = resolveTypeBinding(node);
		if (typeBinding != null) {
			int dimension = typeBinding.getDimensions();
			String signature = getTypeSignature(typeBinding.getElementType());
			push(new ArrayInitializerInstruction(signature, node.expressions()
					.size(), dimension, fCounter));
		}

		return true;
	}

	/**
	 * @see ASTVisitor#visit(ArrayType)
	 */
	@Override
	public boolean visit(ArrayType node) {
		if (!isActive()) {
			return false;
		}
		ITypeBinding arrayTypeBinding = resolveTypeBinding(node);
		if (arrayTypeBinding != null) {
			int dimension = arrayTypeBinding.getDimensions();
			String signature = getTypeSignature(arrayTypeBinding
					.getElementType());
			push(new PushArrayType(signature, dimension, fCounter));
		}

		return false;
	}

	/**
	 * @see ASTVisitor#visit(AssertStatement)
	 */
	@Override
	public boolean visit(AssertStatement node) {
		if (!isActive()) {
			return false;
		}
		setHasError(true);
		addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Assert_statement_cannot_be_used_in_an_evaluation_expression_3);
		return false;
	}

	/**
	 * @see ASTVisitor#visit(Assignment)
	 */
	@Override
	public boolean visit(Assignment node) {
		if (!isActive()) {
			return false;
		}
		Expression leftHandSide = node.getLeftHandSide();
		Expression rightHandSide = node.getRightHandSide();
		int variableTypeId = getTypeId(leftHandSide);
		int valueTypeId = getTypeId(rightHandSide);

		String opToken = node.getOperator().toString();
		int opTokenLength = opToken.length();
		char char0 = opToken.charAt(0);
		char char2 = '\0';
		if (opTokenLength > 2) {
			char2 = opToken.charAt(2);
		}

		ITypeBinding rightBinding = resolveTypeBinding(rightHandSide);
		if (rightBinding == null) {
			return false;
		}
		ITypeBinding leftBinding = resolveTypeBinding(leftHandSide);
		if (leftBinding == null) {
			return false;
		}
		if (variableTypeId == Instruction.T_Object) {
			// If the variable is an object, the value may need to be boxed for
			// the simple assignment.
			// For the compound assignment operators, the value of the variable
			// have to be un-boxed before the operation is done, then re-boxed
			// to
			// to be stored in the variable.

			int unboxedVariableTypeId = getUnBoxedTypeId(leftHandSide);
			int unboxedValueTypeId = getUnBoxedTypeId(rightHandSide);
			int unboxedResultTypeId = Instruction.getBinaryPromotionType(
					unboxedVariableTypeId, unboxedValueTypeId);

			push(new AssignmentOperator(variableTypeId, variableTypeId,
					fCounter));

			leftHandSide.accept(this);

			if (char0 == '=') {

				boolean storeRequired = false;
				if (rightBinding.isPrimitive()) {
					boxing(leftBinding, rightBinding);
					storeRequired = true;
				}
				rightHandSide.accept(this);
				if (storeRequired) {
					storeInstruction(); // boxing
				}

			} else {
				boolean unrecognized = false;

				boxing(leftBinding, rightBinding);

				switch (char0) {
				case '=': // equal
					break;
				case '+': // plus equal
					push(new PlusOperator(unboxedVariableTypeId,
							unboxedValueTypeId, unboxedResultTypeId, fCounter));
					break;
				case '-': // minus equal
					push(new MinusOperator(unboxedVariableTypeId,
							unboxedValueTypeId, unboxedResultTypeId, fCounter));
					break;
				case '*': // multiply equal
					push(new MultiplyOperator(unboxedVariableTypeId,
							unboxedValueTypeId, unboxedResultTypeId, fCounter));
					break;
				case '/': // divide equal
					push(new DivideOperator(unboxedVariableTypeId,
							unboxedValueTypeId, unboxedResultTypeId, fCounter));
					break;
				case '%': // remainder equal
					push(new RemainderOperator(unboxedVariableTypeId,
							unboxedValueTypeId, unboxedResultTypeId, fCounter));
					break;
				case '^': // XOr equal
					push(new XorOperator(unboxedVariableTypeId,
							unboxedValueTypeId, unboxedResultTypeId, fCounter));
					break;
				case '|': // or equal
					push(new OrOperator(unboxedVariableTypeId,
							unboxedValueTypeId, unboxedResultTypeId, fCounter));
					break;
				case '&': // and equal
					push(new AndOperator(unboxedVariableTypeId,
							unboxedValueTypeId, unboxedResultTypeId, fCounter));
					break;
				case '<': // left shift equal
					push(new LeftShiftOperator(unboxedVariableTypeId,
							unboxedValueTypeId, unboxedResultTypeId, fCounter));
					break;
				case '>': // right shift equal or unsigned right shift equal
					switch (char2) {
					case '=': // right shift equal
						push(new RightShiftOperator(unboxedVariableTypeId,
								unboxedValueTypeId, unboxedResultTypeId,
								fCounter));
						break;
					case '>': // unsigned right shift equal
						push(new UnsignedRightShiftOperator(
								unboxedVariableTypeId, unboxedValueTypeId,
								unboxedResultTypeId, fCounter));
						break;
					default:
						unrecognized = true;
						break;
					}
					break;
				default:
					unrecognized = true;
					break;
				}

				if (unrecognized) {
					setHasError(true);
					addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Unrecognized_assignment_operator____4
							+ opToken);
					return false;
				}

				unBoxing(leftBinding);
				push(new Dup());
				storeInstruction(); // dupe
				storeInstruction(); // un-boxing

				boolean storeRequired = unBoxing(rightBinding);
				rightHandSide.accept(this);
				if (storeRequired) {
					storeInstruction(); // un-boxing
				}

				storeInstruction(); // operation
				storeInstruction(); // boxing

			}

		} else {
			boolean unrecognized = false;

			switch (char0) {
			case '=': // equal
				push(new AssignmentOperator(variableTypeId, valueTypeId,
						fCounter));
				break;
			case '+': // plus equal
				push(new PlusAssignmentOperator(variableTypeId, valueTypeId,
						fCounter));
				break;
			case '-': // minus equal
				push(new MinusAssignmentOperator(variableTypeId, valueTypeId,
						fCounter));
				break;
			case '*': // multiply equal
				push(new MultiplyAssignmentOperator(variableTypeId,
						valueTypeId, fCounter));
				break;
			case '/': // divide equal
				push(new DivideAssignmentOperator(variableTypeId, valueTypeId,
						fCounter));
				break;
			case '%': // remainder equal
				push(new RemainderAssignmentOperator(variableTypeId,
						valueTypeId, fCounter));
				break;
			case '^': // XOr equal
				push(new XorAssignmentOperator(variableTypeId, valueTypeId,
						fCounter));
				break;
			case '|': // or equal
				push(new OrAssignmentOperator(variableTypeId, valueTypeId,
						fCounter));
				break;
			case '&': // and equal
				push(new AndAssignmentOperator(variableTypeId, valueTypeId,
						fCounter));
				break;
			case '<': // left shift equal
				push(new LeftShiftAssignmentOperator(variableTypeId,
						valueTypeId, fCounter));
				break;
			case '>': // right shift equal or unsigned right shift equal
				switch (char2) {
				case '=': // right shift equal
					push(new RightShiftAssignmentOperator(variableTypeId,
							valueTypeId, fCounter));
					break;
				case '>': // unsigned right shift equal
					push(new UnsignedRightShiftAssignmentOperator(
							variableTypeId, valueTypeId, fCounter));
					break;
				default:
					unrecognized = true;
					break;
				}
				break;
			default:
				unrecognized = true;
				break;
			}

			if (unrecognized) {
				setHasError(true);
				addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Unrecognized_assignment_operator____4
						+ opToken);
				return false;
			}

			leftHandSide.accept(this);
			boolean storeRequired = unBoxing(rightBinding);
			rightHandSide.accept(this);
			if (storeRequired) {
				storeInstruction();
			}
		}

		return false;

	}

	/**
	 * @see ASTVisitor#visit(Block)
	 */
	@Override
	public boolean visit(Block node) {
		int start = node.getStartPosition();
		if (start == fStartPosition || start == (fStartPosition + 1)) {
			setActive(true);
		}
		if (!isActive()) {
			return true;
		}

		push(new NoOp(fCounter));

		return true;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.
	 * BlockComment)
	 */
	@Override
	public boolean visit(BlockComment node) {
		return false;
	}

	/**
	 * @see ASTVisitor#visit(BooleanLiteral)
	 */
	@Override
	public boolean visit(BooleanLiteral node) {
		if (!isActive()) {
			return false;
		}

		push(new PushBoolean(node.booleanValue()));

		return true;
	}

	/**
	 * @see ASTVisitor#visit(BreakStatement)
	 */
	@Override
	public boolean visit(BreakStatement node) {
		if (!isActive()) {
			return false;
		}
		// create the equivalent jump instruction in the instruction
		// and add an element in the list of pending break and continue
		// instructions
		Jump instruction = new Jump();
		SimpleName labelName = node.getLabel();
		String label = null;
		if (labelName != null) {
			label = labelName.getIdentifier();
		}
		push(instruction);
		fCompleteInstructions.add(new CompleteInstruction(instruction, label,
				true));

		return false;
	}

	/**
	 * @see ASTVisitor#visit(CastExpression)
	 */
	@Override
	public boolean visit(CastExpression node) {
		if (!isActive()) {
			return false;
		}

		Type type = node.getType();
		int typeId = getTypeId(type);
		ITypeBinding typeBinding = resolveTypeBinding(type);

		if (typeBinding != null) {
			String baseTypeSignature;
			int dimension = typeBinding.getDimensions();
			if (typeBinding.isArray()) {
				typeBinding = typeBinding.getElementType();
			}
			baseTypeSignature = getTypeName(typeBinding);
			push(new Cast(typeId, baseTypeSignature, dimension, fCounter));
			node.getExpression().accept(this);
		}

		return false;
	}

	/**
	 * @see ASTVisitor#visit(CatchClause)
	 */
	@Override
	public boolean visit(CatchClause node) {
		if (!isActive()) {
			return false;
		}
		setHasError(true);
		addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Catch_clause_cannot_be_used_in_an_evaluation_expression_6);
		return false;
	}

	/**
	 * @see ASTVisitor#visit(CharacterLiteral)
	 */
	@Override
	public boolean visit(CharacterLiteral node) {
		if (!isActive()) {
			return false;
		}

		push(new PushChar(node.charValue()));

		return true;
	}

	/**
	 * return false, visit expression, type name & arguments, don't visit body
	 * declaration
	 *
	 * @see ASTVisitor#visit(ClassInstanceCreation)
	 */
	@Override
	public boolean visit(ClassInstanceCreation node) {
		if (!isActive()) {
			return true;
		}

		if (node.getAnonymousClassDeclaration() != null) {
			setHasError(true);
			addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Anonymous_type_declaration_cannot_be_used_in_an_evaluation_expression_7);
		}

		IMethodBinding methodBinding = node.resolveConstructorBinding();
		if (methodBinding == null) {
			setHasError(true);
			addErrorMessage(MessageFormat.format(
					EvaluationEngineMessages.ASTInstructionCompiler_1,
					new Object[] { node.toString() }));
			return false;
		}
		ITypeBinding typeBinding = methodBinding.getDeclaringClass();

		boolean isInstanceMemberType = typeBinding.isMember()
				&& !Modifier.isStatic(typeBinding.getModifiers());

		if (isALocalType(typeBinding)) {
			setHasError(true);
			addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Constructor_of_a_local_type_cannot_be_used_in_an_evaluation_expression_8);
		}

		if (containsALocalType(methodBinding)) {
			setHasError(true);
			addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Constructor_which_contains_a_local_type_as_parameter_cannot_be_used_in_an_evaluation_expression_30);
		}

		if (hasErrors()) {
			return false;
		}

		int paramCount = methodBinding.getParameterTypes().length;

		String enclosingTypeSignature = null;
		ITypeBinding enclosingTypeBinding = null;
		if (isInstanceMemberType) {
			enclosingTypeBinding = typeBinding.getDeclaringClass();
			if (enclosingTypeBinding == null) {
				setHasError(true);
				addErrorMessage(MessageFormat.format(
						EvaluationEngineMessages.ASTInstructionCompiler_2,
						new Object[] { typeBinding.getQualifiedName() }));
				return false;
			}
			enclosingTypeSignature = getTypeSignature(enclosingTypeBinding);
			paramCount++;
		}

		String signature = getMethodSignature(methodBinding,
				enclosingTypeSignature).replace('.', '/');

		push(new Constructor(signature, paramCount, fCounter));

		push(new PushType(getTypeName(typeBinding)));
		storeInstruction();

		if (isInstanceMemberType) {
			Expression optionalExpression = node.getExpression();
			if (optionalExpression != null) {
				optionalExpression.accept(this);
			} else {
				// for a non-static inner class, check if we are not in a static
				// context (method)
				ASTNode parent = node;
				do {
					parent = parent.getParent();
				} while (!(parent instanceof MethodDeclaration));
				if (Modifier.isStatic(((MethodDeclaration) parent)
						.getModifiers())) {
					setHasError(true);
					addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Must_explicitly_qualify_the_allocation_with_an_instance_of_the_enclosing_type_33);
					return false;
				}

				push(new PushThis(getEnclosingLevel(node, enclosingTypeBinding)));
				storeInstruction();
			}
		}

		List<Expression> arguments = node.arguments();
		pushMethodArguments(methodBinding, arguments);

		return false;
	}

	/**
	 * @see ASTVisitor#visit(CompilationUnit)
	 */
	@Override
	public boolean visit(CompilationUnit node) {
		return true;
	}

	/**
	 * @see ASTVisitor#visit(ConditionalExpression)
	 */
	@Override
	public boolean visit(ConditionalExpression node) {
		if (!isActive()) {
			return true;
		}

		push(new NoOp(fCounter));

		return true;
	}

	/**
	 * @see ASTVisitor#visit(ConstructorInvocation)
	 */
	@Override
	public boolean visit(ConstructorInvocation node) {
		if (!isActive()) {
			return false;
		}
		setHasError(true);
		addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_this_constructor_invocation_cannot_be_used_in_an_evaluation_expression_9);
		return false;
	}

	/**
	 * @see ASTVisitor#visit(ContinueStatement)
	 */
	@Override
	public boolean visit(ContinueStatement node) {
		if (!isActive()) {
			return false;
		}
		// create the equivalent jump instruction in the instruction
		// and add an element in the list of pending break and continue
		// instructions
		Jump instruction = new Jump();
		SimpleName labelName = node.getLabel();
		String label = null;
		if (labelName != null) {
			label = labelName.getIdentifier();
		}
		push(instruction);
		fCompleteInstructions.add(new CompleteInstruction(instruction, label,
				false));

		return false;
	}

	/**
	 * @see ASTVisitor#visit(CreationReference)
	 */
	@Override
	public boolean visit(CreationReference node) {
		if (!isActive()) {
			return true;
		}
		setHasError(true);
		addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Reference_expressions_cannot_be_used_in_an_evaluation_expression);
		return false;
	}

	/**
	 * @see ASTVisitor#visit(DoStatement)
	 */
	@Override
	public boolean visit(DoStatement node) {
		if (!isActive()) {
			return false;
		}

		push(new NoOp(fCounter));
		return true;
	}

	/**
	 * @see ASTVisitor#visit(EmptyStatement)
	 */
	@Override
	public boolean visit(EmptyStatement node) {
		if (!isActive()) {
			return false;
		}
		push(new NoOp(fCounter));
		return true;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.
	 * EnhancedForStatement)
	 */
	@Override
	public boolean visit(EnhancedForStatement node) {
		if (!isActive()) {
			return false;
		}

		push(new NoOp(fCounter));

		ITypeBinding typeBinding = resolveTypeBinding(node.getExpression());
		if (typeBinding == null) {
			return false;
		}
		Type paramType = node.getParameter().getType();
		ITypeBinding paramBinding = resolveTypeBinding(paramType);
		if (paramBinding == null) {
			return false;
		}
		String typeSignature = getTypeSignature(paramBinding);
		int paramTypeId = getTypeId(paramType);
		boolean isParamPrimitiveType = paramTypeId != Instruction.T_Object
				&& paramTypeId != Instruction.T_String;
		String paramIdentifier = node.getParameter().getName().getIdentifier();

		if (typeBinding.isArray()) {
			// the expression returns an array
			int idIndex = fUniqueIdIndex++;
			String arrayIdentifier = "#a" + idIndex; //$NON-NLS-1$
			String varIdentifier = "#i" + idIndex; //$NON-NLS-1$
			push(new LocalVariableCreation(arrayIdentifier, typeSignature, 1,
					isParamPrimitiveType, true, fCounter));
			node.getExpression().accept(this);
			storeInstruction();
			push(new LocalVariableCreation(varIdentifier,
					"I", 0, true, true, fCounter)); //$NON-NLS-1$
			push(new PushInt(0));
			storeInstruction();
			storeInstruction();
			push(new LocalVariableCreation(paramIdentifier, typeSignature, 0,
					isParamPrimitiveType, false, fCounter));
			storeInstruction();

			push(new LessOperator(Instruction.T_int, Instruction.T_int,
					fCounter));
			push(new PushLocalVariable(varIdentifier));
			storeInstruction();
			push(new PushArrayLength(fCounter));
			push(new PushLocalVariable(arrayIdentifier));
			storeInstruction();
			storeInstruction();
			storeInstruction();

			// conditional jump will be added here

			push(new NoOp(fCounter));
			push(new AssignmentOperator(paramTypeId, paramTypeId, fCounter));
			push(new PushLocalVariable(paramIdentifier));
			storeInstruction();
			push(new org.eclipse.jdt.internal.debug.eval.ast.instructions.ArrayAccess(
					fCounter));
			push(new PushLocalVariable(arrayIdentifier));
			storeInstruction();
			push(new PostfixPlusPlusOperator(Instruction.T_int, fCounter));
			push(new PushLocalVariable(varIdentifier));
			storeInstruction();
			storeInstruction();
			storeInstruction();
			if (checkAutoBoxing(typeBinding.getElementType(), paramBinding)) {
				storeInstruction();
			}
			storeInstruction();
			addPopInstruction();
			node.getBody().accept(this);
			storeInstruction();

			// jump will be added here

		} else {
			// the expression returns a collection
			String iteratorIdentifier = "#i" + fUniqueIdIndex++; //$NON-NLS-1$
			push(new LocalVariableCreation(iteratorIdentifier,
					"Ljava/util/Iterator;", 0, false, true, fCounter)); //$NON-NLS-1$
			push(new SendMessage(
					"iterator", "()Ljava/util/Iterator;", 0, null, fCounter)); //$NON-NLS-1$//$NON-NLS-2$
			node.getExpression().accept(this);
			storeInstruction();
			storeInstruction();
			push(new LocalVariableCreation(paramIdentifier, typeSignature, 0,
					isParamPrimitiveType, false, fCounter));
			storeInstruction();

			push(new SendMessage("hasNext", "()Z", 0, null, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
			push(new PushLocalVariable(iteratorIdentifier));
			storeInstruction();
			storeInstruction();

			// conditional jump will be added here

			push(new NoOp(fCounter));
			push(new AssignmentOperator(paramTypeId, paramTypeId, fCounter));
			push(new PushLocalVariable(paramIdentifier));
			storeInstruction();
			push(new SendMessage(
					"next", "()Ljava/lang/Object;", 0, null, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
			push(new PushLocalVariable(iteratorIdentifier));
			storeInstruction();
			storeInstruction();
			ITypeBinding[] typeArguments = typeBinding.getTypeArguments();
			if (typeArguments != null && typeArguments.length > 0) {
				if (checkAutoBoxing(typeArguments[0], paramBinding)) {
					storeInstruction();
				}
			}
			storeInstruction();
			addPopInstruction();
			node.getBody().accept(this);
			storeInstruction();

			// jump will be added here

		}

		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.
	 * EnumConstantDeclaration)
	 */
	@Override
	public boolean visit(EnumConstantDeclaration node) {
		if (!isActive()) {
			return true;
		}

		// nothing to do, we shouldn't hit this node
		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.
	 * EnumDeclaration)
	 */
	@Override
	public boolean visit(EnumDeclaration node) {
		if (!isActive()) {
			return true;
		}
		setHasError(true);
		addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_0);
		return false;
	}

	/**
	 * @see ASTVisitor#visit(ExpressionMethodReference)
	 */
	@Override
	public boolean visit(ExpressionMethodReference node) {
		if (!isActive()) {
			return true;
		}
		setHasError(true);
		addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Reference_expressions_cannot_be_used_in_an_evaluation_expression);
		return false;
	}

	/**
	 * @see ASTVisitor#visit(ExpressionStatement)
	 */
	@Override
	public boolean visit(ExpressionStatement node) {
		return true;
	}

	/**
	 * return false, visit expression, don't visit name
	 *
	 * @see ASTVisitor#visit(FieldAccess)
	 */
	@Override
	public boolean visit(FieldAccess node) {
		if (!isActive()) {
			return false;
		}

		SimpleName fieldName = node.getName();
		IVariableBinding fieldBinding = (IVariableBinding) fieldName
				.resolveBinding();
		if (fieldBinding != null) {
			ITypeBinding declaringTypeBinding = fieldBinding
					.getDeclaringClass();
			Expression expression = node.getExpression();
			String fieldId = fieldName.getIdentifier();

			if (Modifier.isStatic(fieldBinding.getModifiers())) {
				push(new PushStaticFieldVariable(fieldId,
						getTypeName(declaringTypeBinding), fCounter));
				expression.accept(this);
				addPopInstruction();
			} else {
				if (declaringTypeBinding == null) { // it is a field without
													// declaring type => it is
													// the special length array
													// field
					push(new PushArrayLength(fCounter));
				} else {
					if (isALocalType(declaringTypeBinding)) {
						setHasError(true);
						addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Qualified_local_type_field_access_cannot_be_used_in_an_evaluation_expression_31);
						return false;
					}
					push(new PushFieldVariable(fieldId,
							getTypeSignature(declaringTypeBinding), fCounter));
				}
				expression.accept(this);
			}
		}
		return false;
	}

	/**
	 * @see ASTVisitor#visit(FieldDeclaration)
	 */
	@Override
	public boolean visit(FieldDeclaration node) {
		return true;
	}

	/**
	 * @see ASTVisitor#visit(ForStatement) return <code>false</code>, don't use
	 *      the standard accept order. order used for visiting children :
	 *      initializers, condition, body, updaters
	 */
	@Override
	public boolean visit(ForStatement node) {
		if (!isActive()) {
			return false;
		}

		push(new NoOp(fCounter));

		push(new NoOp(fCounter));
		for (Iterator<Expression> iter = node.initializers().iterator(); iter.hasNext();) {
			Expression expr = iter.next();
			expr.accept(this);
			addPopInstructionIfNeeded(expr);
		}
		storeInstruction();

		Expression condition = node.getExpression();
		if (condition != null) {
			condition.accept(this);
		}

		node.getBody().accept(this);

		push(new NoOp(fCounter));
		for (Iterator<Expression> iter = node.updaters().iterator(); iter.hasNext();) {
			Expression expr = iter.next();
			expr.accept(this);
			addPopInstructionIfNeeded(expr);
		}
		storeInstruction();

		return false;
	}

	/**
	 * @see ASTVisitor#visit(IfStatement)
	 */
	@Override
	public boolean visit(IfStatement node) {
		if (!isActive()) {
			return false;
		}

		push(new NoOp(fCounter));

		return true;
	}

	/**
	 * @see ASTVisitor#visit(ImportDeclaration)
	 */
	@Override
	public boolean visit(ImportDeclaration node) {
		return false;
	}

	/**
	 * return <code>false</code>, don't use the standard accept order.
	 *
	 * @see ASTVisitor#visit(InfixExpression)
	 */
	@Override
	public boolean visit(InfixExpression node) {
		if (!isActive()) {
			return false;
		}

		String opToken = node.getOperator().toString();
		int opTokenLength = opToken.length();
		char char0 = opToken.charAt(0);
		char char1 = '\0';
		char char2 = '\0';
		if (opTokenLength > 1) {
			char1 = opToken.charAt(1);
			if (opTokenLength > 2) {
				char2 = opToken.charAt(2);
			}
		}

		List<Expression> extendedOperands = node.extendedOperands();

		int operatorNumber = extendedOperands.size() + 1;

		int[][] types = new int[operatorNumber][3];

		Iterator<Expression> iterator = extendedOperands.iterator();

		Expression leftOperand = node.getLeftOperand();
		Expression rightOperand = node.getRightOperand();
		int leftTypeId;
		int rightTypeId;
		boolean unbox = false;
		// for == and != un-box when at least operand is primitive (otherwise
		// compare the objects)
		ITypeBinding leftBinding = resolveTypeBinding(leftOperand);
		if (leftBinding == null) {
			return false;
		}
		ITypeBinding rightBinding = resolveTypeBinding(rightOperand);
		if (rightBinding == null) {
			return false;
		}
		if ((char0 == '=' || char0 == '!') && char1 == '=') {
			unbox = leftBinding.isPrimitive() || rightBinding.isPrimitive();
		} else {
			unbox = true;
		}
		if (unbox) {
			leftTypeId = getUnBoxedTypeId(leftOperand);
			rightTypeId = getUnBoxedTypeId(rightOperand);
		} else {
			leftTypeId = getTypeId(leftOperand);
			rightTypeId = getTypeId(rightOperand);
		}
		int resultTypeId = Instruction.getBinaryPromotionType(leftTypeId,
				rightTypeId);

		types[0][0] = resultTypeId;
		types[0][1] = leftTypeId;
		types[0][2] = rightTypeId;

		for (int i = 1; i < operatorNumber; i++) {
			Expression operand = iterator.next();
			leftTypeId = resultTypeId;
			rightTypeId = getUnBoxedTypeId(operand);
			resultTypeId = Instruction.getBinaryPromotionType(leftTypeId,
					rightTypeId);
			types[i][0] = resultTypeId;
			types[i][1] = leftTypeId;
			types[i][2] = rightTypeId;
		}

		boolean unrecognized = false;

		switch (char0) {
		case '*': // multiply
			for (int i = operatorNumber - 1; i >= 0; i--) {
				push(new MultiplyOperator(types[i][0], types[i][1],
						types[i][2], fCounter));
			}
			break;
		case '/': // divide
			for (int i = operatorNumber - 1; i >= 0; i--) {
				push(new DivideOperator(types[i][0], types[i][1], types[i][2],
						fCounter));
			}
			break;
		case '%': // remainder
			for (int i = operatorNumber - 1; i >= 0; i--) {
				push(new RemainderOperator(types[i][0], types[i][1],
						types[i][2], fCounter));
			}
			break;
		case '+': // plus
			for (int i = operatorNumber - 1; i >= 0; i--) {
				push(new PlusOperator(types[i][0], types[i][1], types[i][2],
						fCounter));
			}
			break;
		case '-': // minus
			for (int i = operatorNumber - 1; i >= 0; i--) {
				push(new MinusOperator(types[i][0], types[i][1], types[i][2],
						fCounter));
			}
			break;
		case '<': // left shift or less or less equal
			switch (char1) {
			case '\0': // less
				for (int i = operatorNumber - 1; i >= 0; i--) {
					push(new LessOperator(types[i][1], types[i][2], fCounter));
				}
				break;
			case '<': // left shift
				for (int i = operatorNumber - 1; i >= 0; i--) {
					push(new LeftShiftOperator(
							Instruction.getUnaryPromotionType(types[i][1]),
							types[i][1], types[i][2], fCounter));
				}
				break;
			case '=': // less equal
				for (int i = operatorNumber - 1; i >= 0; i--) {
					push(new LessEqualOperator(types[i][1], types[i][2],
							fCounter));
				}
				break;
			default:
				unrecognized = true;
				break;
			}
			break;
		case '>': // right shift or unsigned right shift or greater or greater
					// equal
			switch (char1) {
			case '\0': // greater
				for (int i = operatorNumber - 1; i >= 0; i--) {
					push(new GreaterOperator(types[i][1], types[i][2], fCounter));
				}
				break;
			case '>': // right shift or unsigned right shift
				switch (char2) {
				case '\0': // right shift
					for (int i = operatorNumber - 1; i >= 0; i--) {
						push(new RightShiftOperator(
								Instruction.getUnaryPromotionType(types[i][1]),
								types[i][1], types[i][2], fCounter));
					}
					break;
				case '>': // unsigned right shift
					for (int i = operatorNumber - 1; i >= 0; i--) {
						push(new UnsignedRightShiftOperator(
								Instruction.getUnaryPromotionType(types[i][1]),
								types[i][1], types[i][2], fCounter));
					}
					break;
				}
				break;
			case '=': // greater equal
				for (int i = operatorNumber - 1; i >= 0; i--) {
					push(new GreaterEqualOperator(types[i][1], types[i][2],
							fCounter));
				}
				break;
			default:
				unrecognized = true;
				break;
			}
			break;
		case '=': // equal equal
			for (int i = operatorNumber - 1; i >= 0; i--) {
				push(new EqualEqualOperator(types[i][1], types[i][2], true,
						fCounter));
			}
			break;
		case '!': // not equal
			for (int i = operatorNumber - 1; i >= 0; i--) {
				push(new EqualEqualOperator(types[i][1], types[i][2], false,
						fCounter));
			}
			break;
		case '^': // XOr
			for (int i = operatorNumber - 1; i >= 0; i--) {
				push(new XorOperator(types[i][0], types[i][1], types[i][2],
						fCounter));
			}
			break;
		case '|': // or or or or
			switch (char1) {
			case '\0': // or
				for (int i = operatorNumber - 1; i >= 0; i--) {
					push(new OrOperator(types[i][0], types[i][1], types[i][2],
							fCounter));
				}
				break;
			case '|': // or or
				for (int i = operatorNumber - 1; i >= 0; i--) {
					push(new NoOp(fCounter));
				}
				break;
			default:
				unrecognized = true;
				break;
			}
			break;
		case '&': // and or and and
			switch (char1) {
			case '\0': // and
				for (int i = operatorNumber - 1; i >= 0; i--) {
					push(new AndOperator(types[i][0], types[i][1], types[i][2],
							fCounter));
				}
				break;
			case '&': // and and
				for (int i = operatorNumber - 1; i >= 0; i--) {
					push(new NoOp(fCounter));
				}
				break;
			default:
				unrecognized = true;
				break;
			}
			break;
		default:
			unrecognized = true;
			break;
		}
		if (unrecognized) {
			setHasError(true);
			addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Unrecognized_infix_operator____13
					+ opToken);
		}
		if (hasErrors()) {
			return false;
		}

		iterator = extendedOperands.iterator();

		if ((char0 == '&' && char1 == '&') || (char0 == '|' && char1 == '|')) {
			boolean isOrOr = char0 == '|';

			ConditionalJump[] conditionalJumps = new ConditionalJump[operatorNumber];
			int[] conditionalJumpAddresses = new int[operatorNumber];

			boolean storeRequired = unBoxing(leftBinding);
			leftOperand.accept(this);
			if (storeRequired) {
				storeInstruction();
			}

			ConditionalJump conditionalJump = new ConditionalJump(isOrOr);
			conditionalJumps[0] = conditionalJump;
			conditionalJumpAddresses[0] = fCounter;
			push(conditionalJump);
			storeInstruction();

			storeRequired = unBoxing(rightBinding);
			rightOperand.accept(this);
			if (storeRequired) {
				storeInstruction();
			}

			for (int i = 1; i < operatorNumber; i++) {
				conditionalJump = new ConditionalJump(isOrOr);
				conditionalJumps[i] = conditionalJump;
				conditionalJumpAddresses[i] = fCounter;
				push(conditionalJump);
				storeInstruction();
				Expression operand = iterator.next();
				ITypeBinding typeBinding = resolveTypeBinding(operand);
				if (typeBinding == null) {
					return false;
				}
				storeRequired = unBoxing(typeBinding);
				operand.accept(this);
				if (storeRequired) {
					storeInstruction();
				}
			}

			Jump jump = new Jump();
			jump.setOffset(1);
			push(jump);
			storeInstruction();

			for (int i = 0; i < operatorNumber; i++) {
				conditionalJumps[i].setOffset(fCounter
						- conditionalJumpAddresses[i] - 1);
			}

			push(new PushBoolean(isOrOr));
			storeInstruction();

			// store the no-op
			storeInstruction();

		} else { // other operators

			boolean storeRequired = false;
			if (unbox) {
				storeRequired = unBoxing(leftBinding);
			}
			leftOperand.accept(this);
			if (storeRequired) {
				storeInstruction();
			}
			if (unbox) {
				storeRequired = unBoxing(rightBinding);
			}
			rightOperand.accept(this);
			if (storeRequired) {
				storeInstruction();
			}

			storeInstruction();
			for (int i = 1; i < operatorNumber; i++) {
				Expression operand = iterator.next();
				if (unbox) {
					ITypeBinding typeBinding = resolveTypeBinding(operand);
					if (typeBinding == null) {
						return false;
					}
					storeRequired = unBoxing(typeBinding);
				}
				operand.accept(this);
				if (storeRequired) {
					storeInstruction();
				}
				storeInstruction();
			}
		}

		return false;
	}

	/**
	 * @see ASTVisitor#visit(Initializer)
	 */
	@Override
	public boolean visit(Initializer node) {
		return true;
	}

	/**
	 * @see ASTVisitor#visit(InstanceofExpression)
	 */
	@Override
	public boolean visit(InstanceofExpression node) {
		if (!isActive()) {
			return false;
		}
		push(new InstanceOfOperator(fCounter));
		return true;
	}

	/**
	 * @see ASTVisitor#visit(Javadoc)
	 */
	@Override
	public boolean visit(Javadoc node) {
		return false;
	}

	/**
	 * @see ASTVisitor#visit(LabeledStatement) return <code>false</code>, don't
	 *      use the standard accept order.
	 */
	@Override
	public boolean visit(LabeledStatement node) {
		node.getBody().accept(this);
		return false;
	}

	/**
	 * @see ASTVisitor#visit(LambdaExpression)
	 */
	@Override
	public boolean visit(LambdaExpression node) {
		if (!isActive()) {
			return true;
		}
		setHasError(true);
		addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Lambda_expressions_cannot_be_used_in_an_evaluation_expression);
		return false;
	}
	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.
	 * LineComment)
	 */
	@Override
	public boolean visit(LineComment node) {
		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.
	 * MarkerAnnotation)
	 */
	@Override
	public boolean visit(MarkerAnnotation node) {
		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MemberRef
	 * )
	 */
	@Override
	public boolean visit(MemberRef node) {
		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.
	 * MemberValuePair)
	 */
	@Override
	public boolean visit(MemberValuePair node) {
		return false;
	}

	/**
	 * @see ASTVisitor#visit(MethodDeclaration)
	 */
	@Override
	public boolean visit(MethodDeclaration node) {
		int start = node.getStartPosition();
		int end = start + node.getLength();
		if (start < fStartPosition && end > fStartPosition) {
			return true;
		}
		return false;
	}

	/**
	 * return false, don't visit name, visit expression & arguments
	 *
	 * @see ASTVisitor#visit(MethodInvocation)
	 */
	@Override
	public boolean visit(MethodInvocation node) {
		if (!isActive()) {
			return false;
		}

		IMethodBinding methodBinding = (IMethodBinding) node.getName().resolveBinding();
		if (methodBinding == null) {
			// could be the receiver is not visible - for example a private
			// field access from super class
			ASTNode root = node.getRoot();
			if (root instanceof CompilationUnit) {
				CompilationUnit cu = (CompilationUnit) root;
				IProblem[] problems = cu.getProblems();
				for (IProblem problem : problems) {
					setHasError(true);
					addErrorMessage(problem.getMessage());
				}
			}
		}

		if (hasErrors()) {
			return false;
		}

		if (containsALocalType(methodBinding)) {
			setHasError(true);
			addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Method_which_contains_a_local_type_as_parameter_cannot_be_used_in_an_evaluation_expression_32);
			return false;
		}

		int paramCount = methodBinding.getParameterTypes().length;
		String selector = methodBinding.getName();

		String signature = getMethodSignature(methodBinding, null).replace('.',
				'/');

		boolean isStatic = Flags.isStatic(methodBinding.getModifiers());
		Expression expression = node.getExpression();

		if (isStatic) {
			String typeName = getTypeName(methodBinding.getDeclaringClass());
			push(new SendStaticMessage(typeName, selector, signature,
					paramCount, fCounter));
			if (expression != null) {
				node.getExpression().accept(this);
				addPopInstruction();
			}
		} else {
			push(new SendMessage(selector, signature, paramCount, null,
					fCounter));
			if (expression == null) {
				push(new PushThis(getEnclosingLevel(node,
						methodBinding.getDeclaringClass())));
				storeInstruction();
			} else {
				node.getExpression().accept(this);
			}
		}

		List<Expression> arguments = node.arguments();
		pushMethodArguments(methodBinding, arguments);

		return false;
	}

	/**
	 * Pushes method arguments onto the stack for a method or constructor
	 * invocation taking variable arguments and auto-boxing into consideration.
	 *
	 * @param methodBinding
	 *            method or constructor being called
	 * @param arguments
	 *            argument list
	 */
	private void pushMethodArguments(IMethodBinding methodBinding, List<Expression> arguments) {
		int argCount = arguments.size();
		ITypeBinding[] parameterTypes = methodBinding.getParameterTypes();
		int paramCount = parameterTypes.length;
		ITypeBinding lastArgBinding = null;
		if (methodBinding.isVarargs()) {
			Expression lastArg = arguments.get(argCount - 1);
			lastArgBinding = resolveTypeBinding(lastArg);
			if (lastArgBinding == null) {
				return;
			}
		}
		if (methodBinding.isVarargs() &&
				!(paramCount == argCount &&
				parameterTypes[paramCount - 1].getDimensions() == lastArgBinding.getDimensions())) {
			// if this method is a varargs, and if the method is invoked using
			// the varargs syntax
			// (multiple arguments) and not an array
			Iterator<Expression> iterator = arguments.iterator();
			// process the first arguments (no part of the variable argument)
			for (int i = 0; i < paramCount - 1; i++) {
				Expression argument = iterator.next();
				boolean storeRequired = checkAutoBoxing(
						argument.resolveTypeBinding(), parameterTypes[i]);
				argument.accept(this);
				if (storeRequired) {
					storeInstruction();
				}
			}
			// create a array of the remainder arguments
			ITypeBinding varargsParameterType = parameterTypes[paramCount - 1];
			ITypeBinding varargsElementType = varargsParameterType
					.getElementType();
			push(new ArrayInitializerInstruction(
					getTypeSignature(varargsElementType), argCount - paramCount
							+ 1, varargsParameterType.getDimensions(), fCounter));
			while (iterator.hasNext()) {
				Expression argument = iterator.next();
				boolean storeRequired = checkAutoBoxing(
						argument.resolveTypeBinding(), varargsElementType);
				argument.accept(this);
				if (storeRequired) {
					storeInstruction();
				}
			}
			storeInstruction();
		} else {
			Iterator<Expression> iterator = arguments.iterator();
			int i = 0;
			while (iterator.hasNext()) {
				Expression argument = iterator.next();
				boolean storeRequired = checkAutoBoxing(
						argument.resolveTypeBinding(), parameterTypes[i++]);
				argument.accept(this);
				if (storeRequired) {
					storeInstruction();
				}
			}
		}
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MethodRef
	 * )
	 */
	@Override
	public boolean visit(MethodRef node) {
		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.
	 * MethodRefParameter)
	 */
	@Override
	public boolean visit(MethodRefParameter node) {
		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.Modifier
	 * )
	 */
	@Override
	public boolean visit(Modifier node) {
		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.
	 * NormalAnnotation)
	 */
	@Override
	public boolean visit(NormalAnnotation node) {
		return false;
	}

	/**
	 * @see ASTVisitor#visit(NullLiteral)
	 */
	@Override
	public boolean visit(NullLiteral node) {
		if (!isActive()) {
			return false;
		}

		push(new PushNull());

		return true;
	}

	/**
	 * @see ASTVisitor#visit(NumberLiteral)
	 */
	@Override
	public boolean visit(NumberLiteral node) {
		if (!isActive()) {
			return false;
		}

		int literalType = getTypeId(node);
		String token = node.getToken();
		int tokenLastCharOffset = token.length() - 1;
		char lastChar = token.charAt(tokenLastCharOffset);
		String subToken = token.substring(0, tokenLastCharOffset);

		switch (literalType) {
		case Instruction.T_byte:
			push(new PushInt(parseByteValue(token)));
			break;
		case Instruction.T_short:
			push(new PushInt(parseShortValue(token)));
			break;
		case Instruction.T_int:
			push(new PushInt(parseIntValue(token)));
			break;
		case Instruction.T_long:
			push(new PushLong(parseLongValue(subToken)));
			break;
		case Instruction.T_float:
			push(new PushFloat(
					Float.parseFloat(removePrefixZerosAndUnderscores(subToken,
							false))));
			break;
		case Instruction.T_double:
			if (lastChar == 'D' || lastChar == 'd') {
				push(new PushDouble(
						Double.parseDouble(removePrefixZerosAndUnderscores(
								subToken, false))));
			} else {
				push(new PushDouble(
						Double.parseDouble(removePrefixZerosAndUnderscores(
								token, false))));
			}
			break;
		}

		return true;
	}

	/**
	 * Removes all preamble typing and underscores and returns the base integer
	 * value
	 *
	 * @param token
	 *            the token to parse
	 * @return the int value of the token
	 */
	public static int parseIntValue(String token) {
		token = removePrefixZerosAndUnderscores(token, false);
		switch (getBase(token)) {
		case 8:
			return Integer.valueOf(token.substring(1), 8).intValue();
		case 16:
			return Integer.valueOf(token.substring(2), 16).intValue();
		case 2:
			return Integer.valueOf(token.substring(2), 2).intValue();
		default:
			return Integer.valueOf(token, 10).intValue();
		}
	}

	/**
	 * Removes all preamble typing and underscores and returns the base short
	 * value
	 *
	 * @param token
	 *            the token to parse
	 * @return the short value of the token
	 */
	public static short parseShortValue(String token) {
		token = removePrefixZerosAndUnderscores(token, false);
		switch (getBase(token)) {
		case 8:
			return Short.valueOf(token.substring(1), 8).shortValue();
		case 16:
			return Short.valueOf(token.substring(2), 16).shortValue();
		case 2:
			return Short.valueOf(token.substring(2), 2).shortValue();
		default:
			return Short.valueOf(token, 10).shortValue();
		}
	}

	/**
	 * Removes all preamble typing and underscores and returns the base byte
	 * value
	 *
	 * @param token
	 *            the token to parse
	 * @return the byte value of the token
	 */
	public static byte parseByteValue(String token) {
		token = removePrefixZerosAndUnderscores(token, false);
		switch (getBase(token)) {
		case 8:
			return Byte.valueOf(token.substring(1), 8).byteValue();
		case 16:
			return Byte.valueOf(token.substring(2), 16).byteValue();
		case 2:
			return Byte.valueOf(token.substring(2), 2).byteValue();
		default:
			return Byte.valueOf(token, 10).byteValue();
		}
	}

	/**
	 * Removes all preamble typing and underscores and returns the base long
	 * value
	 *
	 * @param token
	 *            the token to parse
	 * @return the long value of the token
	 */
	public static long parseLongValue(String token) {
		token = removePrefixZerosAndUnderscores(token, true);
		switch (getBase(token)) {
		case 8:
			return Long.valueOf(token.substring(1), 8).longValue();
		case 16:
			return Long.valueOf(token.substring(2), 16).longValue();
		case 2:
			return Long.valueOf(token.substring(2), 2).longValue();
		default:
			return Long.valueOf(token, 10).longValue();
		}
	}

	/**
	 * Returns the numeric base for the given token according to the Java
	 * specification. Returns 8, 10, or 16.
	 *
	 * @param token
	 *            the token to get the base from
	 * @return the numeric base for the given token
	 */
	public static int getBase(String token) {
		if (token.charAt(0) == '0' && (token.length() > 1)) {
			switch (token.charAt(1)) {
			case 'x':
			case 'X':
				// "0x" prefix: Hexadecimal
				return 16;
			case 'b':
			case 'B':
				// "0b" prefix: binary
				return 2;
			default:
				// "0" prefix: Octal
				return 8;
			}
		}
		return 10; // No prefix: Decimal
	}

	/**
	 * @see ASTVisitor#visit(PackageDeclaration)
	 */
	@Override
	public boolean visit(PackageDeclaration node) {
		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.
	 * ParameterizedType)
	 */
	@Override
	public boolean visit(ParameterizedType node) {
		if (!isActive()) {
			return false;
		}
		ITypeBinding typeBinding = resolveTypeBinding(node);
		if (typeBinding != null) {
			push(new PushType(getTypeName(typeBinding)));
		}
		return false;
	}

	/**
	 * @see ASTVisitor#visit(ParenthesizedExpression)
	 */
	@Override
	public boolean visit(ParenthesizedExpression node) {
		if (!isActive()) {
			return false;
		}
		return true;
	}

	/**
	 * @see ASTVisitor#visit(PostfixExpression)
	 */
	@Override
	public boolean visit(PostfixExpression node) {
		if (!isActive()) {
			return false;
		}

		Expression operand = node.getOperand();
		int expressionTypeId = getTypeId(operand);

		String opToken = node.getOperator().toString();
		char char0 = opToken.charAt(0);

		if (expressionTypeId == Instruction.T_Object) {

			int expressionUnBoxedTypeId = getUnBoxedTypeId(operand);

			AssignmentOperator assignmentInstruction = new AssignmentOperator(
					Instruction.T_Object, Instruction.T_Object, fCounter);
			push(assignmentInstruction);
			operand.accept(this);
			switch (char0) {
			case '+': // plus plus
				push(new PlusOperator(expressionUnBoxedTypeId,
						expressionUnBoxedTypeId, expressionUnBoxedTypeId,
						fCounter));
				break;
			case '-': // minus minus
				push(new MinusOperator(expressionUnBoxedTypeId,
						expressionUnBoxedTypeId, expressionUnBoxedTypeId,
						fCounter));
				break;
			default:
				setHasError(true);
				addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_unrecognized_postfix_operator____15
						+ opToken);
				return false;
			}
			push(new Value(fCounter));
			push(new Dup());
			storeInstruction(); // dupe
			storeInstruction(); // value
			push(new DupX1());
			storeInstruction(); // dup_x1
			ITypeBinding typeBinding = resolveTypeBinding(operand);
			if (typeBinding == null) {
				return false;
			}
			unBoxing(typeBinding);
			storeInstruction(); // un-boxing
			push(new PushInt(1));
			storeInstruction(); // push 1
			storeInstruction(); // operator
			boxing(typeBinding, null);
			storeInstruction(); // boxing
			storeInstruction(); // assignment
			push(new Pop(assignmentInstruction.getSize() + 1));

			return false;
		}

		switch (char0) {
		case '+': // plus plus
			push(new PostfixPlusPlusOperator(expressionTypeId, fCounter));
			break;
		case '-': // minus minus
			push(new PostfixMinusMinusOperator(expressionTypeId, fCounter));
			break;
		default:
			setHasError(true);
			addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_unrecognized_postfix_operator____15
					+ opToken);
			return false;
		}

		return true;
	}

	/**
	 * @see ASTVisitor#visit(PrefixExpression)
	 */
	@Override
	public boolean visit(PrefixExpression node) {
		if (!isActive()) {
			return false;
		}

		Expression operand = node.getOperand();
		int expressionTypeId = getTypeId(operand);

		String opToken = node.getOperator().toString();
		int opTokenLength = opToken.length();
		char char0 = opToken.charAt(0);
		char char1 = '\0';
		if (opTokenLength > 1) {
			char1 = opToken.charAt(1);
		}

		boolean unrecognized = false;

		if (expressionTypeId == Instruction.T_Object) {

			int expressionUnBoxedTypeId = getUnBoxedTypeId(operand);

			ITypeBinding typeBinding = resolveTypeBinding(operand);
			if (typeBinding == null) {
				return false;
			}
			if (char1 == '\0') {
				switch (char0) {
				case '+': // unary plus
					push(new UnaryPlusOperator(expressionUnBoxedTypeId,
							fCounter));
					break;
				case '-': // unary minus
					push(new UnaryMinusOperator(expressionUnBoxedTypeId,
							fCounter));
					break;
				case '~': // twiddle
					push(new TwiddleOperator(expressionUnBoxedTypeId, fCounter));
					break;
				case '!': // not
					push(new NotOperator(expressionUnBoxedTypeId, fCounter));
					break;
				default:
					setHasError(true);
					addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_unrecognized_prefix_operator____16
							+ opToken);
					return false;
				}

				unBoxing(typeBinding);
				operand.accept(this);
				storeInstruction(); // un-boxing

			} else {
				// plus plus and minus minus operators

				push(new AssignmentOperator(Instruction.T_Object,
						Instruction.T_Object, fCounter));

				operand.accept(this);

				boxing(typeBinding, null);

				switch (char1) {
				case '+':
					push(new PlusOperator(expressionUnBoxedTypeId,
							expressionUnBoxedTypeId, expressionUnBoxedTypeId,
							fCounter));
					break;
				case '-':
					push(new MinusOperator(expressionUnBoxedTypeId,
							expressionUnBoxedTypeId, expressionUnBoxedTypeId,
							fCounter));
					break;
				default:
					setHasError(true);
					addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_unrecognized_prefix_operator____16
							+ opToken);
					return false;
				}

				unBoxing(typeBinding);
				push(new Dup());
				storeInstruction(); // dupe
				storeInstruction(); // un-boxing
				push(new PushInt(1));
				storeInstruction(); // push 1

				storeInstruction(); // operator
				storeInstruction(); // boxing

			}

			return false;
		}

		switch (char0) {
		case '+': // plus plus or unary plus
			switch (char1) {
			case '\0': // unary plus
				push(new UnaryPlusOperator(expressionTypeId, fCounter));
				break;
			case '+': // plus plus
				push(new PrefixPlusPlusOperator(expressionTypeId, fCounter));
				break;
			default:
				unrecognized = true;
				break;
			}
			break;
		case '-': // minus minus or unary minus
			switch (char1) {
			case '\0': // unary minus
				push(new UnaryMinusOperator(expressionTypeId, fCounter));
				break;
			case '-': // minus minus
				push(new PrefixMinusMinusOperator(expressionTypeId, fCounter));
				break;
			default:
				unrecognized = true;
				break;
			}
			break;
		case '~': // twiddle
			push(new TwiddleOperator(expressionTypeId, fCounter));
			break;
		case '!': // not
			push(new NotOperator(expressionTypeId, fCounter));
			break;
		default:
			unrecognized = true;
			break;
		}

		if (unrecognized) {
			setHasError(true);
			addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_unrecognized_prefix_operator____16
					+ opToken);
			return false;
		}

		return true;
	}

	/**
	 * @see ASTVisitor#visit(PrimitiveType)
	 */
	@Override
	public boolean visit(PrimitiveType node) {
		if (!isActive()) {
			return false;
		}
		ITypeBinding typeBinding = resolveTypeBinding(node);
		if (typeBinding != null) {
			push(new PushPrimitiveType(getTypeName(typeBinding)));
		}
		return false;
	}

	/**
	 * @see ASTVisitor#visit(QualifiedName)
	 */
	@Override
	public boolean visit(QualifiedName node) {
		if (!isActive()) {
			return false;
		}

		if (hasErrors()) {
			return true;
		}

		IBinding binding = resolveBinding(node);
		if (binding == null) {
			return false;
		}
		switch (binding.getKind()) {
		case IBinding.TYPE:
			node.getName().accept(this);
			break;
		case IBinding.VARIABLE:
			SimpleName fieldName = node.getName();
			IVariableBinding fieldBinding = (IVariableBinding) resolveBinding(fieldName);
			if (fieldBinding == null) {
				return false;
			}
			ITypeBinding declaringTypeBinding = fieldBinding
					.getDeclaringClass();
			String fieldId = fieldName.getIdentifier();

			if (Modifier.isStatic(fieldBinding.getModifiers())) {
				push(new PushStaticFieldVariable(fieldId,
						getTypeName(declaringTypeBinding), fCounter));
			} else {
				if (declaringTypeBinding == null) {
					push(new PushArrayLength(fCounter));
				} else {
					push(new PushFieldVariable(fieldId,
							getTypeSignature(declaringTypeBinding), fCounter));
				}
				node.getQualifier().accept(this);
			}
			storeInstruction();
			break;
		}

		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.
	 * QualifiedType)
	 */
	@Override
	public boolean visit(QualifiedType node) {
		if (!isActive()) {
			return false;
		}
		ITypeBinding typeBinding = resolveTypeBinding(node);
		if (typeBinding != null) {
			push(new PushType(getTypeName(typeBinding)));
		}
		return false;
	}

	/**
	 * @see ASTVisitor#visit(ReturnStatement)
	 */
	@Override
	public boolean visit(ReturnStatement node) {
		if (!isActive()) {
			return false;
		}
		push(new ReturnInstruction(fCounter));
		return true;
	}

	/**
	 * @see ASTVisitor#visit(SimpleName)
	 */
	@Override
	public boolean visit(SimpleName node) {
		if (!isActive()) {
			return false;
		}

		if (hasErrors()) {
			return true;
		}

		IBinding binding = resolveBinding(node);
		if (binding == null) {
			return true;
		}
		String variableId = node.getIdentifier();

		switch (binding.getKind()) {
		case IBinding.TYPE:
			ITypeBinding typeBinding = (ITypeBinding) binding;
			push(new PushType(getTypeName(typeBinding)));
			break;
		case IBinding.VARIABLE:
			IVariableBinding variableBinding = (IVariableBinding) binding;
			ITypeBinding declaringTypeBinding = variableBinding
					.getDeclaringClass();
			if (variableBinding.isField()) {
				if (Modifier.isStatic(variableBinding.getModifiers())) {
					push(new PushStaticFieldVariable(variableId,
							getTypeName(declaringTypeBinding), fCounter));
				} else {
					push(new PushFieldVariable(variableId,
							getTypeSignature(declaringTypeBinding), fCounter));
					push(new PushThis(getEnclosingLevel(node,
							declaringTypeBinding)));
					storeInstruction();
				}
			} else {
				push(new PushLocalVariable(variableId));
			}
			break;
		}
		return true;
	}

	/**
	 * return false, don't visit child
	 *
	 * @see ASTVisitor#visit(SimpleType)
	 */
	@Override
	public boolean visit(SimpleType node) {
		if (!isActive()) {
			return false;
		}

		ITypeBinding typeBinding = resolveTypeBinding(node);
		if (typeBinding != null) {
			push(new PushType(getTypeName(typeBinding)));
		}
		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.
	 * SingleMemberAnnotation)
	 */
	@Override
	public boolean visit(SingleMemberAnnotation node) {
		return false;
	}

	/**
	 * @see ASTVisitor#visit(SingleVariableDeclaration) return
	 *      <code>false</code>, don't use the standard accept order.
	 */
	@Override
	public boolean visit(SingleVariableDeclaration node) {
		if (!isActive()) {
			return false;
		}
		ITypeBinding typeBinding = resolveTypeBinding(node.getType());
		if (typeBinding != null) {
			int typeDimension = typeBinding.getDimensions();
			if (typeDimension != 0) {
				typeBinding = typeBinding.getElementType();
			}
			Expression initializer = node.getInitializer();
			push(new LocalVariableCreation(node.getName().getIdentifier(),
					getTypeSignature(typeBinding), typeDimension,
					typeBinding.isPrimitive(), initializer != null, fCounter));
			if (initializer != null) {
				initializer.accept(this);
			}
		}
		return false;
	}

	/**
	 * @see ASTVisitor#visit(StringLiteral)
	 */
	@Override
	public boolean visit(StringLiteral node) {
		if (!isActive()) {
			return false;
		}

		push(new PushString(node.getLiteralValue()));

		return true;
	}

	/**
	 * @see ASTVisitor#visit(SuperConstructorInvocation)
	 */
	@Override
	public boolean visit(SuperConstructorInvocation node) {
		if (!isActive()) {
			return false;
		}
		setHasError(true);
		addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_super_constructor_invocation_cannot_be_used_in_an_evaluation_expression_19);
		return false;
	}

	/**
	 * @see ASTVisitor#visit(SuperFieldAccess)
	 */
	@Override
	public boolean visit(SuperFieldAccess node) {
		if (!isActive()) {
			return false;
		}

		SimpleName fieldName = node.getName();
		IVariableBinding fieldBinding = (IVariableBinding) resolveBinding(fieldName);
		if (fieldBinding == null) {
			return false;
		}
		ITypeBinding declaringTypeBinding = fieldBinding.getDeclaringClass();
		String fieldId = fieldName.getIdentifier();

		if (Modifier.isStatic(fieldBinding.getModifiers())) {
			push(new PushStaticFieldVariable(fieldId,
					getTypeName(declaringTypeBinding), fCounter));
		} else {
			Name qualifier = node.getQualifier();
			int superLevel = 1;
			int enclosingLevel = 0;
			if (qualifier != null) {
				ITypeBinding typeBinding = resolveTypeBinding(qualifier);
				if (typeBinding == null) {
					return false;
				}
				superLevel = getSuperLevel(typeBinding, declaringTypeBinding);
				ITypeBinding binding = (ITypeBinding) resolveBinding(qualifier);
				if (binding == null) {
					return false;
				}
				enclosingLevel = getEnclosingLevel(node, binding);
			}
			push(new PushFieldVariable(fieldId, superLevel, fCounter));
			push(new PushThis(enclosingLevel));
			storeInstruction();
		}

		return false;
	}

	/**
	 * return false, don't visit name, visit arguments
	 *
	 * @see ASTVisitor#visit(SuperMethodInvocation)
	 */
	@Override
	public boolean visit(SuperMethodInvocation node) {
		if (!isActive()) {
			return false;
		}

		IMethodBinding methodBinding = (IMethodBinding) resolveBinding(node
				.getName());
		if (methodBinding == null) {
			return false;
		}

		if (containsALocalType(methodBinding)) {
			setHasError(true);
			addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Method_which_contains_a_local_type_as_parameter_cannot_be_used_in_an_evaluation_expression_32);
			return false;
		}

		ITypeBinding[] parameterTypes = methodBinding.getParameterTypes();
		int paramCount = parameterTypes.length;
		String selector = methodBinding.getName();
		String signature = getMethodSignature(methodBinding, null);

		Name qualifier = node.getQualifier();
		if (Modifier.isStatic(methodBinding.getModifiers())) {
			push(new SendStaticMessage(
					getTypeName(methodBinding.getDeclaringClass()), selector,
					signature, paramCount, fCounter));
		} else {
			push(new SendMessage(selector, signature, paramCount,
					getTypeSignature(methodBinding.getDeclaringClass()),
					fCounter));
			int enclosingLevel = 0;
			if (qualifier != null) {
				ITypeBinding typeBinding = (ITypeBinding) resolveBinding(qualifier);
				if (typeBinding == null) {
					return false;
				}
				enclosingLevel = getEnclosingLevel(node, typeBinding);
			}
			push(new PushThis(enclosingLevel));
			storeInstruction();
		}

		List<Expression> arguments = node.arguments();
		int argCount = arguments.size();
		ITypeBinding lastArgBinding = null;
		if (methodBinding.isVarargs()) {
			lastArgBinding = resolveTypeBinding(arguments.get(argCount - 1));
			if (lastArgBinding == null) {
				return false;
			}
		}
		if (methodBinding.isVarargs() &&
				!(paramCount == argCount &&
				parameterTypes[paramCount - 1].getDimensions() == lastArgBinding.getDimensions())) {
			// if this method is a varargs, and if the method is invoked using
			// the varargs syntax
			// (multiple arguments) and not an array
			Iterator<Expression> iterator = arguments.iterator();
			// process the first arguments (no part of the variable argument)
			for (int i = 0; i < paramCount - 1; i++) {
				Expression argument = iterator.next();
				boolean storeRequired = checkAutoBoxing(
						argument.resolveTypeBinding(), parameterTypes[i]);
				argument.accept(this);
				if (storeRequired) {
					storeInstruction();
				}
			}
			// create a array of the remainder arguments
			ITypeBinding varargsParameterType = parameterTypes[paramCount - 1];
			ITypeBinding varargsElementType = varargsParameterType
					.getElementType();
			push(new ArrayInitializerInstruction(
					getTypeSignature(varargsElementType), argCount - paramCount
							+ 1, varargsParameterType.getDimensions(), fCounter));
			while (iterator.hasNext()) {
				Expression argument = iterator.next();
				boolean storeRequired = checkAutoBoxing(
						argument.resolveTypeBinding(), varargsElementType);
				argument.accept(this);
				if (storeRequired) {
					storeInstruction();
				}
			}
			storeInstruction();
		} else {
			Iterator<Expression> iterator = arguments.iterator();
			int i = 0;
			while (iterator.hasNext()) {
				Expression argument = iterator.next();
				boolean storeRequired = checkAutoBoxing(
						argument.resolveTypeBinding(), parameterTypes[i++]);
				argument.accept(this);
				if (storeRequired) {
					storeInstruction();
				}
			}
		}

		return false;
	}

	/**
	 * @see ASTVisitor#visit(SuperMethodReference)
	 */
	@Override
	public boolean visit(SuperMethodReference node) {
		if (!isActive()) {
			return true;
		}
		setHasError(true);
		addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Reference_expressions_cannot_be_used_in_an_evaluation_expression);
		return false;
	}

	/**
	 * @see ASTVisitor#visit(SwitchCase)
	 */
	@Override
	public boolean visit(SwitchCase node) {
		// never called
		return false;
	}

	class slot {
		ArrayList<ConditionalJump> jumps = new ArrayList<>();
		ArrayList<Statement> stmts = null;
	}

	/**
	 * @see ASTVisitor#visit(SwitchStatement)
	 */
	@Override
	public boolean visit(SwitchStatement node) {
		if (!isActive()) {
			return false;
		}
		push(new NoOp(fCounter));
		int switchStart = fCounter;
		node.getExpression().accept(this);

		ArrayList<Statement> statementsDefault = null;
		Jump jumpDefault = null;
		ArrayList<slot> jumpsStatements = new ArrayList<>();
		slot currentslot = new slot();
		jumpsStatements.add(currentslot);

		for (Iterator<Statement> iter = node.statements().iterator(); iter.hasNext();) {
			Statement statement = iter.next();
			if (statement instanceof SwitchCase) {
				SwitchCase switchCase = (SwitchCase) statement;
				if (switchCase.isDefault()) {
					jumpDefault = new Jump();
					push(jumpDefault);
					storeInstruction(); // jump
					statementsDefault = new ArrayList<>();
				} else {
					if (switchCase.getExpression() instanceof StringLiteral) {
						push(new SendMessage(
								"equals", "(Ljava/lang/Object;)Z", 1, null, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
					} else {
						push(new EqualEqualOperator(Instruction.T_int,
								Instruction.T_int, true, fCounter));
					}
					push(new Dup());
					storeInstruction(); // dupe
					switchCase.getExpression().accept(this);
					storeInstruction(); // equal-equal
					ConditionalJump condJump = new ConditionalJump(true);
					push(condJump);
					storeInstruction(); // conditional jump
					if (currentslot.stmts != null) {
						currentslot = new slot();
						jumpsStatements.add(currentslot);
					}
					currentslot.jumps.add(condJump);
				}
			} else {
				if (statementsDefault != null) {
					statementsDefault.add(statement);
				} else {
					if (currentslot.stmts == null) {
						currentslot.stmts = new ArrayList<>();
					}
					currentslot.stmts.add(statement);
				}
			}
		}

		Jump jumpEnd = null;
		if (jumpDefault == null) {
			push(new Pop(0));
			storeInstruction(); // pop
			jumpEnd = new Jump();
			push(jumpEnd);
			storeInstruction(); // jump
		}

		for (Iterator<slot> iter = jumpsStatements.iterator(); iter.hasNext();) {
			currentslot = iter.next();
			for (Iterator<ConditionalJump> iterator = currentslot.jumps.iterator(); iterator.hasNext();) {
				ConditionalJump condJump = iterator.next();
				condJump.setOffset((fCounter - fInstructions.indexOf(condJump)) - 1);
			}
			if (currentslot.stmts != null) {
				push(new Pop(0));
				storeInstruction(); // pop
				for (Iterator<Statement> iterator = currentslot.stmts.iterator(); iterator.hasNext();) {
					iterator.next().accept(this);
				}
			}
		}

		// default case
		if (jumpDefault != null) {
			jumpDefault.setOffset((fCounter - fInstructions.indexOf(jumpDefault)) - 1);
			push(new Pop(0));
			storeInstruction(); // pop
			for (Iterator<Statement> iterator = statementsDefault.iterator(); iterator.hasNext();) {
				iterator.next().accept(this);
			}
		} else if(jumpEnd != null){
			jumpEnd.setOffset((fCounter - fInstructions.indexOf(jumpEnd)) - 1);
		}

		// for each pending break or continue instruction which are related to
		// this loop, set the offset of the corresponding jump.
		String label = getLabel(node);
		for (Iterator<CompleteInstruction> iter = fCompleteInstructions.iterator(); iter.hasNext();) {
			CompleteInstruction instruction = iter.next();
			Jump jumpInstruction = instruction.fInstruction;
			int instructionAddress = fInstructions.indexOf(jumpInstruction);
			if (instructionAddress > switchStart && (instruction.fLabel == null || instruction.fLabel.equals(label))) {
				iter.remove();
				if (instruction.fIsBreak) {
					// jump to the instruction after the last instruction of the
					// switch
					jumpInstruction.setOffset((fCounter - instructionAddress) - 1);
				}
			}
		}
		return false;
	}

	/**
	 * @see ASTVisitor#visit(SynchronizedStatement)
	 */
	@Override
	public boolean visit(SynchronizedStatement node) {
		if (!isActive()) {
			return false;
		}
		return true;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TagElement
	 * )
	 */
	@Override
	public boolean visit(TagElement node) {
		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.
	 * TextElement)
	 */
	@Override
	public boolean visit(TextElement node) {
		return false;
	}

	/**
	 * @see ASTVisitor#visit(ThisExpression)
	 */
	@Override
	public boolean visit(ThisExpression node) {
		if (!isActive()) {
			return false;
		}

		Name qualifier = node.getQualifier();
		int enclosingLevel = 0;
		if (qualifier != null) {
			ITypeBinding binding = (ITypeBinding) resolveBinding(qualifier);
			if (binding == null) {
				return false;
			}
			enclosingLevel = getEnclosingLevel(node, binding);
		}
		push(new PushThis(enclosingLevel));

		return false;
	}

	/**
	 * @see ASTVisitor#visit(ThrowStatement)
	 */
	@Override
	public boolean visit(ThrowStatement node) {
		if (!isActive()) {
			return false;
		}
		push(new ThrowInstruction(fCounter));
		return true;
	}

	/**
	 * @see ASTVisitor#visit(TryStatement)
	 */
	@Override
	public boolean visit(TryStatement node) {
		if (!isActive()) {
			return false;
		}
		setHasError(true);
		addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Try_statement_cannot_be_used_in_an_evaluation_expression_23);
		return false;
	}

	/**
	 * @see ASTVisitor#visit(TypeDeclaration)
	 */
	@Override
	public boolean visit(TypeDeclaration node) {
		if (!isActive()) {
			return true;
		}
		setHasError(true);
		addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Type_declaration_cannot_be_used_in_an_evaluation_expression_24);
		return false;
	}

	/**
	 * @see ASTVisitor#visit(TypeDeclarationStatement)
	 */
	@Override
	public boolean visit(TypeDeclarationStatement node) {
		if (!isActive()) {
			return true;
		}
		setHasError(true);
		addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Type_declaration_statement_cannot_be_used_in_an_evaluation_expression_25);
		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.
	 * TypeParameter)
	 */
	@Override
	public boolean visit(TypeParameter node) {
		return false;
	}

	/**
	 * @see ASTVisitor#visit(TypeLiteral)
	 */
	@Override
	public boolean visit(TypeLiteral node) {
		if (!isActive()) {
			return false;
		}

		push(new PushClassLiteralValue(fCounter));

		return true;
	}

	/**
	 * @see ASTVisitor#visit(TypeMethodReference)
	 */
	@Override
	public boolean visit(TypeMethodReference node) {
		if (!isActive()) {
			return true;
		}
		setHasError(true);
		addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Reference_expressions_cannot_be_used_in_an_evaluation_expression);
		return false;
	}

	/**
	 * @see ASTVisitor#visit(VariableDeclarationExpression)
	 */
	@Override
	public boolean visit(VariableDeclarationExpression node) {
		/*
		 * if it is in the code to execute, return <code>false</code>, we don't
		 * use the standard accept order. Otherwise, return true. We want to
		 * search the code to execute in variable declarations (in case of inner
		 * classes).
		 */
		if (!isActive()) {
			return true;
		}
		for (Iterator<VariableDeclarationFragment> iter = node.fragments().iterator(); iter.hasNext();) {
			iter.next().accept(this);
		}
		return false;
	}

	/**
	 * @see ASTVisitor#visit(VariableDeclarationFragment)
	 */
	@Override
	public boolean visit(VariableDeclarationFragment node) {
		/*
		 * if it is in the code to execute, return <code>false</code>, we don't
		 * use the standard accept order. Otherwise, return true. We want to
		 * search the code to execute in variable declarations (in case of inner
		 * classes).
		 */
		if (!isActive()) {
			return true;
		}
		// get the type of the variable
		ITypeBinding varTypeBinding;
		ASTNode parent = node.getParent();
		switch (parent.getNodeType()) {
		case ASTNode.VARIABLE_DECLARATION_EXPRESSION:
			varTypeBinding = resolveTypeBinding(((VariableDeclarationExpression) parent)
					.getType());
			break;
		case ASTNode.VARIABLE_DECLARATION_STATEMENT:
			varTypeBinding = resolveTypeBinding(((VariableDeclarationStatement) parent)
					.getType());
			break;
		default:
			setHasError(true);
			addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Error_in_type_declaration_statement);
			return false;
		}
		if (varTypeBinding == null) {
			return false;
		}
		int typeDimension = varTypeBinding.getDimensions();
		ITypeBinding elementBinding = varTypeBinding;
		if (typeDimension != 0) {
			elementBinding = elementBinding.getElementType();
		}

		Expression initializer = node.getInitializer();
		push(new LocalVariableCreation(node.getName().getIdentifier(),
				getTypeSignature(elementBinding), typeDimension,
				elementBinding.isPrimitive(), initializer != null, fCounter));
		if (initializer != null) {
			initializer.accept(this);
			ITypeBinding expBindnig = initializer.resolveTypeBinding();
			if (expBindnig != null) {
				if (checkAutoBoxing(expBindnig, varTypeBinding)) {
					storeInstruction();
				}
			}
		}

		return false;
	}

	/**
	 * @see ASTVisitor#visit(VariableDeclarationStatement)
	 */
	@Override
	public boolean visit(VariableDeclarationStatement node) {
		/*
		 * if it is in the code to execute, return <code>false</code>, we don't
		 * use the standard accept order. Otherwise, return true. We want to
		 * search the code to execute in variable declarations (in case of inner
		 * classes).
		 */
		if (!isActive()) {
			return true;
		}
		for (Iterator<VariableDeclarationFragment> iter = node.fragments().iterator(); iter.hasNext();) {
			iter.next().accept(this);
		}
		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.
	 * WildcardType)
	 */
	@Override
	public boolean visit(WildcardType node) {
		// we shouldn't have to do anything
		return false;
	}

	/**
	 * @see ASTVisitor#visit(WhileStatement)
	 */
	@Override
	public boolean visit(WhileStatement node) {
		if (!isActive()) {
			return false;
		}

		push(new NoOp(fCounter));
		return true;
	}

	// --------------------------

	private int getTypeId(Expression expression) {
		ITypeBinding typeBinding = expression.resolveTypeBinding();
		if (typeBinding == null) {
			return Instruction.T_undefined;
		}
		String typeName = typeBinding.getQualifiedName();
		if (typeBinding.isPrimitive()) {
			return getPrimitiveTypeId(typeName);
		} else if ("java.lang.String".equals(typeName)) { //$NON-NLS-1$
			return Instruction.T_String;
		} else {
			return Instruction.T_Object;
		}
	}

	private int getUnBoxedTypeId(Expression expression) {
		ITypeBinding typeBinding = expression.resolveTypeBinding();
		if (typeBinding == null) {
			return Instruction.T_undefined;
		}
		String typeName = typeBinding.getQualifiedName();
		if (typeBinding.isPrimitive()) {
			return getPrimitiveTypeId(typeName);
		} else if ("java.lang.String".equals(typeName)) { //$NON-NLS-1$
			return Instruction.T_String;
		} else {
			// un-boxing
			if ("java.lang.Integer".equals(typeName)) { //$NON-NLS-1$
				return Instruction.T_int;
			} else if ("java.lang.Character".equals(typeName)) { //$NON-NLS-1$
				return Instruction.T_char;
			} else if ("java.lang.Byte".equals(typeName)) { //$NON-NLS-1$
				return Instruction.T_byte;
			} else if ("java.lang.Short".equals(typeName)) { //$NON-NLS-1$
				return Instruction.T_short;
			} else if ("java.lang.Long".equals(typeName)) { //$NON-NLS-1$
				return Instruction.T_long;
			} else if ("java.lang.Float".equals(typeName)) { //$NON-NLS-1$
				return Instruction.T_float;
			} else if ("java.lang.Double".equals(typeName)) { //$NON-NLS-1$
				return Instruction.T_double;
			} else if ("java.lang.Boolean".equals(typeName)) { //$NON-NLS-1$
				return Instruction.T_boolean;
			}
			return Instruction.T_Object;
		}
	}

	private int getTypeId(Type type) {
		if (type.isPrimitiveType()) {
			return getPrimitiveTypeId(((PrimitiveType) type)
					.getPrimitiveTypeCode().toString());
		} else if (type.isSimpleType()) {
			SimpleType simpleType = (SimpleType) type;
			if ("java.lang.String".equals(simpleType.getName().getFullyQualifiedName())) { //$NON-NLS-1$
				return Instruction.T_String;
			}
			return Instruction.T_Object;
		} else if (type.isArrayType()) {
			return Instruction.T_Object;
		} else if (type.isParameterizedType()) {
			return Instruction.T_Object;
		} else {
			return Instruction.T_undefined;
		}

	}

	public static String removePrefixZerosAndUnderscores(String tokenString,
			boolean isLong) {
		char[] token = tokenString.toCharArray();
		int max = token.length;
		int start = 0;
		int end = max - 1;
		if (isLong) {
			end--; // remove the 'L' or 'l'
		}
		if (max > 1 && token[0] == '0') {
			if (max > 2 && (token[1] == 'x' || token[1] == 'X')) {
				start = 2;
			} else if (max > 2 && (token[1] == 'b' || token[1] == 'B')) {
				start = 2;
			} else {
				start = 1;
			}
		}
		boolean modified = false;
		boolean ignore = true;
		loop: for (int i = start; i < max; i++) {
			char currentChar = token[i];
			switch (currentChar) {
			case '0':
				// this is a prefix '0'
				if (ignore && !modified && (i < end)) {
					modified = true;
				}
				break;
			case '_':
				modified = true;
				break loop;
			default:
				ignore = false;
			}
		}
		if (!modified) {
			return tokenString;
		}
		ignore = true;
		StringBuilder buffer = new StringBuilder();
		buffer.append(token, 0, start);
		loop: for (int i = start; i < max; i++) {
			char currentChar = token[i];
			switch (currentChar) {
			case '0':
				if (ignore && (i < end)) {
					// this is a prefix '0'
					continue loop;
				}
				break;
			case '_':
				continue loop;
			default:
				ignore = false;
			}
			buffer.append(currentChar);
		}
		return buffer.toString();
	}

	/**
	 * Returns the method signature given the binding and the enclosing type
	 * signature (if there is one)
	 *
	 * @param methodBinding
	 *            the binding to get the signature for
	 * @param enclosingTypeSignature
	 *            the enclosing type signature or <code>null</code>
	 * @return the method signature for the given binding and enclosing type
	 *         signature
	 */
	private String getMethodSignature(IMethodBinding methodBinding,
			String enclosingTypeSignature) {
		methodBinding = methodBinding.getMethodDeclaration();
		ITypeBinding[] parameterTypes = methodBinding.getParameterTypes();
		int offset = 0;
		int argCount;
		String[] parameterSignatures;
		if (enclosingTypeSignature == null) {
			argCount = parameterTypes.length;
			parameterSignatures = new String[argCount];
		} else {
			offset = 1;
			argCount = parameterTypes.length + 1;
			parameterSignatures = new String[argCount];
			parameterSignatures[0] = enclosingTypeSignature;
		}
		for (int i = 0; i < parameterTypes.length; i++) {
			parameterSignatures[i + offset] = getTypeSignature(parameterTypes[i]);
		}
		String signature = Signature.createMethodSignature(parameterSignatures,
				getTypeSignature(methodBinding.getReturnType()));
		return signature;
	}

	private int getPrimitiveTypeId(String typeName) {
		switch (typeName.charAt(0)) {
		case 'b': // byte or boolean
			switch (typeName.charAt(1)) {
			case 'o': // boolean;
				return Instruction.T_boolean;
			case 'y': // byte
				return Instruction.T_byte;
			}
			break;
		case 'c': // char
			return Instruction.T_char;
		case 'd': // double
			return Instruction.T_double;
		case 'f': // float
			return Instruction.T_float;
		case 'i': // int
			return Instruction.T_int;
		case 'l': // long
			return Instruction.T_long;
		case 'n':
			return Instruction.T_null;
		case 's': // short
			return Instruction.T_short;
		case 'v': // void
			return Instruction.T_void;
		}
		return Instruction.T_undefined;
	}

	/**
	 * Resolves and returns the type binding from the given expression reporting
	 * an error if the binding is <code>null</code>.
	 *
	 * @param expression
	 *            expression to resolve type binding for
	 * @return type binding or <code>null</code> if not available
	 */
	private ITypeBinding resolveTypeBinding(Expression expression) {
		ITypeBinding typeBinding = expression.resolveTypeBinding();
		if (typeBinding == null) {
			setHasError(true);
			addErrorMessage(MessageFormat.format(
					EvaluationEngineMessages.ASTInstructionCompiler_3,
					new Object[] { expression.toString() }));
		}
		return typeBinding;
	}

	/**
	 * Resolves and returns the type binding for the give type reporting an
	 * error if the binding is <code>null</code>.
	 *
	 * @param type
	 *            type to resolve binding for
	 * @return type binding or <code>null</code> if not available
	 */
	private ITypeBinding resolveTypeBinding(Type type) {
		ITypeBinding typeBinding = type.resolveBinding();
		if (typeBinding == null) {
			setHasError(true);
			addErrorMessage(MessageFormat.format(
					EvaluationEngineMessages.ASTInstructionCompiler_3,
					new Object[] { type.toString() }));
		}
		return typeBinding;
	}

	/**
	 * Resolves and returns the binding for the given name reporting an error if
	 * the binding is <code>null</code>.
	 *
	 * @param name
	 *            name to resolve binding for
	 * @return binding or <code>null</code> if not available
	 */
	private IBinding resolveBinding(Name name) {
		IBinding binding = name.resolveBinding();
		if (binding == null) {
			setHasError(true);
			addErrorMessage(MessageFormat.format(
					EvaluationEngineMessages.ASTInstructionCompiler_5,
					new Object[] { name.getFullyQualifiedName() }));
		}
		return binding;
	}

	/**
	 * Resolves and returns the type binding for the given name reporting an
	 * error if the binding is <code>null</code>.
	 *
	 * @param name
	 *            name to resolve type binding for
	 * @return type binding or <code>null</code> if not available
	 */
	private ITypeBinding resolveTypeBinding(Name name) {
		ITypeBinding typeBinding = name.resolveTypeBinding();
		if (typeBinding == null) {
			setHasError(true);
			addErrorMessage(MessageFormat.format(
					EvaluationEngineMessages.ASTInstructionCompiler_3,
					new Object[] { name.getFullyQualifiedName() }));
		}
		return typeBinding;
	}
}
